From c43e572eec848ecd6bd5f021b41335fe74201785 Mon Sep 17 00:00:00 2001 From: SirStendec Date: Fri, 5 Apr 2019 18:04:14 -0400 Subject: [PATCH] 4.0.0-rc16 * Added: Closed Captioning settings to override the font family and font size. * Added: Closed Captioning settings to override the position of captions. * Changed: Player settings are no longer located under `Channel` in the settings menu. * Fixed: Portrait Mode not working correctly when collapsing chat when Portrait Mode is active. * Fixed: The button to collapse chat not appearing in the correct position when Portrait Mode and Swapped Sidebars are both active. * Fixed: The button to collapse chat not appearing in Firefox when Swapped Sidebars is active. --- src/main.js | 2 +- .../css_tweaks/styles/portrait-swapped.scss | 5 + .../modules/css_tweaks/styles/portrait.scss | 1 + .../css_tweaks/styles/swap-sidebars.scss | 5 +- src/sites/twitch-twilight/modules/layout.js | 20 +- src/sites/twitch-twilight/modules/player.jsx | 177 ++++++++++++++++-- 6 files changed, 192 insertions(+), 18 deletions(-) create mode 100644 src/sites/twitch-twilight/modules/css_tweaks/styles/portrait-swapped.scss diff --git a/src/main.js b/src/main.js index 33208a22..f06891ad 100644 --- a/src/main.js +++ b/src/main.js @@ -149,7 +149,7 @@ ${typeof x[1] === 'string' ? x[1] : JSON.stringify(x[1], null, 4)}` FrankerFaceZ.Logger = Logger; const VER = FrankerFaceZ.version_info = { - major: 4, minor: 0, revision: 0, extra: '-rc15.4', + major: 4, minor: 0, revision: 0, extra: '-rc16', commit: __git_commit__, build: __webpack_hash__, toString: () => diff --git a/src/sites/twitch-twilight/modules/css_tweaks/styles/portrait-swapped.scss b/src/sites/twitch-twilight/modules/css_tweaks/styles/portrait-swapped.scss new file mode 100644 index 00000000..6897a5c9 --- /dev/null +++ b/src/sites/twitch-twilight/modules/css_tweaks/styles/portrait-swapped.scss @@ -0,0 +1,5 @@ +// Unnecessarily expressive rule to make it more important. +.twilight-root .right-column .right-column__toggle-visibility { + right: unset !important; + left: 0.5rem !important; +} \ No newline at end of file diff --git a/src/sites/twitch-twilight/modules/css_tweaks/styles/portrait.scss b/src/sites/twitch-twilight/modules/css_tweaks/styles/portrait.scss index 38a0a42b..4c4414c8 100644 --- a/src/sites/twitch-twilight/modules/css_tweaks/styles/portrait.scss +++ b/src/sites/twitch-twilight/modules/css_tweaks/styles/portrait.scss @@ -50,6 +50,7 @@ top: 6.5rem; right: .5rem; left: unset !important; + transform: rotate(90deg); } .emote-picker__tab-content { diff --git a/src/sites/twitch-twilight/modules/css_tweaks/styles/swap-sidebars.scss b/src/sites/twitch-twilight/modules/css_tweaks/styles/swap-sidebars.scss index 551253c8..530c213d 100644 --- a/src/sites/twitch-twilight/modules/css_tweaks/styles/swap-sidebars.scss +++ b/src/sites/twitch-twilight/modules/css_tweaks/styles/swap-sidebars.scss @@ -1,6 +1,9 @@ .twilight-main { order: 2 } .side-nav { order: 3 } -.right-column { order: 1 } +.right-column { + order: 1; + z-index: 2; +} .side-nav__toggle-visibility { right: unset !important; diff --git a/src/sites/twitch-twilight/modules/layout.js b/src/sites/twitch-twilight/modules/layout.js index 81ab0273..a38e906c 100644 --- a/src/sites/twitch-twilight/modules/layout.js +++ b/src/sites/twitch-twilight/modules/layout.js @@ -61,11 +61,26 @@ export default class Layout extends Module { return ratio <= ctx.get('layout.portrait-threshold'); }, changed: val => { - this.css_tweaks.toggle('portrait', val); this.updatePortraitMode(); } }); + this.settings.add('layout.inject-portrait', { + requires: ['layout.use-portrait', 'context.ui.rightColumnExpanded'], + process(ctx) { + return ctx.get('layout.use-portrait') && ctx.get('context.ui.rightColumnExpanded'); + }, + changed: val => this.css_tweaks.toggle('portrait', val) + }); + + this.settings.add('layout.use-portrait-swapped', { + requires: ['layout.inject-portrait', 'layout.swap-sidebars'], + process(ctx) { + return ctx.get('layout.inject-portrait') && ctx.get('layout.swap-sidebars') + }, + changed: val => this.css_tweaks.toggle('portrait-swapped', val) + }); + this.settings.add('layout.show-portrait-chat', { requires: ['layout.use-portrait', 'layout.portrait-extra-height', 'layout.portrait-extra-width'], process() { @@ -117,7 +132,8 @@ export default class Layout extends Module { } onEnable() { - this.css_tweaks.toggle('portrait', this.settings.get('layout.use-portrait')); + this.css_tweaks.toggle('portrait', this.settings.get('layout.inject-portrait')); + this.css_tweaks.toggle('portrait-swapped', this.settings.get('layout.use-portrait-swapped')); this.css_tweaks.setVariable('portrait-extra-width', `${this.settings.get('layout.portrait-extra-width')}rem`); this.css_tweaks.setVariable('portrait-extra-height', `${this.settings.get('layout.portrait-extra-height')}rem`); diff --git a/src/sites/twitch-twilight/modules/player.jsx b/src/sites/twitch-twilight/modules/player.jsx index be811991..a0ab1a79 100644 --- a/src/sites/twitch-twilight/modules/player.jsx +++ b/src/sites/twitch-twilight/modules/player.jsx @@ -9,6 +9,8 @@ import {createElement, on, off} from 'utilities/dom'; export const PLAYER_ROUTES = ['front-page', 'user', 'video', 'user-video', 'user-clip', 'user-videos', 'user-clips', 'user-collections', 'user-events', 'user-followers', 'user-following', 'dash']; +const STYLE_VALIDATOR = createElement('span'); + export default class Player extends Module { constructor(...args) { super(...args); @@ -37,7 +39,7 @@ export default class Player extends Module { this.settings.add('player.volume-scroll', { default: false, ui: { - path: 'Channel > Player >> Volume', + path: 'Player > General >> Volume', title: 'Adjust volume by scrolling with the mouse wheel.', description: '*This setting will not work properly on streams with visible extensions when mouse interaction with extensions is allowed.*', component: 'setting-check-box' @@ -52,7 +54,7 @@ export default class Player extends Module { this.settings.add('player.volume-scroll-steps', { default: 0.1, ui: { - path: 'Channel > Player >> Volume', + path: 'Player > General >> Volume', title: 'Volume scroll amount', description: 'How much the volume level is changed per individual scroll input.', component: 'setting-select-box', @@ -65,6 +67,82 @@ export default class Player extends Module { } }); + this.settings.add('player.captions.font-size', { + default: '', + ui: { + path: 'Player > Closed Captioning >> Font', + title: 'Font Size', + description: 'How large should captions be. This can be a percentage, such as `10%`, or a pixel value, such as `50px`.', + component: 'setting-text-box' + }, + changed: () => this.updateCaptionsCSS() + }); + + this.settings.add('player.captions.font-family', { + default: '', + ui: { + path: 'Player > Closed Captioning >> Font', + title: 'Font Family', + description: 'Override the font used for displaying Closed Captions.', + component: 'setting-text-box' + }, + changed: () => this.updateCaptionsCSS() + }); + + this.settings.add('player.captions.custom-position', { + default: false, + ui: { + path: 'Player > Closed Captioning >> Position', + sort: -1, + title: 'Enable overriding the position and alignment of closed captions.', + component: 'setting-check-box' + }, + changed: () => this.updateCaptionsCSS() + }); + + this.settings.add('player.captions.vertical', { + default: '10%', + ui: { + path: 'Player > Closed Captioning >> Position', + title: 'Vertical Position', + component: 'setting-text-box', + description: 'Override the position for Closed Captions. This can be a percentage, such as `10%`, or a pixel value, such as `50px`.' + }, + changed: () => this.updateCaptionsCSS() + }); + + this.settings.add('player.captions.horizontal', { + default: '50%', + ui: { + path: 'Player > Closed Captioning >> Position', + title: 'Horizontal Position', + component: 'setting-text-box', + description: 'Override the position for Closed Captions. This can be a percentage, such as `10%`, or a pixel value, such as `50px`.' + }, + changed: () => this.updateCaptionsCSS() + }); + + this.settings.add('player.captions.alignment', { + default: 32, + ui: { + path: 'Player > Closed Captioning >> Position', + title: 'Alignment', + component: 'setting-select-box', + data: [ + {value: 11, title: 'Top Left'}, + {value: 12, title: 'Top Center'}, + {value: 13, title: 'Top Right'}, + {value: 21, title: 'Middle Left'}, + {value: 22, title: 'Middle Center'}, + {value: 23, title: 'Middle Right'}, + {value: 31, title: 'Bottom Left'}, + {value: 32, title: 'Bottom Center'}, + {value: 33, title: 'Bottom Right'} + ] + }, + changed: () => this.updateCaptionsCSS() + }); + this.settings.add('player.theatre.no-whispers', { default: false, requires: ['whispers.show'], @@ -76,7 +154,7 @@ export default class Player extends Module { }, ui: { - path: 'Channel > Player >> Theatre Mode', + path: 'Player > General >> Theatre Mode', title: 'Hide whispers when Theatre Mode is enabled.', component: 'setting-check-box' }, @@ -86,7 +164,7 @@ export default class Player extends Module { this.settings.add('player.theatre.metadata', { default: false, ui: { - path: 'Channel > Player >> Theatre Mode', + path: 'Player > General >> Theatre Mode', title: 'Show metadata when mousing over the player.', component: 'setting-check-box' }, @@ -97,7 +175,7 @@ export default class Player extends Module { this.settings.add('player.theatre.auto-enter', { default: false, ui: { - path: 'Channel > Player >> Theatre Mode', + path: 'Player > General >> Theatre Mode', title: 'Automatically open Theatre Mode when visiting a channel.', component: 'setting-check-box' } @@ -106,7 +184,7 @@ export default class Player extends Module { this.settings.add('player.ext-hide', { default: 0, ui: { - path: 'Channel > Player >> Extensions', + path: 'Player > General >> Extensions', title: 'Show Overlay Extensions', component: 'setting-select-box', data: [ @@ -121,7 +199,7 @@ export default class Player extends Module { this.settings.add('player.ext-interaction', { default: true, ui: { - path: 'Channel > Player >> Extensions', + path: 'Player > General >> Extensions', title: 'Allow mouse interaction with overlay extensions.', component: 'setting-check-box' }, @@ -131,7 +209,7 @@ export default class Player extends Module { this.settings.add('player.home.autoplay', { default: true, ui: { - path: 'Channel > Player >> Playback', + path: 'Player > General >> Playback', title: 'Auto-play featured broadcasters on the front page.', component: 'setting-check-box' }, @@ -140,7 +218,7 @@ export default class Player extends Module { this.settings.add('player.no-autoplay', { default: false, ui: { - path: 'Channel > Player >> Playback', + path: 'Player > General >> Playback', title: 'Do not automatically start playing videos or streams.', description: 'Note: This feature does not apply when navigating directly from channel to channel.', component: 'setting-check-box' @@ -150,7 +228,7 @@ export default class Player extends Module { this.settings.add('player.vod.autoplay', { default: true, ui: { - path: 'Channel > Player >> Playback', + path: 'Player > General >> Playback', title: 'Auto-play the next recommended video after a video finishes.', component: 'setting-check-box' } @@ -159,7 +237,7 @@ export default class Player extends Module { this.settings.add('player.volume-always-shown', { default: false, ui: { - path: 'Channel > Player >> Volume', + path: 'Player > General >> Volume', title: 'Keep the volume slider expanded at all times.', component: 'setting-check-box' }, @@ -170,7 +248,7 @@ export default class Player extends Module { this.settings.add('player.hide-event-bar', { default: false, ui: { - path: 'Channel > Player >> General', + path: 'Player > General >> General', title: 'Hide Event Bar', description: 'Hide the Event Bar which appears above the player when there is an ongoing event for the current channel.', component: 'setting-check-box' @@ -184,7 +262,7 @@ export default class Player extends Module { this.settings.add('player.hide-rerun-bar', { default: false, ui: { - path: 'Channel > Player >> General', + path: 'Player > General >> General', title: 'Hide Rerun Bar', description: 'Hide the Rerun Bar which appears above the player when the current channel is playing a video rather than live content.', component: 'setting-check-box' @@ -198,7 +276,7 @@ export default class Player extends Module { this.settings.add('player.hide-mouse', { default: true, ui: { - path: 'Channel > Player >> General', + path: 'Player > General >> General', title: "Hide mouse when controls aren't visible.", component: 'setting-check-box' }, @@ -214,6 +292,76 @@ export default class Player extends Module { this.css_tweaks.toggleHide('player-ext', val === 2); } + updateCaptionsCSS() { + // Font + const font_size = this.settings.get('player.captions.font-size'); + let font_family = this.settings.get('player.captions.font-family'); + if ( font_family.indexOf(' ') !== -1 && font_family.indexOf(',') === -1 && font_family.indexOf('"') === -1 && font_family.indexOf("'") === -1 ) + font_family = `"${font_family}"`; + + STYLE_VALIDATOR.style.fontSize = ''; + STYLE_VALIDATOR.style.fontFamily = ''; + + STYLE_VALIDATOR.style.fontSize = font_size; + STYLE_VALIDATOR.style.fontFamily = font_family; + + const font_out = []; + if ( STYLE_VALIDATOR.style.fontFamily ) + font_out.push(`font-family: ${STYLE_VALIDATOR.style.fontFamily} !important;`); + if ( STYLE_VALIDATOR.style.fontSize ) + font_out.push(`font-size: ${STYLE_VALIDATOR.style.fontSize} !important;`); + + if ( font_out.length ) + this.css_tweaks.set('captions-font', `.player-captions { + ${font_out.join('\n\t')} +}`) + else + this.css_tweaks.delete('captions-font'); + + // Position + const enabled = this.settings.get('player.captions.custom-position'), + vertical = this.settings.get('player.captions.vertical'), + horizontal = this.settings.get('player.captions.horizontal'), + alignment = this.settings.get('player.captions.alignment'); + + if ( ! enabled ) { + this.css_tweaks.delete('captions-position'); + return; + } + + const out = [], + align_horizontal = alignment % 10, + align_vertical = Math.floor(alignment / 10); + + let custom_top = false, + custom_left = false; + + STYLE_VALIDATOR.style.top = ''; + STYLE_VALIDATOR.style.top = vertical; + if ( STYLE_VALIDATOR.style.top ) { + out.push(`${align_vertical === 3 ? 'bottom' : 'top'}: ${STYLE_VALIDATOR.style.top} !important;`) + out.push(`${align_vertical === 3 ? 'top' : 'bottom'}: unset !important;`); + custom_top = true; + } + + STYLE_VALIDATOR.style.top = ''; + STYLE_VALIDATOR.style.top = horizontal; + if ( STYLE_VALIDATOR.style.top ) { + out.push(`${align_horizontal === 3 ? 'right' : 'left'}: ${STYLE_VALIDATOR.style.top} !important;`); + out.push(`${align_horizontal === 3 ? 'left' : 'right'}: unset !important;`); + custom_left = true; + } + + if ( align_horizontal !== 2 ) + out.push(`width: unset !important;`); + + out.push(`transform: translate(${(!custom_left || align_horizontal === 2) ? '-50%' : '0'}, ${(!custom_top || align_vertical === 2) ? '-50%' : '0'})`); + + this.css_tweaks.set('captions-position', `.player-captions-container { + ${out.join('\n\t')}; +}`); + } + onEnable() { this.css_tweaks.toggle('player-volume', this.settings.get('player.volume-always-shown')); this.css_tweaks.toggle('player-ext-mouse', !this.settings.get('player.ext-interaction')); @@ -223,6 +371,7 @@ export default class Player extends Module { this.css_tweaks.toggleHide('player-event-bar', this.settings.get('player.hide-event-bar')); this.css_tweaks.toggleHide('player-rerun-bar', this.settings.get('player.hide-rerun-bar')); this.updateHideExtensions(); + this.updateCaptionsCSS(); const t = this;