mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-07-05 10:38:30 +00:00
4.0.0-rc10
* Added: Support for rendering metadata for the new Twitch layout. * Fixed: The option to disable Hosts not working with the new Twitch layout.
This commit is contained in:
parent
44dd04de20
commit
6654fda11d
7 changed files with 495 additions and 88 deletions
|
@ -100,7 +100,7 @@ class FrankerFaceZ extends Module {
|
||||||
FrankerFaceZ.Logger = Logger;
|
FrankerFaceZ.Logger = Logger;
|
||||||
|
|
||||||
const VER = FrankerFaceZ.version_info = {
|
const VER = FrankerFaceZ.version_info = {
|
||||||
major: 4, minor: 0, revision: 0, extra: '-rc9.3',
|
major: 4, minor: 0, revision: 0, extra: '-rc10',
|
||||||
commit: __git_commit__,
|
commit: __git_commit__,
|
||||||
build: __webpack_hash__,
|
build: __webpack_hash__,
|
||||||
toString: () =>
|
toString: () =>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// Channel Metadata
|
// Channel Metadata
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
import {createElement, ClickOutside} from 'utilities/dom';
|
import {createElement, ClickOutside, setChildren} from 'utilities/dom';
|
||||||
import {maybe_call} from 'utilities/object';
|
import {maybe_call} from 'utilities/object';
|
||||||
|
|
||||||
import {duration_to_string} from 'utilities/time';
|
import {duration_to_string} from 'utilities/time';
|
||||||
|
@ -58,10 +58,10 @@ export default class Metadata extends Module {
|
||||||
this.definitions.uptime = {
|
this.definitions.uptime = {
|
||||||
refresh() { return this.settings.get('metadata.uptime') > 0 },
|
refresh() { return this.settings.get('metadata.uptime') > 0 },
|
||||||
|
|
||||||
setup() {
|
setup(data) {
|
||||||
const socket = this.resolve('socket'),
|
const socket = this.resolve('socket'),
|
||||||
apollo = this.resolve('site.apollo'),
|
apollo = this.resolve('site.apollo'),
|
||||||
created_at = apollo.getFromQuery('ChannelPage_ChannelHeader', 'data.user.stream.createdAt');
|
created_at = apollo.getFromQuery(data.legacy ? 'ChannelPage_ChannelHeader' : 'ChannelPage_User', 'data.user.stream.createdAt');
|
||||||
|
|
||||||
if ( ! created_at )
|
if ( ! created_at )
|
||||||
return {};
|
return {};
|
||||||
|
@ -86,6 +86,8 @@ export default class Metadata extends Module {
|
||||||
return duration_to_string(data.uptime, false, false, false, setting !== 2);
|
return duration_to_string(data.uptime, false, false, false, setting !== 2);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
subtitle: () => this.i18n.t('metadata.uptime.subtitle', 'Uptime'),
|
||||||
|
|
||||||
tooltip(data) {
|
tooltip(data) {
|
||||||
if ( ! data.created )
|
if ( ! data.created )
|
||||||
return null;
|
return null;
|
||||||
|
@ -135,7 +137,7 @@ export default class Metadata extends Module {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! stats )
|
if ( ! stats || stats.hlsLatencyBroadcaster < -100 )
|
||||||
return {stats};
|
return {stats};
|
||||||
|
|
||||||
let drift = 0;
|
let drift = 0;
|
||||||
|
@ -154,6 +156,8 @@ export default class Metadata extends Module {
|
||||||
order: 3,
|
order: 3,
|
||||||
icon: 'ffz-i-gauge',
|
icon: 'ffz-i-gauge',
|
||||||
|
|
||||||
|
subtitle: () => this.i18n.t('metadata.player-stats.subtitle', 'Latency'),
|
||||||
|
|
||||||
label(data) {
|
label(data) {
|
||||||
if ( ! this.settings.get('metadata.player-stats') || ! data.delay )
|
if ( ! this.settings.get('metadata.player-stats') || ! data.delay )
|
||||||
return null;
|
return null;
|
||||||
|
@ -226,9 +230,6 @@ export default class Metadata extends Module {
|
||||||
if ( bar ) {
|
if ( bar ) {
|
||||||
for(const inst of bar.ChannelBar.instances)
|
for(const inst of bar.ChannelBar.instances)
|
||||||
bar.updateMetadata(inst, keys);
|
bar.updateMetadata(inst, keys);
|
||||||
|
|
||||||
for(const inst of bar.HostBar.instances)
|
|
||||||
bar.updateMetadata(inst, keys);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,6 +240,264 @@ export default class Metadata extends Module {
|
||||||
|
|
||||||
let el = container.querySelector(`.ffz-stat[data-key="${key}"]`);
|
let el = container.querySelector(`.ffz-stat[data-key="${key}"]`);
|
||||||
|
|
||||||
|
const def = this.definitions[key],
|
||||||
|
destroy = () => {
|
||||||
|
if ( el ) {
|
||||||
|
if ( el.tooltip )
|
||||||
|
el.tooltip.destroy();
|
||||||
|
|
||||||
|
if ( el.popper )
|
||||||
|
el.popper.destroy();
|
||||||
|
|
||||||
|
if ( el._ffz_destroy )
|
||||||
|
el._ffz_destroy();
|
||||||
|
|
||||||
|
el._ffz_destroy = el.tooltip = el.popper = null;
|
||||||
|
el.remove();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( ! def )
|
||||||
|
return destroy();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Process the data if a setup method is defined.
|
||||||
|
if ( def.setup )
|
||||||
|
data = await def.setup.call(this, data);
|
||||||
|
|
||||||
|
// Let's get refresh logic out of the way now.
|
||||||
|
const refresh = maybe_call(def.refresh, this, data);
|
||||||
|
if ( refresh )
|
||||||
|
timers[key] = setTimeout(
|
||||||
|
() => refresh_fn(key),
|
||||||
|
typeof refresh === 'number' ? refresh : 1000
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Grab the element again in case it changed, somehow.
|
||||||
|
el = container.querySelector(`.ffz-sidebar-stat[data-key="${key}"]`);
|
||||||
|
|
||||||
|
let stat, old_color, sub_el;
|
||||||
|
|
||||||
|
const label = maybe_call(def.label, this, data);
|
||||||
|
|
||||||
|
if ( ! label )
|
||||||
|
return destroy();
|
||||||
|
|
||||||
|
const tooltip = maybe_call(def.tooltip, this, data),
|
||||||
|
subtitle = maybe_call(def.subtitle, this, data),
|
||||||
|
order = maybe_call(def.order, this, data),
|
||||||
|
color = maybe_call(def.color, this, data) || '';
|
||||||
|
|
||||||
|
if ( ! el ) {
|
||||||
|
let icon = maybe_call(def.icon, this, data);
|
||||||
|
let button = false;
|
||||||
|
|
||||||
|
el = (<div
|
||||||
|
class="ffz-sidebar-stat tw-flex tw-flex-grow-1 tw-flex-column tw-justify-content-center"
|
||||||
|
data-key={key}
|
||||||
|
tip_content={tooltip}
|
||||||
|
/>);
|
||||||
|
|
||||||
|
if ( def.popup || def.click ) {
|
||||||
|
button = true;
|
||||||
|
|
||||||
|
let btn, popup;
|
||||||
|
let cls = maybe_call(def.button, this, data);
|
||||||
|
if ( typeof cls !== 'string' )
|
||||||
|
cls = `tw-button--${cls ? 'hollow' : 'text'}`;
|
||||||
|
|
||||||
|
if ( typeof icon === 'string' )
|
||||||
|
icon = (<span class="tw-button__icon tw-button__icon--left"><figure class={icon} /></span>);
|
||||||
|
|
||||||
|
if ( def.popup && def.click ) {
|
||||||
|
el.appendChild(<div class="tw-flex tw--full-width tw-flex-no-wrap">
|
||||||
|
{btn = (<button class={`tw-interactive tw-button tw-button--full-width ${cls} ffz-has-stat-arrow`}>
|
||||||
|
{icon}
|
||||||
|
{stat = <div class="tw-button__text ffz-sidebar-stat--label" />}
|
||||||
|
</button>)}
|
||||||
|
{popup = (<button class={`tw-button ${cls} ffz-stat-arrow`}>
|
||||||
|
<span class="tw-button__icon tw-pd-x-0">
|
||||||
|
<figure class="ffz-i-down-dir" />
|
||||||
|
</span>
|
||||||
|
</button>)}
|
||||||
|
</div>);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
el.appendChild(btn = popup = (<button class={`tw-interactive tw-button tw-button--full-width ${cls}`}>
|
||||||
|
{icon}
|
||||||
|
{stat = <div class="tw-button__text ffz-sidebar-stat--label" />}
|
||||||
|
{def.popup && <span class="tw-button__icon tw-button__icon--right">
|
||||||
|
<figure class="ffz-i-down-dir" />
|
||||||
|
</span>}
|
||||||
|
</button>));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( def.click )
|
||||||
|
btn.addEventListener('click', e => {
|
||||||
|
if ( btn.disabled || btn.classList.contains('disabled') || el.disabled || el.classList.contains('disabled') )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
def.click.call(this, el._ffz_data, e, () => refresh_fn(key));
|
||||||
|
});
|
||||||
|
|
||||||
|
if ( def.popup )
|
||||||
|
popup.addEventListener('click', () => {
|
||||||
|
if ( popup.disabled || popup.classList.contains('disabled') || el.disabled || el.classList.contains('disabled') )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( el._ffz_popup )
|
||||||
|
return el._ffz_destroy();
|
||||||
|
|
||||||
|
const destroy = el._ffz_destroy = () => {
|
||||||
|
if ( el._ffz_outside )
|
||||||
|
el._ffz_outside.destroy();
|
||||||
|
|
||||||
|
if ( el._ffz_popup ) {
|
||||||
|
const fp = el._ffz_popup;
|
||||||
|
el._ffz_popup = null;
|
||||||
|
fp.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
el._ffz_destroy = el._ffz_outside = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const parent = document.body.querySelector('body #root,body'),
|
||||||
|
tt = el._ffz_popup = new Tooltip(parent, el, {
|
||||||
|
logger: this.log,
|
||||||
|
manual: true,
|
||||||
|
html: true,
|
||||||
|
|
||||||
|
tooltipClass: 'ffz-metadata-balloon tw-balloon tw-block tw-border tw-elevation-1 tw-border-radius-small tw-c-background',
|
||||||
|
// Hide the arrow for now, until we re-do our CSS to make it render correctly.
|
||||||
|
arrowClass: 'tw-balloon__tail tw-overflow-hidden tw-absolute',
|
||||||
|
arrowInner: 'tw-balloon__tail-symbol tw-border-t tw-border-r tw-border-b tw-border-l tw-border-radius-small tw-c-background tw-absolute',
|
||||||
|
innerClass: 'tw-pd-1',
|
||||||
|
|
||||||
|
popper: {
|
||||||
|
placement: 'right-start',
|
||||||
|
modifiers: {
|
||||||
|
preventOverflow: {
|
||||||
|
boundariesElement: parent
|
||||||
|
},
|
||||||
|
flip: {
|
||||||
|
behavior: ['top', 'bottom', 'left', 'right']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
content: (t, tip) => def.popup.call(this, el._ffz_data, tip, () => refresh_fn(key)),
|
||||||
|
onShow: (t, tip) =>
|
||||||
|
setTimeout(() => {
|
||||||
|
el._ffz_outside = new ClickOutside(tip.outer, destroy);
|
||||||
|
}),
|
||||||
|
onHide: destroy
|
||||||
|
});
|
||||||
|
|
||||||
|
tt._enter(el);
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
el.appendChild(<div class="tw-align-items-center tw-flex tw-justify-content-center tw-font-size-4">
|
||||||
|
{stat = <div class="tw-strong ffz-sidebar-stat--label" />}
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
|
||||||
|
el.appendChild(sub_el = <div class="tw-flex tw-justify-content-center tw-c-text-alt-2 tw-font-size-6 ffz-sidebar-stat--subtitle" />);
|
||||||
|
|
||||||
|
let subcontainer;
|
||||||
|
|
||||||
|
if ( button ) {
|
||||||
|
subcontainer = container.querySelector('.ffz-sidebar-stats--buttons');
|
||||||
|
if ( ! subcontainer )
|
||||||
|
container.appendChild(subcontainer = (<div class="tw-flex tw-flex-wrap tw-justify-content-between ffz-sidebar-stats ffz-sidebar-stats--buttons" />));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
subcontainer = container.querySelector('.ffz-sidebar-stats--stats');
|
||||||
|
if ( ! subcontainer ) {
|
||||||
|
subcontainer = (<div class="tw-flex tw-flex-wrap tw-justify-content-between ffz-sidebar-stats ffz-sidebar-stats--stats" />);
|
||||||
|
const btns = container.querySelector('.ffz-sidebar-stats--buttons');
|
||||||
|
if ( btns )
|
||||||
|
container.insertBefore(subcontainer, btns);
|
||||||
|
else
|
||||||
|
container.appendChild(subcontainer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
el._ffz_order = order;
|
||||||
|
|
||||||
|
if ( order != null )
|
||||||
|
el.style.order = order;
|
||||||
|
|
||||||
|
subcontainer.appendChild(el);
|
||||||
|
|
||||||
|
if ( def.tooltip ) {
|
||||||
|
const parent = document.body.querySelector('body #root,body');
|
||||||
|
el.tooltip = new Tooltip(parent, el, {
|
||||||
|
logger: this.log,
|
||||||
|
live: false,
|
||||||
|
html: true,
|
||||||
|
content: () => el.tip_content,
|
||||||
|
onShow: (t, tip) => el.tip = tip,
|
||||||
|
onHide: () => el.tip = null,
|
||||||
|
popper: {
|
||||||
|
placement: 'top',
|
||||||
|
modifiers: {
|
||||||
|
flip: {
|
||||||
|
behavior: ['bottom', 'top']
|
||||||
|
},
|
||||||
|
preventOverflow: {
|
||||||
|
boundariesElement: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
stat = el.querySelector('.ffz-sidebar-stat--label');
|
||||||
|
sub_el = el.querySelector('.ffz-sidebar-stat--subtitle')
|
||||||
|
old_color = el.dataset.color || '';
|
||||||
|
|
||||||
|
if ( el._ffz_order !== order )
|
||||||
|
el.style.order = el._ffz_order = order;
|
||||||
|
|
||||||
|
if ( el.tip_content !== tooltip ) {
|
||||||
|
el.tip_content = tooltip;
|
||||||
|
if ( el.tip )
|
||||||
|
el.tip.element.innerHTML = tooltip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( old_color !== color )
|
||||||
|
el.dataset.color = el.style.color = color;
|
||||||
|
|
||||||
|
el._ffz_data = data;
|
||||||
|
|
||||||
|
setChildren(stat, label, true);
|
||||||
|
setChildren(sub_el, subtitle, true);
|
||||||
|
|
||||||
|
if ( def.disabled !== undefined )
|
||||||
|
el.disabled = maybe_call(def.disabled, this, data);
|
||||||
|
|
||||||
|
} catch(err) {
|
||||||
|
this.log.capture(err, {
|
||||||
|
tags: {
|
||||||
|
metadata: key
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.log.error(`Error rendering metadata for ${key}`, err);
|
||||||
|
return destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async renderLegacy(key, data, container, timers, refresh_fn) {
|
||||||
|
if ( timers[key] )
|
||||||
|
clearTimeout(timers[key]);
|
||||||
|
|
||||||
|
let el = container.querySelector(`.ffz-stat[data-key="${key}"]`);
|
||||||
|
|
||||||
const def = this.definitions[key],
|
const def = this.definitions[key],
|
||||||
destroy = () => {
|
destroy = () => {
|
||||||
if ( el ) {
|
if ( el ) {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
import { has } from 'utilities/object';
|
import { get, has } from 'utilities/object';
|
||||||
|
|
||||||
import Twilight from 'site';
|
import Twilight from 'site';
|
||||||
|
|
||||||
|
@ -44,9 +44,8 @@ export default class Channel extends Module {
|
||||||
|
|
||||||
this.ChannelPage = this.fine.define(
|
this.ChannelPage = this.fine.define(
|
||||||
'channel-page',
|
'channel-page',
|
||||||
n => n.getHostedChannelLogin && n.handleHostingChange,
|
n => (n.getHostedChannelLogin && n.handleHostingChange) || n.hostModeFromGraphQL,
|
||||||
//n => n.hostModeFromGraphQL,
|
['user', 'user-videos', 'user-clips', 'user-collections', 'user-events', 'user-followers', 'user-following']
|
||||||
['user']
|
|
||||||
);
|
);
|
||||||
|
|
||||||
this.RaidController = this.fine.define(
|
this.RaidController = this.fine.define(
|
||||||
|
@ -68,17 +67,12 @@ export default class Channel extends Module {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.ChannelPage.on('update', inst => {
|
this.ChannelPage.on('update', inst => {
|
||||||
if ( this.settings.get('channel.hosting.enable') )
|
if ( this.settings.get('channel.hosting.enable') || has(inst.state, 'hostMode') )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// We can't do this immediately because the player state
|
// We can't do this immediately because the player state
|
||||||
// occasionally screws up if we do.
|
// occasionally screws up if we do.
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
/*if ( inst.state.hostMode ) {
|
|
||||||
inst.ffzExpectedHost = inst.state.hostMode;
|
|
||||||
inst.ffzOldSetState({hostMode: null});
|
|
||||||
}*/
|
|
||||||
|
|
||||||
const current_channel = inst.props.data && inst.props.data.variables && inst.props.data.variables.currentChannelLogin;
|
const current_channel = inst.props.data && inst.props.data.variables && inst.props.data.variables.currentChannelLogin;
|
||||||
if ( current_channel && current_channel !== inst.state.videoPlayerSource ) {
|
if ( current_channel && current_channel !== inst.state.videoPlayerSource ) {
|
||||||
inst.ffzExpectedHost = inst.state.videoPlayerSource;
|
inst.ffzExpectedHost = inst.state.videoPlayerSource;
|
||||||
|
@ -134,26 +128,40 @@ export default class Channel extends Module {
|
||||||
if ( inst._ffz_hosting_wrapped )
|
if ( inst._ffz_hosting_wrapped )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const t = this;
|
const t = this,
|
||||||
|
new_style = has(inst.state, 'hostMode');
|
||||||
|
|
||||||
|
inst.ffzGetChannel = () => {
|
||||||
|
const params = inst.props.match.params
|
||||||
|
if ( ! params )
|
||||||
|
return get('props.data.variables.currentChannelLogin', inst)
|
||||||
|
|
||||||
|
return params.channelName || params.channelLogin
|
||||||
|
}
|
||||||
|
|
||||||
inst.ffzOldSetState = inst.setState;
|
inst.ffzOldSetState = inst.setState;
|
||||||
inst.setState = function(state, ...args) {
|
inst.setState = function(state, ...args) {
|
||||||
try {
|
try {
|
||||||
|
if ( new_style ) {
|
||||||
|
if ( has(state, 'hostMode') ) {
|
||||||
|
t.log.info('update-host', state.hostMode)
|
||||||
|
|
||||||
|
inst.ffzExpectedHost = state.hostMode;
|
||||||
|
if ( state.hostMode && ! t.settings.get('channel.hosting.enable') ) {
|
||||||
|
state.hostMode = null;
|
||||||
|
state.videoPlayerSource = inst.ffzGetChannel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
if ( ! t.settings.get('channel.hosting.enable') ) {
|
if ( ! t.settings.get('channel.hosting.enable') ) {
|
||||||
if ( has(state, 'isHosting') )
|
if ( has(state, 'isHosting') )
|
||||||
state.isHosting = false;
|
state.isHosting = false;
|
||||||
|
|
||||||
if ( has(state, 'videoPlayerSource') )
|
if ( has(state, 'videoPlayerSource') )
|
||||||
state.videoPlayerSource = inst.props.match.params.channelName;
|
state.videoPlayerSource = inst.ffzGetChannel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if ( has(state, 'hostMode') ) {
|
|
||||||
inst.ffzExpectedHost = state.hostMode;
|
|
||||||
if ( state.hostMode && ! t.settings.get('channel.hosting.enable') ) {
|
|
||||||
state.hostMode = null;
|
|
||||||
state.videoPlayerSource = inst.props.match.params.channelName;
|
|
||||||
}
|
}
|
||||||
}*/
|
|
||||||
|
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
t.log.capture(err, {extra: {props: inst.props, state}});
|
t.log.capture(err, {extra: {props: inst.props, state}});
|
||||||
|
@ -164,6 +172,17 @@ export default class Channel extends Module {
|
||||||
|
|
||||||
inst._ffz_hosting_wrapped = true;
|
inst._ffz_hosting_wrapped = true;
|
||||||
|
|
||||||
|
if ( new_style ) {
|
||||||
|
const hosted = inst.ffzExpectedHost = inst.state.hostMode;
|
||||||
|
t.log.info('Expected Host', hosted);
|
||||||
|
|
||||||
|
if ( hosted && ! this.settings.get('channel.hosting.enable') )
|
||||||
|
inst.ffzOldSetState({
|
||||||
|
hostMode: null,
|
||||||
|
videoPlayerSource: inst.props.match.params.channelName
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
inst.ffzOldGetHostedLogin = inst.getHostedChannelLogin;
|
inst.ffzOldGetHostedLogin = inst.getHostedChannelLogin;
|
||||||
inst.getHostedChannelLogin = function() {
|
inst.getHostedChannelLogin = function() {
|
||||||
return t.settings.get('channel.hosting.enable') ?
|
return t.settings.get('channel.hosting.enable') ?
|
||||||
|
@ -181,17 +200,13 @@ export default class Channel extends Module {
|
||||||
inst.ffzExpectedHost = inst.state.isHosting ? inst.state.videoPlayerSource : null;
|
inst.ffzExpectedHost = inst.state.isHosting ? inst.state.videoPlayerSource : null;
|
||||||
if ( ! this.settings.get('channel.hosting.enable') )
|
if ( ! this.settings.get('channel.hosting.enable') )
|
||||||
inst.ffzOldHostHandler(null);
|
inst.ffzOldHostHandler(null);
|
||||||
|
}
|
||||||
|
|
||||||
// Finally, we force an update so that any child components
|
// Finally, we force an update so that any child components
|
||||||
// receive our updated handler.
|
// receive our updated handler.
|
||||||
inst.forceUpdate();
|
inst.forceUpdate();
|
||||||
|
|
||||||
/*const hosted = inst.ffzExpectedHost = inst.state.hostMode;
|
|
||||||
if ( hosted && ! this.settings.get('channel.hosting.enable') )
|
|
||||||
inst.ffzOldSetState({
|
|
||||||
hostMode: null,
|
|
||||||
videoPlayerSource: inst.props.match.params.channelName
|
|
||||||
});*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -200,15 +215,17 @@ export default class Channel extends Module {
|
||||||
val = this.settings.get('channel.hosting.enable');
|
val = this.settings.get('channel.hosting.enable');
|
||||||
|
|
||||||
for(const inst of this.ChannelPage.instances) {
|
for(const inst of this.ChannelPage.instances) {
|
||||||
inst.ffzOldHostHandler(val ? inst.ffzExpectedHost : null);
|
if ( has(inst.state, 'hostMode') ) {
|
||||||
|
const host = val ? inst.ffzExpectedHost : null,
|
||||||
/*const host = val ? inst.ffzExpectedHost : null,
|
target = host && host.hostedChannel && host.hostedChannel.login || inst.ffzGetChannel();
|
||||||
target = host && host.hostedChannel && host.hostedChannel.login || inst.props.match.params.channelName;
|
|
||||||
|
|
||||||
inst.ffzOldSetState({
|
inst.ffzOldSetState({
|
||||||
hostMode: host,
|
hostMode: host,
|
||||||
videoPlayerSource: target
|
videoPlayerSource: target
|
||||||
});*/
|
});
|
||||||
|
|
||||||
|
} else
|
||||||
|
inst.ffzOldHostHandler(val ? inst.ffzExpectedHost : null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,7 +9,6 @@ import {deep_copy} from 'utilities/object';
|
||||||
|
|
||||||
import CHANNEL_QUERY from './channel_bar_query.gql';
|
import CHANNEL_QUERY from './channel_bar_query.gql';
|
||||||
|
|
||||||
|
|
||||||
export default class ChannelBar extends Module {
|
export default class ChannelBar extends Module {
|
||||||
constructor(...args) {
|
constructor(...args) {
|
||||||
super(...args);
|
super(...args);
|
||||||
|
@ -21,27 +20,19 @@ export default class ChannelBar extends Module {
|
||||||
this.inject('metadata');
|
this.inject('metadata');
|
||||||
this.inject('socket');
|
this.inject('socket');
|
||||||
|
|
||||||
this.apollo.registerModifier('ChannelPage_ChannelHeader', CHANNEL_QUERY);
|
this.apollo.registerModifier('ChannelPage_User', CHANNEL_QUERY);
|
||||||
this.apollo.registerModifier('ChannelPage_ChannelHeader', data => {
|
/*this.apollo.registerModifier('ChannelPage_User', data => {
|
||||||
const u = data && data.data && data.data.user;
|
const u = data && data.data && data.data.user;
|
||||||
if ( u ) {
|
if ( u ) {
|
||||||
const o = u.profileViewCount = new Number(u.profileViewCount || 0);
|
const o = u.profileViewCount = new Number(u.profileViewCount || 0);
|
||||||
o.data = deep_copy(u);
|
o.data = deep_copy(u);
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);*/
|
||||||
|
|
||||||
|
|
||||||
this.ChannelBar = this.fine.define(
|
this.ChannelBar = this.fine.define(
|
||||||
'channel-bar',
|
'channel-bar',
|
||||||
n => n.getTitle && n.getGame && n.renderGame,
|
n => n.renderChannelMetadata && n.renderTitleInfo,
|
||||||
['user']
|
['user', 'video', 'user-videos', 'user-clips', 'user-collections', 'user-events', 'user-followers', 'user-following']
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
this.HostBar = this.fine.define(
|
|
||||||
'host-container',
|
|
||||||
n => n.handleReportHosterClick,
|
|
||||||
['user']
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,16 +45,6 @@ export default class ChannelBar extends Module {
|
||||||
for(const inst of instances)
|
for(const inst of instances)
|
||||||
this.updateChannelBar(inst);
|
this.updateChannelBar(inst);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/*this.HostBar.on('unmount', this.unmountHostBar, this);
|
|
||||||
this.HostBar.on('mount', this.updateHostBar, this);
|
|
||||||
this.HostBar.on('update', this.updateHostBar, this);
|
|
||||||
|
|
||||||
this.HostBar.ready((cls, instances) => {
|
|
||||||
for(const inst of instances)
|
|
||||||
this.updateHostBar(inst);
|
|
||||||
});*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,11 +80,13 @@ export default class ChannelBar extends Module {
|
||||||
|
|
||||||
updateMetadata(inst, keys) {
|
updateMetadata(inst, keys) {
|
||||||
const container = this.fine.getChildNode(inst),
|
const container = this.fine.getChildNode(inst),
|
||||||
metabar = container && container.querySelector && container.querySelector('.channel-info-bar__action-container > .tw-flex');
|
wrapper = container && container.querySelector && container.querySelector('.side-nav-channel-info__info-wrapper > .tw-pd-t-05');
|
||||||
|
|
||||||
if ( ! inst._ffz_mounted || ! metabar )
|
if ( ! inst._ffz_mounted || ! wrapper )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const metabar = wrapper;
|
||||||
|
|
||||||
if ( ! keys )
|
if ( ! keys )
|
||||||
keys = this.metadata.keys;
|
keys = this.metadata.keys;
|
||||||
else if ( ! Array.isArray(keys) )
|
else if ( ! Array.isArray(keys) )
|
||||||
|
@ -112,7 +95,7 @@ export default class ChannelBar extends Module {
|
||||||
const timers = inst._ffz_meta_timers = inst._ffz_meta_timers || {},
|
const timers = inst._ffz_meta_timers = inst._ffz_meta_timers || {},
|
||||||
refresh_func = key => this.updateMetadata(inst, key),
|
refresh_func = key => this.updateMetadata(inst, key),
|
||||||
data = {
|
data = {
|
||||||
channel: inst.props.userData && inst.props.userData.user,
|
channel: inst.props.data && inst.props.data.user,
|
||||||
hosting: false,
|
hosting: false,
|
||||||
_inst: inst
|
_inst: inst
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,9 @@ body .channel-page__video-player--theatre-mode {
|
||||||
}
|
}
|
||||||
|
|
||||||
body .video-watch-page__right-column,
|
body .video-watch-page__right-column,
|
||||||
body .channel-page__right-column {
|
body .channel-page__right-column,
|
||||||
|
body .right-column,
|
||||||
|
body .channel-root__right-column {
|
||||||
width: var(--ffz-chat-width);
|
width: var(--ffz-chat-width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
124
src/sites/twitch-twilight/modules/legacy_channel_bar.js
Normal file
124
src/sites/twitch-twilight/modules/legacy_channel_bar.js
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Channel Bar
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
import Module from 'utilities/module';
|
||||||
|
import {deep_copy} from 'utilities/object';
|
||||||
|
|
||||||
|
import CHANNEL_QUERY from './channel_bar_query.gql';
|
||||||
|
|
||||||
|
|
||||||
|
export default class LegacyChannelBar extends Module {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
this.should_enable = true;
|
||||||
|
|
||||||
|
this.inject('site.fine');
|
||||||
|
this.inject('site.apollo');
|
||||||
|
this.inject('metadata');
|
||||||
|
this.inject('socket');
|
||||||
|
|
||||||
|
this.apollo.registerModifier('ChannelPage_ChannelHeader', CHANNEL_QUERY);
|
||||||
|
this.apollo.registerModifier('ChannelPage_ChannelHeader', data => {
|
||||||
|
const u = data && data.data && data.data.user;
|
||||||
|
if ( u ) {
|
||||||
|
const o = u.profileViewCount = new Number(u.profileViewCount || 0);
|
||||||
|
o.data = deep_copy(u);
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
|
||||||
|
this.ChannelBar = this.fine.define(
|
||||||
|
'legacy-channel-bar',
|
||||||
|
n => n.getTitle && n.getGame && n.renderGame,
|
||||||
|
['user']
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
this.HostBar = this.fine.define(
|
||||||
|
'legacy-host-container',
|
||||||
|
n => n.handleReportHosterClick,
|
||||||
|
['user']
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
onEnable() {
|
||||||
|
this.ChannelBar.on('unmount', this.unmountChannelBar, this);
|
||||||
|
this.ChannelBar.on('mount', this.updateChannelBar, this);
|
||||||
|
this.ChannelBar.on('update', this.updateChannelBar, this);
|
||||||
|
|
||||||
|
this.ChannelBar.ready((cls, instances) => {
|
||||||
|
for(const inst of instances)
|
||||||
|
this.updateChannelBar(inst);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*this.HostBar.on('unmount', this.unmountHostBar, this);
|
||||||
|
this.HostBar.on('mount', this.updateHostBar, this);
|
||||||
|
this.HostBar.on('update', this.updateHostBar, this);
|
||||||
|
|
||||||
|
this.HostBar.ready((cls, instances) => {
|
||||||
|
for(const inst of instances)
|
||||||
|
this.updateHostBar(inst);
|
||||||
|
});*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
updateChannelBar(inst) {
|
||||||
|
const login = inst.props.channelLogin;
|
||||||
|
if ( login !== inst._ffz_old_login ) {
|
||||||
|
if ( inst._ffz_old_login )
|
||||||
|
this.socket.unsubscribe(inst, `channel.${inst._ffz_old_login}`);
|
||||||
|
|
||||||
|
if ( login )
|
||||||
|
this.socket.subscribe(inst, `channel.${login}`);
|
||||||
|
inst._ffz_old_login = login;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateMetadata(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
unmountChannelBar(inst) {
|
||||||
|
if ( inst._ffz_old_login ) {
|
||||||
|
this.socket.unsubscribe(inst, `channel.${inst._ffz_old_login}`);
|
||||||
|
inst._ffz_old_login = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const timers = inst._ffz_meta_timers;
|
||||||
|
if ( timers )
|
||||||
|
for(const key in timers)
|
||||||
|
if ( timers[key] )
|
||||||
|
clearTimeout(timers[key]);
|
||||||
|
|
||||||
|
inst._ffz_meta_timers = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
updateMetadata(inst, keys) {
|
||||||
|
const container = this.fine.getChildNode(inst),
|
||||||
|
metabar = container && container.querySelector && container.querySelector('.channel-info-bar__action-container > .tw-flex');
|
||||||
|
|
||||||
|
if ( ! inst._ffz_mounted || ! metabar )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( ! keys )
|
||||||
|
keys = this.metadata.keys;
|
||||||
|
else if ( ! Array.isArray(keys) )
|
||||||
|
keys = [keys];
|
||||||
|
|
||||||
|
const timers = inst._ffz_meta_timers = inst._ffz_meta_timers || {},
|
||||||
|
refresh_func = key => this.updateMetadata(inst, key),
|
||||||
|
data = {
|
||||||
|
channel: inst.props.userData && inst.props.userData.user,
|
||||||
|
hosting: false,
|
||||||
|
legacy: true,
|
||||||
|
_inst: inst
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const key of keys)
|
||||||
|
this.metadata.renderLegacy(key, data, metabar, timers, refresh_func);
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,8 +36,30 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ffz-sidebar-stats {
|
||||||
|
margin-top: .5rem;
|
||||||
|
margin-right: -1rem;
|
||||||
|
|
||||||
|
& + .ffz-sidebar-stats {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ffz-sidebar-stat {
|
||||||
|
min-width: calc(50% - 1rem);
|
||||||
|
margin: 0 1rem 1rem 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ffz-has-stat-arrow {
|
||||||
|
border-top-right-radius: 0 !important;
|
||||||
|
border-bottom-right-radius: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.ffz-stat-arrow {
|
.ffz-stat-arrow {
|
||||||
border-left: none !important;
|
border-left: none !important;
|
||||||
|
border-top-left-radius: 0 !important;
|
||||||
|
border-bottom-left-radius: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue