diff --git a/package.json b/package.json index 829c6e67..19eaccc0 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "frankerfacez", "author": "Dan Salvato LLC", - "version": "4.53.0", + "version": "4.54.0", "description": "FrankerFaceZ is a Twitch enhancement suite.", "private": true, "license": "Apache-2.0", diff --git a/src/modules/chat/override-editor.vue b/src/modules/chat/override-editor.vue index 94fde86d..068bb22a 100644 --- a/src/modules/chat/override-editor.vue +++ b/src/modules/chat/override-editor.vue @@ -25,6 +25,17 @@ @change="updateName" > + + + + {{ t('setting.set-to-current', 'Set to Current') }} + + + + + + + {{ t('setting.set-to-current', 'Set to Current') }} + + + tip.update(), setColor: val => this.setColor(user.id, val), deleteColor: () => this.deleteColor(user.id), diff --git a/src/sites/twitch-twilight/index.js b/src/sites/twitch-twilight/index.js index fd1256eb..9f7098e9 100644 --- a/src/sites/twitch-twilight/index.js +++ b/src/sites/twitch-twilight/index.js @@ -106,12 +106,17 @@ export default class Twilight extends BaseSite { window.addEventListener('resize', update_size); update_size(); - const update_fullscreen = () => this.settings.updateContext({ - fullscreen: !! document.fullscreenElement - }); + const update_fullscreen = () => { + this.settings.updateContext({ + fullscreen: !! document.fullscreenElement + }); + this.emit(':fullscreen'); + } document.addEventListener('fullscreenchange', update_fullscreen); - update_fullscreen(); + this.settings.updateContext({ + fullscreen: !! document.fullscreenElement + }); // Share Context store.subscribe(() => this.updateContext()); diff --git a/src/sites/twitch-twilight/modules/chat/index.js b/src/sites/twitch-twilight/modules/chat/index.js index dc800779..9e793493 100644 --- a/src/sites/twitch-twilight/modules/chat/index.js +++ b/src/sites/twitch-twilight/modules/chat/index.js @@ -1392,7 +1392,10 @@ export default class ChatHook extends Module { inst.props.setMessageBufferAPI({ addUpdateHandler: inst.addUpdateHandler, removeUpdateHandler: inst.removeUpdateHandler, + getUnreadCount: inst.getUnreadCount, getMessages: inst.getMessages, + getMessagesForHighlight: inst.getMessagesForHighlight, + getMessagesForAllHighlights: inst.getMessagesForAllHighlights, isPaused: inst.isPaused, setPaused: inst.setPaused, hasNewerLeft: inst.hasNewerLeft, @@ -2307,6 +2310,10 @@ export default class ChatHook extends Module { this.notifySubscribers(); } } + + if ( this.flushHighlightsBuffer ) + this.flushHighlightsBuffer(); + } catch(err) { t.log.error('Error running flush.', err); return old_flush.call(this); diff --git a/src/sites/twitch-twilight/modules/css_tweaks/index.js b/src/sites/twitch-twilight/modules/css_tweaks/index.js index f8f0bd6e..94285d23 100644 --- a/src/sites/twitch-twilight/modules/css_tweaks/index.js +++ b/src/sites/twitch-twilight/modules/css_tweaks/index.js @@ -13,7 +13,7 @@ const STYLE_VALIDATOR = document.createElement('span'); const CLASSES = { //'unfollow': '.follow-btn__follow-btn--following,.follow-btn--following', - 'top-discover': '.navigation-link[data-a-target="discover-link"]', + //'top-discover': '.navigation-link[data-a-target="discover-link"]', 'side-nav': '.side-nav,#sideNav', 'side-nav-viewers': '.side-nav-card__live-status', 'side-rec-channels': '.side-nav .recommended-channels,.side-nav .side-nav-section + .side-nav-section:not(.online-friends):not(.bd--shelf)', @@ -329,7 +329,7 @@ export default class CSSTweaks extends Module { } }); - this.settings.add('layout.discover', { + /*this.settings.add('layout.discover', { default: true, ui: { path: 'Appearance > Layout >> Top Navigation', @@ -340,6 +340,15 @@ export default class CSSTweaks extends Module { this.toggleHide('top-discover', !val); this.updateTopNav(); } + });*/ + + this.settings.add('layout.turbo-cta', { + default: true, + ui: { + path: 'Appearance > Layout >> Top Navigation', + title: 'Allow the Twitch Turbo button to appear.', + component: 'setting-check-box' + } }); this.settings.add('layout.prime-offers', { @@ -486,7 +495,7 @@ export default class CSSTweaks extends Module { this.toggleHide('side-offline-channels', this.settings.get('layout.side-nav.hide-offline')); this.toggleHide('discover-luna', this.settings.get('layout.hide-discover-luna')); this.toggleHide('prime-offers', !this.settings.get('layout.prime-offers')); - this.toggleHide('top-discover', !this.settings.get('layout.discover')); + //this.toggleHide('top-discover', !this.settings.get('layout.discover')); this.toggle('hide-unfollow-button', this.settings.get('channel.hide-unfollow')); this.toggleHide('pinned-hype-chat', ! this.settings.get('chat.hype.show-pinned')); diff --git a/src/sites/twitch-twilight/modules/loadable.jsx b/src/sites/twitch-twilight/modules/loadable.jsx index 5f2bc949..b919ad1c 100644 --- a/src/sites/twitch-twilight/modules/loadable.jsx +++ b/src/sites/twitch-twilight/modules/loadable.jsx @@ -22,6 +22,11 @@ export default class Loadable extends Module { n => n.props?.component && n.props.loader ); + this.ErrorBoundaryComponent = this.fine.define( + 'error-boundary-component', + n => n.props?.name && n.props?.onError && n.props?.children && n.onErrorBoundaryTestEmit + ); + this.overrides = new Map(); } @@ -31,6 +36,32 @@ export default class Loadable extends Module { this.toggle('PaidPinnedChatMessageList', val); }); + this.settings.getChanges('layout.turbo-cta', val => { + this.toggle('TopNav__TurboButton_Available', val); + }); + + this.ErrorBoundaryComponent.ready((cls, instances) => { + this.log.debug('Found Error Boundary component wrapper.'); + + const t = this, + old_render = cls.prototype.render; + + cls.prototype.render = function() { + try { + const type = this.props.name; + if ( t.overrides.has(type) && ! t.shouldRender(type) ) + return null; + } catch(err) { + /* no-op */ + console.error(err); + } + + return old_render.call(this); + } + + this.ErrorBoundaryComponent.updateInstances(); + }); + this.LoadableComponent.ready((cls, instances) => { this.log.debug('Found Loadable component wrapper.'); @@ -72,6 +103,7 @@ export default class Loadable extends Module { return old_render.call(this); } + this.LoadableComponent.updateInstances(); }); } @@ -91,7 +123,14 @@ export default class Loadable extends Module { update(cmp) { for(const inst of this.LoadableComponent.instances) { - if ( inst?.props?.component === cmp ) + const type = inst?.props?.component; + if ( type && type === cmp ) + inst.forceUpdate(); + } + + for(const inst of this.ErrorBoundaryComponent.instances) { + const name = inst?.props?.name; + if ( name && name === cmp ) inst.forceUpdate(); } } diff --git a/src/sites/twitch-twilight/modules/player.jsx b/src/sites/twitch-twilight/modules/player.jsx index d48541c4..b2a6c2d2 100644 --- a/src/sites/twitch-twilight/modules/player.jsx +++ b/src/sites/twitch-twilight/modules/player.jsx @@ -138,6 +138,15 @@ export default class Player extends PlayerBase { } }); + this.settings.add('player.fullscreen.auto-chat', { + default: false, + ui: { + path: 'Player > General >> Fullscreen', + title: 'Automatically expand chat when entering fullscreen mode.', + component: 'setting-check-box' + } + }); + this.settings.add('player.hide-event-bar', { default: false, ui: { @@ -178,6 +187,8 @@ export default class Player extends PlayerBase { this.on(':fix-player', this.repositionPlayer, this); + this.on('site:fullscreen', this.maybeOpenChat, this); + this.TheatreHost.on('mount', inst => { inst._ffz_theater_start = Date.now(); this.tryTheatreMode(inst); @@ -195,6 +206,14 @@ export default class Player extends PlayerBase { this.PlayerSource.on('update', this.checkCarousel, this); } + maybeOpenChat() { + if ( ! this.settings.get('player.fullscreen.auto-chat') ) + return; + + this.parent.awaitElement('.right-column--collapsed .right-column__toggle-visibility button', document.fullscreenElement, 1000) + .then(el => el.click()); + } + shouldStopAutoplay() { return this.settings.get('player.no-autoplay') || (! this.settings.get('player.home.autoplay') && this.router.current?.name === 'front-page'); diff --git a/src/sites/twitch-twilight/styles/color_normalizer.scss b/src/sites/twitch-twilight/styles/color_normalizer.scss index 6c9e6eb4..b6dd3121 100644 --- a/src/sites/twitch-twilight/styles/color_normalizer.scss +++ b/src/sites/twitch-twilight/styles/color_normalizer.scss @@ -1,5 +1,6 @@ .tw-root--theme-dark, html { body, + .creator-chat-stats-carousel, .channel-header, .channel-root__right-column, .chat-viewers__pane, @@ -93,6 +94,14 @@ .ach-card--expanded .ach-card__inner { border-color: var(--color-border-brand) !important; } + + .creator-chat-stats-carousel__right-arrow { + background: linear-gradient(270deg, var(--color-background-body) 60%, transparent) !important; + } + + .creator-chat-stats-carousel__left-arrow { + background: linear-gradient(90deg, var(--color-background-body) 60%, transparent) !important; + } } html { diff --git a/src/utilities/compat/fine.js b/src/utilities/compat/fine.js index a2248b35..aecfc072 100644 --- a/src/utilities/compat/fine.js +++ b/src/utilities/compat/fine.js @@ -611,6 +611,18 @@ export class FineWrapper extends EventEmitter { fn(inst); } + updateInstances(node = null, max_depth = 1000) { + if ( ! this._class ) + return; + + const instances = this.fine.findAllMatching(node, n => n.constructor === this._class, max_depth); + + for(const inst of instances) { + inst._ffz_mounted = true; + this.instances.add(inst); + } + } + _set(cls, instances) { if ( this._class ) throw new Error('already have a class');