diff --git a/package.json b/package.json index 74686196..9201a940 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "frankerfacez", "author": "Dan Salvato LLC", - "version": "4.20.57", + "version": "4.20.58", "description": "FrankerFaceZ is a Twitch enhancement suite.", "license": "Apache-2.0", "scripts": { diff --git a/src/modules/metadata.jsx b/src/modules/metadata.jsx index 8a559437..0363b87b 100644 --- a/src/modules/metadata.jsx +++ b/src/modules/metadata.jsx @@ -291,6 +291,7 @@ export default class Metadata extends Module { this.definitions['player-stats'] = { button: true, inherit: true, + modview: true, refresh() { return this.settings.get('metadata.player-stats') diff --git a/src/sites/twitch-twilight/modules/css_tweaks/index.js b/src/sites/twitch-twilight/modules/css_tweaks/index.js index 20d1a2d5..5e1de877 100644 --- a/src/sites/twitch-twilight/modules/css_tweaks/index.js +++ b/src/sites/twitch-twilight/modules/css_tweaks/index.js @@ -22,6 +22,7 @@ const CLASSES = { 'side-closed-rec-channels': '.side-nav--collapsed .recommended-channels,.side-nav--collapsed .side-nav-section + .side-nav-section:not(.online-friends)', 'side-offline-channels': '.ffz--side-nav-card-offline', 'side-rerun-channels': '.side-nav .ffz--side-nav-card-rerun', + 'modview-hide-info': '.tw-flex.modview-player-widget__hide-stream-info', 'community-highlights': '.community-highlight-stack__card', @@ -62,6 +63,16 @@ export default class CSSTweaks extends Module { // Layout + this.settings.add('metadata.modview.hide-info', { + default: false, + ui: { + path: 'Channel > Metadata >> Mod View', + title: 'Hide "Hide Stream Info Stripe" button.', + component: 'setting-check-box' + }, + changed: val => this.toggleHide('modview-hide-info', val) + }); + this.settings.add('metadata.viewers.no-native', { requires: ['metadata.viewers'], default: null, @@ -420,6 +431,7 @@ export default class CSSTweaks extends Module { } onEnable() { + this.toggleHide('modview-hide-info', this.settings.get('metadata.modview.hide-info')); this.toggleHide('side-nav-viewers', this.settings.get('layout.side-nav.hide-viewers')); this.toggle('hide-native-uptime', this.settings.get('metadata.uptime.no-native')); this.toggle('hide-native-viewers', this.settings.get('metadata.viewers.no-native')); diff --git a/src/sites/twitch-twilight/modules/css_tweaks/styles/chat-width.scss b/src/sites/twitch-twilight/modules/css_tweaks/styles/chat-width.scss index c82c6e75..9c77f097 100644 --- a/src/sites/twitch-twilight/modules/css_tweaks/styles/chat-width.scss +++ b/src/sites/twitch-twilight/modules/css_tweaks/styles/chat-width.scss @@ -2,6 +2,10 @@ min-width: unset !important; } +.reward-center__content { + width: calc(var(--ffz-chat-width) - 2rem) !important; +} + body .whispers--theatre-mode.whispers--right-column-expanded-beside { right: var(--ffz-chat-width); } diff --git a/src/sites/twitch-twilight/modules/featured_follow.js b/src/sites/twitch-twilight/modules/featured_follow.js index 85acbfa7..3d1854b5 100644 --- a/src/sites/twitch-twilight/modules/featured_follow.js +++ b/src/sites/twitch-twilight/modules/featured_follow.js @@ -49,6 +49,7 @@ export default class FeaturedFollow extends Module { this.metadata.definitions.following = { order: 150, button: true, + modview: true, popup: async (data, tip, refresh_fn, add_callback) => { const vue = this.resolve('vue'), diff --git a/src/sites/twitch-twilight/modules/host_button/index.js b/src/sites/twitch-twilight/modules/host_button/index.js index 91a75593..0fec8532 100644 --- a/src/sites/twitch-twilight/modules/host_button/index.js +++ b/src/sites/twitch-twilight/modules/host_button/index.js @@ -59,6 +59,7 @@ export default class HostButton extends Module { border: true, button: true, fade_in: true, + modview: true, disabled: () => this._host_updating || this._host_error, diff --git a/src/sites/twitch-twilight/modules/mod-view.jsx b/src/sites/twitch-twilight/modules/mod-view.jsx index 73db6635..7f8e0862 100644 --- a/src/sites/twitch-twilight/modules/mod-view.jsx +++ b/src/sites/twitch-twilight/modules/mod-view.jsx @@ -5,9 +5,7 @@ // ============================================================================ import Module from 'utilities/module'; -import { Color } from 'utilities/color'; import {debounce} from 'utilities/object'; -import {createElement, ClickOutside, setChildren} from 'utilities/dom'; export default class ModView extends Module { @@ -28,6 +26,7 @@ export default class ModView extends Module { this.should_enable = true; this._cached_channel = null; + this._cached_id = null; this.Root = this.elemental.define( 'mod-view-root', '.moderation-view-page', @@ -38,10 +37,11 @@ export default class ModView extends Module { this.ModInfoBar = this.elemental.define( 'mod-info-bar', '.modview-player-widget__stream-info .simplebar-content', ['mod-view'], - {childNodes: true, subtree: true}, 1 + {childNodes: true, subtree: true}, 1, 30000, false ); this.checkRoot = debounce(this.checkRoot, 250); + this.checkBar = debounce(this.checkBar, 250); } onEnable() { @@ -81,6 +81,10 @@ export default class ModView extends Module { } } + checkBar() { + this.ModInfoBar.clean(); + } + checkRoot() { this.Root.each(el => this.updateRoot(el)); } @@ -95,8 +99,9 @@ export default class ModView extends Module { i++; } - if ( channel?.id && this._cached_channel != channel.id ) { - this._cached_channel = channel.id; + if ( channel?.id && this._cached_id != channel.id ) { + this._cached_id = channel.id; + this._cached_channel = channel; this.updateSubscription(channel.login); this.getChannelColor(el, channel.id).then(color => { @@ -171,6 +176,7 @@ export default class ModView extends Module { } removeRoot() { + this._cached_id = null; this._cached_channel = null; this.updateSubscription(); this.channel.updateChannelColor(); @@ -196,7 +202,7 @@ export default class ModView extends Module { title = bcast?.title, game = bcast?.game; - if ( channel?.id && channel.id != this._cached_channel ) + if ( channel?.id && channel.id != this._cached_id ) this.checkRoot(); if ( title != el._cached_title || game?.id != el._cached_game ) { @@ -209,6 +215,16 @@ export default class ModView extends Module { title }); } + + if ( container ) { + if ( ! container._ffz_cont ) { + const e = container._ffz_cont = container.querySelector('.modview-player-widget__viewcount'); + if ( e ) + e.classList.add('ffz--mod-tray'); + } + + this.updateMetadata(container); + } } removeBar(el) { @@ -218,18 +234,68 @@ export default class ModView extends Module { title: null }); - if ( el._ffz_cont ) - el._ffz_cont.classList.remove('ffz--meta-tray'); + const container = el.closest('.modview-player-widget__stream-info'); + if ( ! container ) + return; - el._ffz_cont = null; - if ( el._ffz_meta_timers ) { - for(const val of Object.values(el._ffz_meta_timers)) + if ( container._ffz_cont ) + container._ffz_cont.classList.remove('ffz--mod-tray'); + + container._ffz_cont = null; + if ( container._ffz_meta_timers ) { + for(const val of Object.values(container._ffz_meta_timers)) clearTimeout(val); - el._ffz_meta_timers = null; + container._ffz_meta_timers = null; } - el._ffz_update = null; + container._ffz_update = null; + } + + updateMetadata(el, keys) { + const cont = el._ffz_cont, + channel = this._cached_channel; + //root = this.fine.getReactInstance(el); + + /*let channel = null, state = root?.return?.memoizedState, i = 0; + while(state != null && channel == null && i < 50 ) { + state = state?.next; + channel = state?.memoizedState?.current?.previousData?.result?.data?.channel; + i++; + }*/ + + if ( ! cont || ! document.contains(cont) ) { + this.checkBar(); + return; + } + + if ( ! channel?.id ) + return; + + if ( ! keys ) + keys = this.metadata.keys; + else if ( ! Array.isArray(keys) ) + keys = [keys]; + + const timers = el._ffz_meta_timers = el._ffz_meta_timers || {}, + refresh_fn = key => this.updateMetadata(el, key), + data = { + channel: { + id: channel.id, + login: channel.login, + display_name: channel.displayName + }, + el, + getViewerCount: () => 0, + getUserSelfImmediate: () => null, + getUserSelf: () => null, + getBroadcastID: () => null + }; + + for(const key of keys) + if ( this.metadata.definitions[key].modview ) + this.metadata.renderLegacy(key, data, cont, timers, refresh_fn); + } } \ No newline at end of file diff --git a/src/sites/twitch-twilight/modules/player.jsx b/src/sites/twitch-twilight/modules/player.jsx index c2f86af7..eda9132c 100644 --- a/src/sites/twitch-twilight/modules/player.jsx +++ b/src/sites/twitch-twilight/modules/player.jsx @@ -7,6 +7,7 @@ import Module from 'utilities/module'; import {createElement, on, off} from 'utilities/dom'; import {debounce} from 'utilities/object'; +import { IS_FIREFOX } from 'src/utilities/constants'; export const PLAYER_ROUTES = [ 'front-page', 'user', 'video', 'user-video', 'user-clip', 'user-videos', @@ -15,6 +16,11 @@ export const PLAYER_ROUTES = [ 'mod-view', 'user-home' ]; +const HAS_PITCH = (() => { + const el = createElement('video'); + return el.preservesPitch != null || el.mozPreservesPitch != null +})(); + const HAS_COMPRESSOR = window.AudioContext && window.DynamicsCompressorNode != null; const STYLE_VALIDATOR = createElement('span'); @@ -217,9 +223,6 @@ export default class Player extends Module { }); } - /* - // This is currently broken due to changes Twitch has made in the player - // backend. Removing it for now to avoid user confusion. this.settings.add('player.allow-catchup', { default: true, ui: { @@ -229,11 +232,8 @@ export default class Player extends Module { component: 'setting-check-box' }, - changed: val => { - for(const inst of this.Player.instances) - this.updateAutoPlaybackRate(inst, val); - } - });*/ + changed: () => this.updatePlaybackRates() + }); this.settings.add('player.mute-click', { default: false, @@ -809,16 +809,19 @@ export default class Player extends Module { this.updateGUI(inst); this.compressPlayer(inst); + this.updatePlaybackRate(inst); } }); this.Player.on('mount', inst => { this.updateGUI(inst); this.compressPlayer(inst); + this.updatePlaybackRate(inst); }); this.Player.on('update', inst => { this.updateGUI(inst); this.compressPlayer(inst); + this.updatePlaybackRate(inst); }); this.Player.on('unmount', inst => { @@ -1058,7 +1061,7 @@ export default class Player extends Module { return; } - let icon, tip, extra, btn, cont = container.querySelector('.ffz--player-comp'); + let icon, tip, extra, ff_el, btn, cont = container.querySelector('.ffz--player-comp'); if ( ! has_comp ) { if ( cont ) cont.remove(); @@ -1083,6 +1086,7 @@ export default class Player extends Module {