1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-08-03 16:38:31 +00:00
FrankerFaceZ/src/sites/twitch-twilight/modules/channel_bar.jsx
SirStendec 30b9a15c0d 4.19.6
* Added: Display bits emote rewards in the FFZ Emote Menu alongside subscription emotes.
* Changed: 2FA reward emotes are now labelled as such in their tool-tips.
* Changed: Update the style for the chat pause notice at the bottom of chat to match the latest Twitch style and language.
* Fixed: Disabling hosting not working on Mod View.
* Fixed: Emote sets not being sorted correctly in the FFZ Emote Menu when combining multiple sets (such as multiple subscription tiers) into one section.
* API Changed: The `setting-color-box` component now allows you to open the color picker up and not only down.
2020-04-03 19:30:28 -04:00

291 lines
No EOL
7.2 KiB
JavaScript

'use strict';
// ============================================================================
// Channel Bar
// ============================================================================
import Module from 'utilities/module';
import {get} from 'utilities/object';
import {createElement} from 'utilities/dom';
//import CHANNEL_QUERY from './channel_header_query.gql';
export default class ChannelBar extends Module {
constructor(...args) {
super(...args);
this.should_enable = true;
this.inject('i18n');
this.inject('settings');
this.inject('site.css_tweaks');
this.inject('site.fine');
this.inject('site.web_munch');
this.inject('site.apollo');
this.inject('site.twitch_data');
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.settings.add('channel.metadata.force-above', {
default: false,
ui: {
path: 'Channel > Metadata >> Appearance',
title: 'Force metadata and tags to the top of the channel information bar.',
component: 'setting-check-box'
},
changed: val => this.css_tweaks.toggle('channel-metadata-top', val)
});
this.VideoBar = this.fine.define(
'video-bar',
n => n.props && n.props.getLastVideoOffset && n.renderTrackedHighlightButton,
['video', 'user-video']
);
this.ChannelBar = this.fine.define(
'channel-bar',
n => n.getTitle && n.getGame && n.renderGame,
['user']
);
this.ModWidget = this.fine.define(
'mod-widget',
n => n.renderToolbar && n.getToolbarControls && n.childContext,
['mod-view']
);
}
onEnable() {
this.css_tweaks.toggle('channel-metadata-top', this.settings.get('channel.metadata.force-above'));
this.on('i18n:update', () => {
for(const bar of this.VideoBar.instances)
this.updateVideoBar(bar);
});
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.ModWidget.on('mount', this.updateModWidget, this);
this.ModWidget.on('update', this.updateModWidget, this);
this.ModWidget.ready((cls, instances) => {
for(const inst of instances)
this.updateModWidget(inst);
});*/
//this.VideoBar.on('unmount', this.unmountVideoBar, this);
this.VideoBar.on('mount', this.updateVideoBar, this);
this.VideoBar.on('update', this.updateVideoBar, this);
this.VideoBar.ready((cls, instances) => {
for(const inst of instances)
this.updateVideoBar(inst);
});
}
/*updateModWidget(inst) {
const container = this.fine.getChildNode(inst);
if ( ! container || ! container.querySelector('.video-player-hosting-ui__container') )
return;
const header = container.querySelector('.mod-view-panel-header');
if ( ! header )
return;
let cont = header.querySelector('.ffz--stat-container');
if ( ! cont ) {
cont = <div class="ffz--stat-container tw-pd-l-05"></div>;
const contcont = header.querySelector(':scope > div:first-child > div');
if ( ! contcont )
return;
contcont.appendChild(cont);
}
this.log.info('mod-widget', inst, cont);
}*/
updateVideoBar(inst) {
const container = this.fine.getChildNode(inst),
timestamp = container && container.querySelector('[data-test-selector="date"]');
if ( ! timestamp )
return;
const published = get('props.video.publishedAt', inst);
if ( ! published )
timestamp.classList.toggle('ffz-tooltip', false);
else {
timestamp.classList.toggle('ffz-tooltip', true);
timestamp.dataset.title = this.i18n.t('video.published-on', 'Published on: {date,date}', {date: published});
}
}
updateChannelBar(inst) {
const login = get('props.channel.login', inst);
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.updateUptime(inst);
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;
}
getBroadcastID(inst) {
const current_id = inst.props?.channel?.stream?.id;
if ( current_id === inst._ffz_stream_id ) {
if ( Date.now() - inst._ffz_broadcast_saved < 60000 )
return Promise.resolve(inst._ffz_broadcast_id);
}
return new Promise(async (s, f) => {
if ( inst._ffz_broadcast_updating )
return inst._ffz_broadcast_updating.push([s, f]);
inst._ffz_broadcast_updating = [[s, f]];
let id, err;
try {
id = await this.twitch_data.getBroadcastID(inst.props.channel.id);
} catch(error) {
id = null;
err = error;
}
const waiters = inst._ffz_broadcast_updating;
inst._ffz_broadcast_updating = null;
if ( current_id !== inst.props?.channel?.stream?.id ) {
err = new Error('Outdated');
inst._ffz_stream_id = null;
inst._ffz_broadcast_saved = 0;
inst._ffz_broadcast_id = null;
for(const pair of waiters)
pair[1](err);
return;
}
inst._ffz_broadcast_id = id;
inst._ffz_broadcast_saved = Date.now();
inst._ffz_stream_id = current_id;
if ( err ) {
for(const pair of waiters)
pair[1](err);
} else {
for(const pair of waiters)
pair[0](id);
}
});
}
async updateUptime(inst) {
const current_id = inst?.props?.channel?.id;
if ( current_id === inst._ffz_uptime_id ) {
if ( Date.now() - inst._ffz_uptime_saved < 60000 )
return;
}
if ( inst._ffz_uptime_updating )
return;
inst._ffz_uptime_updating = true;
inst._ffz_uptime_id = current_id;
if ( ! current_id )
inst._ffz_meta = null;
else {
try {
inst._ffz_meta = await this.twitch_data.getStreamMeta(current_id, inst?.props?.channel?.login);
} catch(err) {
this.log.capture(err);
this.log.error('Error fetching uptime:', err);
inst._ffz_meta = null;
}
}
inst._ffz_uptime_saved = Date.now();
inst._ffz_uptime_updating = false;
this.updateMetadata(inst);
}
updateMetadata(inst, keys) {
const container = this.fine.getChildNode(inst),
metabar = container?.querySelector?.('.channel-info-bar__viewers-count-wrapper > .tw-flex:last-child');
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.channel,
meta: inst._ffz_meta,
hosting: false,
legacy: true,
_inst: inst,
getBroadcastID: () => this.getBroadcastID(inst)
}
for(const key of keys)
this.metadata.renderLegacy(key, data, metabar, timers, refresh_func);
}
}