var FFZ = window.FrankerFaceZ, utils = require('../utils'); // -------------------- // Settings // -------------------- FFZ.settings_info.portrait_mode = { type: "select", options: { 0: "Disabled", 1: "Automatic (Use Window Aspect Ratio)", 2: "Always On", 3: "Automatic (Video Below)", 4: "Always On (Video Below)" }, value: 0, process_value: function(val) { if ( val === false ) return 0; if ( val === true ) return 1; if ( typeof val === "string" ) return parseInt(val) || 0; return val; }, category: "Appearance", no_mobile: true, no_bttv: true, name: "Portrait Mode (Chat Below Video)", help: "Display the right sidebar beneath (or above) the video player for viewing in portrait orientations.", on_update: function(val) { if ( this.has_bttv ) return; var Layout = utils.ember_lookup('service:layout'); if ( ! Layout ) return; Layout.set('rawPortraitMode', val); this._fix_menu_position(); } } FFZ.settings_info.portrait_warning = { value: false, visible: false } FFZ.settings_info.swap_sidebars = { type: "boolean", value: false, category: "Sidebar", no_mobile: true, no_bttv: true, name: "Swap Sidebar Positions", help: "Swap the positions of the left and right sidebars, placing chat on the left.", on_update: function(val) { if ( this.has_bttv ) return; document.body.classList.toggle("ffz-sidebar-swap", val); this._fix_menu_position(); } }; FFZ.settings_info.flip_dashboard = { type: "boolean", value: false, category: "Dashboard", no_mobile: true, no_bttv: true, name: "Swap Column Positions", help: "Swap the positions of the left and right columns of the dashboard.", on_update: function(val) { if ( this.has_bttv ) return; document.body.classList.toggle("ffz-flip-dashboard", val); } }; FFZ.settings_info.right_column_width = { type: "button", value: 340, category: "Appearance", no_mobile: true, no_bttv: true, name: "Right Sidebar Width", help: "Set the width of the right sidebar for chat.", method: function() { var f = this, old_val = this.settings.right_column_width || 340; utils.prompt("Right Sidebar Width", "Please enter a new width for the right sidebar, in pixels.
Minimum: 250
Default: 340", old_val, function(new_val) {
if ( new_val === null || new_val === undefined )
return;
var width = parseInt(new_val);
if ( ! width || Number.isNaN(width) || ! Number.isFinite(width) )
width = 340;
f.settings.set('right_column_width', Math.max(250, width));
});
},
on_update: function(val) {
if ( this.has_bttv )
return;
var Layout = utils.ember_lookup('service:layout');
if ( ! Layout )
return;
Layout.set('rightColumnWidth', val);
Ember.propertyDidChange(Layout, 'contentWidth');
}
};
FFZ.settings_info.minimal_channel_title = {
type: "boolean",
value: false,
category: "Appearance",
no_mobile: true,
no_bttv: true,
name: "Minimal Channel Title",
help: "Hide the channel's name and current game when viewing a channel to maximize player size.",
on_update: function(val) {
if ( this.has_bttv )
return;
var Layout = utils.ember_lookup('service:layout');
if ( ! Layout )
return;
document.body.classList.toggle('ffz-minimal-channel-title', val);
Ember.propertyDidChange(Layout, 'windowHeight');
}
}
// --------------------
// Initialization
// --------------------
FFZ.prototype.setup_layout = function() {
if ( this.has_bttv )
return;
document.body.classList.toggle("ffz-sidebar-swap", this.settings.swap_sidebars);
document.body.classList.toggle('ffz-minimal-channel-title', this.settings.minimal_channel_title);
this.log("Creating layout style element.");
var s = this._layout_style = document.createElement('style');
s.id = 'ffz-layout-css';
document.head.appendChild(s);
var Layout = utils.ember_lookup('service:layout'),
f = this;
if ( ! Layout )
return this.log("Unable to locate the Ember service:layout");
this.log("Hooking the Ember service:layout");
Layout.reopen({
rightColumnWidth: 340,
rawPortraitMode: 0,
portraitVideoBelow: false,
portraitMode: function() {
var raw = this.get("rawPortraitMode");
this.set('portraitVideoBelow', raw === 3 || raw === 4);
if ( raw === 0 )
return false;
if ( raw === 2 || raw === 4 )
return true;
// Not sure if I should be adding some other value to offset the ratio. What feels best?
var ratio = this.get("windowWidth") / (this.get("windowHeight") + 120 + 60);
return ratio < 1;
}.property("rawPortraitMode", "windowHeight", "windowWidth"),
isTooSmallForRightColumn: function() {
if ( ! f.has_bttv && this.get('portraitMode') ) {
var size = this.get('playerSize'),
height = size[1];
// Make sure we have at least a bit of room for the chat.
return this.get("windowHeight") < (height + 120 + 60 + 200);
} else
return this.get("windowWidth") < (1090 - this.get('rightColumnWidth'))
}.property("windowWidth", "rightColumnWidth", "playerSize", "windowHeight"),
contentWidth: function() {
var left_width = this.get("isLeftColumnClosed") ? 50 : 240,
right_width = ! f.has_bttv && this.get('portraitMode') ? 0 : this.get("isRightColumnClosed") ? 0 : this.get("rightColumnWidth");
return this.get("windowWidth") - left_width - right_width - 60;
}.property("windowWidth", "portraitMode", "isRightColumnClosed", "isLeftColumnClosed", "rightColumnWidth"),
playerSize: function() {
var h = this.get('windowHeight'),
c = this.get('PLAYER_CONTROLS_HEIGHT'),
r = this.get('contentWidth'),
i = (9 * r / 16) + c,
d = h - (f.settings.minimal_channel_title ? 75 : 120) - 60,
c = h - 94 - 185,
l = Math.floor(r),
o = Math.floor(Math.min(i, d)),
s = Math.floor(Math.min(i, c));
return [l, o, s];
}.property("contentWidth", "windowHeight", "portraitMode", "PLAYER_CONTROLS_HEIGHT"),
playerStyle: function() {
var size = this.get('playerSize'),
width = size[0],
height = size[1],
host_height = size[2];
return "";
}.property("playerSize"),
ffzPortraitWarning: function() {
var t = this;
// Delay this, in case we're just resizing the window.
setTimeout(function() {
if ( ! f.settings.portrait_mode || f._portrait_warning || f.settings.portrait_warning || document.body.getAttribute('data-current-path').indexOf('user.') !== 0 || ! t.get('isTooSmallForRightColumn') )
return;
f._portrait_warning = true;
f.show_message('Twitch\'s Chat Sidebar has been hidden as a result of FrankerFaceZ\'s Portrait Mode because the window is too wide.
Please disable Portrait Mode or make your window narrower.
Do not show this message again');
}, 50);
}.observes("isTooSmallForRightColumn"),
ffzUpdateCss: function() {
var window_height = this.get('windowHeight'),
window_width = this.get('windowWidth'),
out = 'body.ffz-small-player #player .dynamic-player {' +
'position: fixed;' +
'z-index: 9;' +
'box-shadow: 0 0 20px 0 black;';
if ( .25 * window_width >= .5 * window_height )
out += 'width: 25vw !important; height: 14.0625vw !important;';
else
out += 'width: 50vh !important; height: 28.125vh !important;';
if ( ! f.has_bttv ) {
if ( this.get('isRightColumnClosed') )
out += 'top: 0; right: 0}';
else {
if ( this.get('portraitMode') ) {
var size = this.get('playerSize'),
video_below = this.get('portraitVideoBelow'),
video_height = size[1] + (f.settings.minimal_channel_title ? 75 : 120) + 60,
chat_height = window_height - video_height,
video_top = video_below ? chat_height : 0,
chat_top = video_below ? 0 : video_height,
theatre_video_height = Math.floor(Math.max(window_height * 0.1, Math.min(window_height - 300, 9 * window_width / 16))),
theatre_chat_height = window_height - theatre_video_height,
theatre_video_top = video_below ? theatre_chat_height : 0,
theatre_chat_top = video_below ? 0 : theatre_video_height;
out += 'top: ' + video_top + 'px;right: 0}' +
'body[data-current-path^="user."] #left_col .warp { min-height: inherit }' +
'body[data-current-path^="user."] #left_col { overflow: hidden }' +
'body[data-current-path^="user."] #left_col .warp,' +
'body[data-current-path^="user."] #left_col,' +
'body[data-current-path^="user."]:not(.ffz-sidebar-swap) #main_col{' +
'margin-right:0 !important;' +
'top:' + video_top + 'px;' +
'height:' + video_height + 'px}' +
'body[data-current-path^="user."].ffz-sidebar-swap #main_col{' +
'margin-left:0 !important;' +
'top:' + video_top + 'px;' +
'height:' + video_height + 'px}' +
'body[data-current-path^="user."] #right_col{' +
'width:100%;' +
'top:' + chat_top + 'px;' +
'height:' + chat_height + 'px}' +
'body[data-current-path^="user."] .app-main.theatre #left_col .warp,' +
'body[data-current-path^="user."] .app-main.theatre #left_col,' +
'body[data-current-path^="user."] .app-main.theatre #main_col{' +
'top:' + theatre_video_top + 'px;' +
'height:' + theatre_video_height + 'px}' +
'body[data-current-path^="user."] .app-main.theatre #right_col{' +
'top:' + theatre_chat_top + 'px;' +
'height:' + theatre_chat_height + 'px}';
} else {
var width = this.get('rightColumnWidth');
out += 'top: 0; right: ' + width + 'px}' +
'#main_col.expandRight #right_close{left: none !important}' +
'#right_col{width:' + width + 'px}' +
'body:not(.ffz-sidebar-swap) #main_col:not(.expandRight){' +
'margin-right:' + width + 'px}' +
'body.ffz-sidebar-swap .theatre #main_col:not(.expandRight),' +
'body.ffz-sidebar-swap #main_col:not(.expandRight){' +
'margin-left:' + width + 'px}';
}
}
f._layout_style.innerHTML = out;
}
}.observes("isRightColumnClosed", "playerSize", "rightColumnWidth", "portraitMode", "windowHeight", "windowWidth"),
ffzUpdatePlayerStyle: function() {
Ember.propertyDidChange(Layout, 'playerStyle');
}.observes('windowHeight', 'windowWidth'),
ffzUpdatePortraitCSS: function() {
var portrait = this.get("portraitMode");
document.body.classList.toggle("ffz-portrait", ! f.has_bttv && portrait);
}.observes("portraitMode"),
ffzFixTabs: function() {
if ( f.settings.group_tabs && f._chatv && f._chatv._ffz_tabs ) {
setTimeout(function() {
var cr = f._chatv && f._chatv.$('.chat-room');
cr && cr.css && cr.css('top', f._chatv._ffz_tabs.offsetHeight + "px");
},0);
}
}.observes("isRightColumnClosed", "rightColumnWidth", "portraitMode", "playerSize")
});
// Force the layout to update.
Layout.set('rightColumnWidth', this.settings.right_column_width);
Layout.set('rawPortraitMode', this.settings.portrait_mode);
// Force re-calculation of everything.
Ember.propertyDidChange(Layout, 'windowWidth');
Ember.propertyDidChange(Layout, 'windowHeight');
Layout.ffzUpdatePortraitCSS();
}