2019-03-19 15:03:43 -04:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
// Layout Overrides for Twitch Twilight
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
import Module from 'utilities/module';
|
2019-06-06 16:33:14 -04:00
|
|
|
import {has} from 'utilities/object';
|
2019-03-19 15:03:43 -04:00
|
|
|
|
|
|
|
const PORTRAIT_ROUTES = ['user', 'video', 'user-video', 'user-clip', 'user-videos', 'user-clips', 'user-collections', 'user-events', 'user-followers', 'user-following'];
|
2019-08-09 14:24:26 -04:00
|
|
|
const MINIMAL_ROUTES = ['popout', 'embed-chat', 'dash-chat'];
|
2019-03-19 15:03:43 -04:00
|
|
|
|
|
|
|
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');
|
|
|
|
|
2019-11-14 19:52:35 -05:00
|
|
|
/*this.TopNav = this.fine.define(
|
2019-09-28 23:52:50 -04:00
|
|
|
'top-nav',
|
|
|
|
n => n.computeStyles && n.navigationLinkSize
|
2019-11-14 19:52:35 -05:00
|
|
|
);*/
|
2019-09-28 23:52:50 -04:00
|
|
|
|
2019-10-28 01:06:02 -04:00
|
|
|
/*this.RightColumn = this.fine.define(
|
2019-03-19 15:03:43 -04:00
|
|
|
'tw-rightcolumn',
|
2019-04-18 03:16:19 -04:00
|
|
|
n => n.hideOnBreakpoint && n.handleToggleVisibility
|
2019-10-28 01:06:02 -04:00
|
|
|
);*/
|
2019-06-06 16:33:14 -04:00
|
|
|
|
2019-10-23 17:49:01 -05:00
|
|
|
this.SideBarChannels = this.fine.define(
|
|
|
|
'nav-cards',
|
|
|
|
t => t.getCardSlideInContent && t.props && has(t.props, 'tooltipContent')
|
|
|
|
);
|
|
|
|
|
2019-03-19 15:03:43 -04:00
|
|
|
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'
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-06-17 15:32:38 -04:00
|
|
|
this.settings.add('layout.portrait-invert', {
|
|
|
|
default: false,
|
|
|
|
ui: {
|
|
|
|
path: 'Appearance > Layout >> Channel',
|
|
|
|
title: 'When in portrait mode, place chat at the top.',
|
|
|
|
component: 'setting-check-box'
|
|
|
|
},
|
|
|
|
changed: val => document.body.classList.toggle('ffz--portrait-invert', val)
|
|
|
|
});
|
|
|
|
|
2019-03-19 15:03:43 -04:00
|
|
|
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', {
|
2020-09-29 14:15:43 -04:00
|
|
|
requires: ['layout.portrait', 'layout.portrait-threshold', 'context.route.name', 'context.size', 'context.isWatchParty'],
|
2019-03-19 15:03:43 -04:00
|
|
|
process(ctx) {
|
2020-09-29 14:15:43 -04:00
|
|
|
if ( ctx.get('context.isWatchParty') )
|
|
|
|
return false;
|
|
|
|
|
2019-03-19 15:03:43 -04:00
|
|
|
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');
|
|
|
|
},
|
2019-05-16 14:46:26 -04:00
|
|
|
changed: () => this.updatePortraitMode()
|
2019-03-19 15:03:43 -04:00
|
|
|
});
|
|
|
|
|
2019-04-05 18:04:14 -04:00
|
|
|
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)
|
|
|
|
});
|
|
|
|
|
2019-11-25 17:50:20 -05:00
|
|
|
this.settings.add('layout.use-portrait-meta', {
|
|
|
|
requires: ['layout.inject-portrait', 'player.theatre.metadata'],
|
|
|
|
process(ctx) {
|
|
|
|
return ctx.get('layout.inject-portrait') && ctx.get('player.theatre.metadata')
|
|
|
|
},
|
|
|
|
changed: val => this.css_tweaks.toggle('portrait-metadata', val)
|
|
|
|
});
|
|
|
|
|
|
|
|
this.settings.add('layout.use-portrait-meta-top', {
|
|
|
|
requires: ['layout.use-portrait-meta', 'layout.portrait-invert'],
|
|
|
|
process(ctx) {
|
|
|
|
return ctx.get('layout.use-portrait-meta') && ! ctx.get('layout.portrait-invert')
|
|
|
|
},
|
|
|
|
changed: val => this.css_tweaks.toggle('portrait-metadata-top', val)
|
|
|
|
});
|
|
|
|
|
2019-03-19 15:03:43 -04:00
|
|
|
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', {
|
2019-05-07 15:04:12 -04:00
|
|
|
requires: ['context.new_channel', 'context.squad_bar', 'context.hosting', 'context.ui.theatreModeEnabled', 'player.theatre.no-whispers', 'whispers.show', 'layout.minimal-navigation'],
|
2019-03-19 15:03:43 -04:00
|
|
|
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;
|
|
|
|
|
2019-05-07 15:04:12 -04:00
|
|
|
if ( ctx.get('context.squad_bar') )
|
|
|
|
height += 6;
|
|
|
|
|
2019-03-19 15:03:43 -04:00
|
|
|
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`)
|
|
|
|
});
|
2019-04-18 03:16:19 -04:00
|
|
|
|
|
|
|
this.settings.add('layout.is-minimal', {
|
|
|
|
require: ['context.route.name'],
|
|
|
|
process(ctx) {
|
|
|
|
return MINIMAL_ROUTES.includes(ctx.get('context.route.name'));
|
|
|
|
}
|
|
|
|
});
|
2019-03-19 15:03:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
onEnable() {
|
2019-06-17 15:32:38 -04:00
|
|
|
document.body.classList.toggle('ffz--portrait-invert', this.settings.get('layout.portrait-invert'));
|
|
|
|
|
2019-09-28 23:52:50 -04:00
|
|
|
this.on(':update-nav', this.updateNavLinks, this);
|
|
|
|
|
2019-04-05 18:04:14 -04:00
|
|
|
this.css_tweaks.toggle('portrait', this.settings.get('layout.inject-portrait'));
|
|
|
|
this.css_tweaks.toggle('portrait-swapped', this.settings.get('layout.use-portrait-swapped'));
|
2019-11-25 17:50:20 -05:00
|
|
|
this.css_tweaks.toggle('portrait-metadata', this.settings.get('layout.use-portrait-meta'));
|
|
|
|
this.css_tweaks.toggle('portrait-metadata-top', this.settings.get('layout.use-portrait-meta-top'));
|
2019-03-19 15:03:43 -04:00
|
|
|
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`);
|
|
|
|
|
2020-07-16 16:34:03 -04:00
|
|
|
this.on('site.directory:update-cards', () => {
|
|
|
|
for(const inst of this.SideBarChannels.instances)
|
|
|
|
this.updateCardClass(inst);
|
|
|
|
});
|
|
|
|
|
2019-10-23 17:49:01 -05:00
|
|
|
this.SideBarChannels.ready((cls, instances) => {
|
|
|
|
for(const inst of instances)
|
|
|
|
this.updateCardClass(inst);
|
|
|
|
});
|
|
|
|
|
|
|
|
this.SideBarChannels.on('mount', this.updateCardClass, this);
|
|
|
|
this.SideBarChannels.on('update', this.updateCardClass, this);
|
|
|
|
|
2019-10-28 01:06:02 -04:00
|
|
|
/*const t = this;
|
2019-03-19 15:03:43 -04:00
|
|
|
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();
|
|
|
|
}
|
2019-10-28 01:06:02 -04:00
|
|
|
});*/
|
2019-03-19 15:03:43 -04:00
|
|
|
}
|
|
|
|
|
2019-04-18 03:16:19 -04:00
|
|
|
get is_minimal() {
|
|
|
|
return this.settings.get('layout.is-minimal')
|
|
|
|
}
|
|
|
|
|
2019-10-23 17:49:01 -05:00
|
|
|
updateCardClass(inst) {
|
|
|
|
const node = this.fine.getChildNode(inst);
|
|
|
|
|
2020-07-16 16:34:03 -04:00
|
|
|
if ( node ) {
|
2019-10-23 17:49:01 -05:00
|
|
|
node.classList.toggle('ffz--side-nav-card-rerun',
|
|
|
|
inst.props?.tooltipContent?.props?.streamType === 'rerun'
|
|
|
|
);
|
2020-07-16 16:34:03 -04:00
|
|
|
node.classList.toggle('ffz--side-nav-card-offline',
|
|
|
|
inst.props?.offline === true
|
|
|
|
);
|
|
|
|
|
|
|
|
const game = inst.props?.tooltipContent?.props?.gameName || inst.props?.metadataLeft?.props?.activity?.stream?.game?.name || inst.props?.metadataLeft;
|
|
|
|
node.classList.toggle('tw-hide', this.settings.provider.get('directory.game.blocked-games', []).includes(game));
|
|
|
|
}
|
2019-10-23 17:49:01 -05:00
|
|
|
}
|
|
|
|
|
2019-09-28 23:52:50 -04:00
|
|
|
updateNavLinks() {
|
2019-11-14 19:52:35 -05:00
|
|
|
|
2019-09-28 23:52:50 -04:00
|
|
|
}
|
|
|
|
|
2019-03-19 15:03:43 -04:00
|
|
|
updatePortraitMode() {
|
2019-12-13 20:14:55 -05:00
|
|
|
|
2019-03-19 15:03:43 -04:00
|
|
|
}
|
|
|
|
}
|