diff --git a/src/main.js b/src/main.js
index b7d61f5b..65c971d2 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.1',
+ major: 4, minor: 0, revision: 0, extra: '-rc15.2',
commit: __git_commit__,
build: __webpack_hash__,
toString: () =>
diff --git a/src/sites/twitch-twilight/modules/chat/rich_content.jsx b/src/sites/twitch-twilight/modules/chat/rich_content.jsx
index c6f42f4e..622dd2be 100644
--- a/src/sites/twitch-twilight/modules/chat/rich_content.jsx
+++ b/src/sites/twitch-twilight/modules/chat/rich_content.jsx
@@ -75,24 +75,20 @@ export default class RichContent extends Module {
}
renderCardImage() {
- return (
-
- {this.state.error ?
- (

) :
- (
+ return (
+ {this.state.error ?
+ (

) :
+ (
+
+
{this.state.loaded && this.state.image ?
- (

)
+ (

)
: null}
- )}
-
+
+
)}
)
}
diff --git a/src/sites/twitch-twilight/modules/css_tweaks/index.js b/src/sites/twitch-twilight/modules/css_tweaks/index.js
index 146c1f5f..ebcff7d4 100644
--- a/src/sites/twitch-twilight/modules/css_tweaks/index.js
+++ b/src/sites/twitch-twilight/modules/css_tweaks/index.js
@@ -8,9 +8,6 @@ import Module from 'utilities/module';
import {ManagedStyle} from 'utilities/dom';
import {has} from 'utilities/object';
-
-const PORTRAIT_ROUTES = ['user', 'video', 'user-video', 'user-clip', 'user-videos', 'user-clips', 'user-collections', 'user-events', 'user-followers', 'user-following']
-
const CLASSES = {
'top-discover': '.top-nav__nav-link[data-a-target="discover-link"]',
'side-nav': '.side-nav',
@@ -53,87 +50,6 @@ export default class CSSTweaks extends Module {
// Layout
- this.settings.add('layout.portrait', {
- default: false,
- ui: {
- path: 'Appearance > Layout >> Channel',
- title: 'Enable Portrait Mode',
- description: 'In Portrait Mode, chat will be displayed beneath the player when the window is taller than it is wide.',
- component: 'setting-check-box'
- }
- });
-
- this.settings.add('layout.portrait-threshold', {
- default: 1.25,
- ui: {
- path: 'Appearance > Layout >> Channel',
- title: 'Portrait Mode Threshold',
- description: 'This is the Width to Height ratio at which point Portrait Mode will begin to activate.',
- component: 'setting-text-box',
- process(val) {
- val = parseFloat(val, 10)
- if ( isNaN(val) || ! isFinite(val) || val <= 0 )
- return 1.25;
-
- return val;
- }
- }
- })
-
- this.settings.add('layout.use-portrait', {
- requires: ['layout.portrait', 'layout.portrait-threshold', 'context.ui.rightColumnExpanded', 'context.route.name', 'context.size'],
- process(ctx) {
- const size = ctx.get('context.size');
- if ( ! size || ! ctx.get('layout.portrait') || ! ctx.get('context.ui.rightColumnExpanded') || ! PORTRAIT_ROUTES.includes(ctx.get('context.route.name')) )
- return false;
-
- const ratio = size.width / size.height;
- return ratio <= ctx.get('layout.portrait-threshold');
- },
- changed: val => this.toggle('portrait', val)
- });
-
- this.settings.add('layout.portrait-extra-height', {
- requires: ['context.new_channel', 'context.hosting', 'context.ui.theatreModeEnabled', 'player.theatre.no-whispers', 'whispers.show', 'layout.minimal-navigation'],
- process(ctx) {
- let height = 0;
- if ( ctx.get('context.ui.theatreModeEnabled') ) {
- if ( ctx.get('layout.minimal-navigation') )
- height += 1;
-
- if ( ctx.get('whispers.show') && ! ctx.get('player.theatre.no-whispers') )
- height += 4;
-
- } else {
- height = ctx.get('layout.minimal-navigation') ? 1 : 5;
- if ( ctx.get('whispers.show') )
- height += 4;
-
- height += ctx.get('context.new_channel') ? 1 : 5;
-
- if ( ctx.get('context.hosting') )
- height += 4;
- }
-
- return `${height}rem`;
- },
-
- changed: val => this.setVariable('portrait-extra-height', val)
- })
-
- this.settings.add('layout.portrait-extra-width', {
- require: ['layout.side-nav.show', 'context.ui.theatreModeEnabled', 'context.ui.sideNavExpanded'],
- process(ctx) {
- if ( ! ctx.get('layout.side-nav.show') || ctx.get('context.ui.theatreModeEnabled') )
- return '0px';
-
- return ctx.get('context.ui.sideNavExpanded') ? '24rem' : '5rem'
- },
-
- changed: val => this.setVariable('portrait-extra-width', val)
- });
-
-
this.settings.add('layout.side-nav.show', {
default: true,
ui: {
@@ -295,7 +211,6 @@ export default class CSSTweaks extends Module {
this.toggle('swap-sidebars', this.settings.get('layout.swap-sidebars'));
this.toggle('minimal-navigation', this.settings.get('layout.minimal-navigation'));
this.toggle('theatre-nav', this.settings.get('layout.theatre-navigation'));
- this.toggle('portrait', this.settings.get('layout.use-portrait'));
this.toggle('hide-side-nav-avatars', ! this.settings.get('layout.side-nav.show-avatars'));
this.toggleHide('side-nav', !this.settings.get('layout.side-nav.show'));
@@ -312,9 +227,6 @@ export default class CSSTweaks extends Module {
this.toggleHide('side-closed-friends', friends === 2);
this.toggleHide('whispers', !this.settings.get('whispers.show'));
-
- this.setVariable('portrait-extra-width', this.settings.get('layout.portrait-extra-width'))
- this.setVariable('portrait-extra-height', this.settings.get('layout.portrait-extra-height'))
}
toggleHide(key, val) {
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 49a79eae..38a0a42b 100644
--- a/src/sites/twitch-twilight/modules/css_tweaks/styles/portrait.scss
+++ b/src/sites/twitch-twilight/modules/css_tweaks/styles/portrait.scss
@@ -26,7 +26,7 @@
}
.whispers--theatre-mode {
- bottom: 5rem !important;
+ bottom: 0 !important;
right: 0 !important;
}
diff --git a/src/sites/twitch-twilight/modules/layout.js b/src/sites/twitch-twilight/modules/layout.js
new file mode 100644
index 00000000..81ab0273
--- /dev/null
+++ b/src/sites/twitch-twilight/modules/layout.js
@@ -0,0 +1,174 @@
+'use strict';
+
+// ============================================================================
+// Layout Overrides for Twitch Twilight
+// ============================================================================
+
+import Module from 'utilities/module';
+
+const PORTRAIT_ROUTES = ['user', 'video', 'user-video', 'user-clip', 'user-videos', 'user-clips', 'user-collections', 'user-events', 'user-followers', 'user-following'];
+
+export default class Layout extends Module {
+ constructor(...args) {
+ super(...args);
+
+ this.should_enable = true;
+
+ this.inject('settings');
+ this.inject('site.fine');
+ this.inject('site.css_tweaks');
+
+ this.RightColumn = this.fine.define(
+ 'tw-rightcolumn',
+ n => n.hideOnBreakpoint && n.onTheatreMouseMove
+ );
+
+ this.settings.add('layout.portrait', {
+ default: false,
+ ui: {
+ path: 'Appearance > Layout >> Channel',
+ title: 'Enable Portrait Mode',
+ description: 'In Portrait Mode, chat will be displayed beneath the player when the window is taller than it is wide.',
+ component: 'setting-check-box'
+ }
+ });
+
+ this.settings.add('layout.portrait-threshold', {
+ default: 1.25,
+ ui: {
+ path: 'Appearance > Layout >> Channel',
+ title: 'Portrait Mode Threshold',
+ description: 'This is the Width to Height ratio at which point Portrait Mode will begin to activate.',
+ component: 'setting-text-box',
+ process(val) {
+ val = parseFloat(val, 10)
+ if ( isNaN(val) || ! isFinite(val) || val <= 0 )
+ return 1.25;
+
+ return val;
+ }
+ }
+ })
+
+ this.settings.add('layout.use-portrait', {
+ requires: ['layout.portrait', 'layout.portrait-threshold', 'context.route.name', 'context.size'],
+ process(ctx) {
+ const size = ctx.get('context.size');
+ if ( ! size || ! ctx.get('layout.portrait') || ! PORTRAIT_ROUTES.includes(ctx.get('context.route.name')) )
+ return false;
+
+ const ratio = size.width / size.height;
+ return ratio <= ctx.get('layout.portrait-threshold');
+ },
+ changed: val => {
+ this.css_tweaks.toggle('portrait', val);
+ this.updatePortraitMode();
+ }
+ });
+
+ this.settings.add('layout.show-portrait-chat', {
+ requires: ['layout.use-portrait', 'layout.portrait-extra-height', 'layout.portrait-extra-width'],
+ process() {
+ // TODO: Calculate this based on the expected player height.
+ return true;
+ },
+ changed: () => this.updatePortraitMode()
+ });
+
+ this.settings.add('layout.portrait-extra-height', {
+ requires: ['context.new_channel', 'context.hosting', 'context.ui.theatreModeEnabled', 'player.theatre.no-whispers', 'whispers.show', 'layout.minimal-navigation'],
+ process(ctx) {
+ let height = 0;
+ if ( ctx.get('context.ui.theatreModeEnabled') ) {
+ if ( ctx.get('layout.minimal-navigation') )
+ height += 1;
+
+ if ( ctx.get('whispers.show') && ! ctx.get('player.theatre.no-whispers') )
+ height += 4;
+
+ } else {
+ height = ctx.get('layout.minimal-navigation') ? 1 : 5;
+ if ( ctx.get('whispers.show') )
+ height += 4;
+
+ height += ctx.get('context.new_channel') ? 1 : 5;
+
+ if ( ctx.get('context.hosting') )
+ height += 4;
+ }
+
+ return height;
+ },
+
+ changed: val => this.css_tweaks.setVariable('portrait-extra-height', `${val}rem`)
+ })
+
+ this.settings.add('layout.portrait-extra-width', {
+ require: ['layout.side-nav.show', 'context.ui.theatreModeEnabled', 'context.ui.sideNavExpanded'],
+ process(ctx) {
+ if ( ! ctx.get('layout.side-nav.show') || ctx.get('context.ui.theatreModeEnabled') )
+ return 0;
+
+ return ctx.get('context.ui.sideNavExpanded') ? 24 : 5
+ },
+
+ changed: val => this.css_tweaks.setVariable('portrait-extra-width', `${val}rem`)
+ });
+ }
+
+ onEnable() {
+ this.css_tweaks.toggle('portrait', this.settings.get('layout.use-portrait'));
+ 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`);
+
+ const t = this;
+ this.RightColumn.ready((cls, instances) => {
+ cls.prototype.ffzHideOnBreakpoint = function() {
+ try {
+ if ( ! this.containerRef )
+ return;
+
+ if ( ! t.settings.get('layout.use-portrait') )
+ return this.oldHideOnBreakpoint ? this.oldHideOnBreakpoint() : null;
+
+ const should_show = t.settings.get('layout.show-portrait-chat'),
+ is_showing = this.props.rightColumnExpandedByBreakpoint;
+
+ if ( should_show && ! is_showing ) {
+ this.containerRef.style.display = '';
+ this.props.expandRightColumnFromBreakpoint();
+
+ } else if ( ! should_show && is_showing ) {
+ this.containerRef.style.display = 'none';
+ this.props.collapseRightColumnFromBreakpoint();
+ }
+ } catch(err) {
+ if ( this.oldHideOnBreakpoint )
+ this.oldHideOnBreakpoint();
+
+ t.log.capture(err);
+ }
+ }
+
+ cls.prototype.ffzInstall = function() {
+ if ( this.oldHideOnBreakpoint )
+ return;
+
+ this.oldHideOnBreakpoint = this.hideOnBreakpoint;
+ this.hideOnBreakpoint = () => this.ffzHideOnBreakpoint();
+ }
+
+ for(const inst of instances) {
+ window.removeEventListener('resize', inst.hideOnBreakpoint);
+ inst.ffzInstall();
+ window.addEventListener('resize', inst.hideOnBreakpoint);
+ inst.hideOnBreakpoint();
+ }
+ });
+ }
+
+ updatePortraitMode() {
+ for(const inst of this.RightColumn.instances)
+ inst.hideOnBreakpoint();
+ }
+}
\ No newline at end of file