From 76b72b86c8d0ab6b97f5ade41d1c1403040743ad Mon Sep 17 00:00:00 2001 From: SirStendec Date: Fri, 5 Nov 2021 18:01:28 -0400 Subject: [PATCH] 4.29.3 * Added: Setting to hide the "Discover Luna" link in the top navigation. * Changed: Hide blocked categories from the directory's category list. * Fixed: Stream up-times not appearing in the directory. * Fixed: Error in error handler for PubSub. * API Added: `Dialog` now supports prepending its element to its container, rather than appending. * API Added: `tip.add_class` for adding additional classes to rich tooltips that may now have had their element created yet. --- package.json | 2 +- src/bridge.js | 9 +- src/clips.js | 7 +- src/main.js | 8 +- .../main_menu/components/setting-spacer.vue | 3 + src/player.js | 7 +- src/settings/index.js | 6 +- src/settings/providers.js | 11 +- src/sites/shared/player.jsx | 12 +- .../twitch-twilight/modules/bttv_compat.js | 3 + .../modules/chat/emote_menu.jsx | 17 +- .../twitch-twilight/modules/chat/index.js | 74 ++++++--- .../modules/css_tweaks/index.js | 16 +- .../modules/css_tweaks/styles/portrait.scss | 2 +- .../modules/directory/game.jsx | 2 +- .../modules/directory/index.jsx | 150 ++++++++---------- src/utilities/compat/subpump.js | 2 +- src/utilities/compat/webmunch.js | 3 + src/utilities/dialog.js | 20 ++- src/utilities/logging.js | 13 ++ src/utilities/tooltip.js | 3 +- styles/native/tag.scss | 5 + 22 files changed, 219 insertions(+), 156 deletions(-) create mode 100644 src/modules/main_menu/components/setting-spacer.vue diff --git a/package.json b/package.json index 3e726317..55b2a707 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "frankerfacez", "author": "Dan Salvato LLC", - "version": "4.29.2", + "version": "4.29.3", "description": "FrankerFaceZ is a Twitch enhancement suite.", "private": true, "license": "Apache-2.0", diff --git a/src/bridge.js b/src/bridge.js index d88f3b47..13723bc5 100644 --- a/src/bridge.js +++ b/src/bridge.js @@ -11,11 +11,13 @@ import SettingsManager from './settings/index'; class FFZBridge extends Module { constructor() { super(); - const start_time = performance.now(), - VER = FFZBridge.version_info; + const start_time = performance.now(); FFZBridge.instance = this; + this.host = 'null'; + this.flavor = 'bridge'; + this.name = 'ffz_bridge'; this.__state = 0; this.__modules.core = this; @@ -29,8 +31,7 @@ class FFZBridge extends Module { this.log.init = true; this.core_log = this.log.get('core'); - - this.log.info(`FrankerFaceZ Settings Bridge v${VER} (build ${VER.build}${VER.commit ? ` - commit ${VER.commit}` : ''}) (initial ${location})`); + this.log.hi(this); // ======================================================================== diff --git a/src/clips.js b/src/clips.js index 8629c73e..91a4ad16 100644 --- a/src/clips.js +++ b/src/clips.js @@ -21,11 +21,11 @@ import Chat from 'src/modules/chat'; class FrankerFaceZ extends Module { constructor() { super(); - const start_time = performance.now(), - VER = FrankerFaceZ.version_info; + const start_time = performance.now(); FrankerFaceZ.instance = this; + this.host = 'twitch'; this.flavor = 'clips'; this.name = 'ffz_clips'; this.__state = 0; @@ -42,8 +42,7 @@ class FrankerFaceZ extends Module { this.log.init = true; this.core_log = this.log.get('core'); - - this.log.info(`FrankerFaceZ Standalone Clips v${VER} (build ${VER.build}${VER.commit ? ` - commit ${VER.commit}` : ''}) (initial ${location})`); + this.log.hi(this); // ======================================================================== diff --git a/src/main.js b/src/main.js index f48f3db7..ff108559 100644 --- a/src/main.js +++ b/src/main.js @@ -22,11 +22,11 @@ import Vue from 'utilities/vue'; class FrankerFaceZ extends Module { constructor() { super(); - const start_time = performance.now(), - VER = FrankerFaceZ.version_info; + const start_time = performance.now(); FrankerFaceZ.instance = this; + this.host = 'twitch'; this.flavor = 'main'; this.name = 'frankerfacez'; this.__state = 0; @@ -46,8 +46,7 @@ class FrankerFaceZ extends Module { this.log.init = true; this.core_log = this.log.get('core'); - - this.log.info(`FrankerFaceZ v${VER} (build ${VER.build}${VER.commit ? ` - commit ${VER.commit}` : ''}) (initial ${location})`); + this.log.hi(this); // ======================================================================== @@ -190,6 +189,5 @@ FrankerFaceZ.utilities = { } - window.FrankerFaceZ = FrankerFaceZ; window.ffz = new FrankerFaceZ(); diff --git a/src/modules/main_menu/components/setting-spacer.vue b/src/modules/main_menu/components/setting-spacer.vue new file mode 100644 index 00000000..78a7129d --- /dev/null +++ b/src/modules/main_menu/components/setting-spacer.vue @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/src/player.js b/src/player.js index 2dd70dcd..431d01d6 100644 --- a/src/player.js +++ b/src/player.js @@ -18,11 +18,11 @@ import Site from './sites/player'; class FrankerFaceZ extends Module { constructor() { super(); - const start_time = performance.now(), - VER = FrankerFaceZ.version_info; + const start_time = performance.now(); FrankerFaceZ.instance = this; + this.host = 'twitch'; this.flavor = 'player'; this.name = 'ffz_player'; this.__state = 0; @@ -39,8 +39,7 @@ class FrankerFaceZ extends Module { this.log.init = true; this.core_log = this.log.get('core'); - - this.log.info(`FrankerFaceZ Standalone Player v${VER} (build ${VER.build}${VER.commit ? ` - commit ${VER.commit}` : ''}) (initial ${location})`); + this.log.hi(this); // ======================================================================== diff --git a/src/settings/index.js b/src/settings/index.js index 1bed6686..49fb9c00 100644 --- a/src/settings/index.js +++ b/src/settings/index.js @@ -52,7 +52,7 @@ export default class SettingsManager extends Module { for(const key in PROVIDERS) if ( has(PROVIDERS, key) ) { const provider = PROVIDERS[key]; - if ( provider.key && provider.supported() ) + if ( provider.key && provider.supported(this) ) this.providers[provider.key] = provider; } @@ -584,7 +584,7 @@ export default class SettingsManager extends Module { providers.sort((a,b) => b.priority - a.priority); for(const provider of providers) { - if ( provider.supported() && provider.hasContent && await provider.hasContent() ) // eslint-disable-line no-await-in-loop + if ( provider.supported(this) && provider.hasContent && await provider.hasContent(this) ) // eslint-disable-line no-await-in-loop return provider.key; } @@ -602,7 +602,7 @@ export default class SettingsManager extends Module { * from the current provider. */ async changeProvider(key, transfer) { - if ( ! this.providers[key] || ! this.providers[key].supported() ) + if ( ! this.providers[key] || ! this.providers[key].supported(this) ) throw new Error(`Invalid provider: ${key}`); // If we're changing to the current provider... well, that doesn't make diff --git a/src/settings/providers.js b/src/settings/providers.js index 1e0abc85..d52c93b8 100644 --- a/src/settings/providers.js +++ b/src/settings/providers.js @@ -9,7 +9,8 @@ import {EventEmitter} from 'utilities/events'; import {has} from 'utilities/object'; const DB_VERSION = 1, - NOT_WWW = window.location.host !== 'www.twitch.tv'; + NOT_WWW_TWITCH = window.location.host !== 'www.twitch.tv', + NOT_WWW_YT = window.location.host !== 'www.youtube.com'; // ============================================================================ @@ -1026,7 +1027,9 @@ export class CrossOriginStorageBridge extends SettingsProvider { this._last_id = 0; const frame = this.frame = document.createElement('iframe'); - frame.src = '//www.twitch.tv/p/ffz_bridge/'; + frame.src = this.manager.root.host === 'twitch' ? + '//www.twitch.tv/p/ffz_bridge/' : + '//www.youtube.com/__ffz_bridge/'; frame.id = 'ffz-settings-bridge'; frame.style.width = 0; frame.style.height = 0; @@ -1038,8 +1041,8 @@ export class CrossOriginStorageBridge extends SettingsProvider { // Static Properties - static supported() { return NOT_WWW; } - static hasContent() { return NOT_WWW; } + static supported(manager) { return manager.root.host === 'twitch' ? NOT_WWW_TWITCH : NOT_WWW_YT; } + static hasContent(manager) { return CrossOriginStorageBridge.supported(manager); } static key = 'cosb'; static priority = 100; diff --git a/src/sites/shared/player.jsx b/src/sites/shared/player.jsx index 91fb87e1..1e9aad38 100644 --- a/src/sites/shared/player.jsx +++ b/src/sites/shared/player.jsx @@ -643,8 +643,8 @@ export default class PlayerBase extends Module { this._ffz_installed = true; - if ( ! this._ffzUpdateVolume ) - this._ffzUpdateVolume = debounce(this.ffzUpdateVolume.bind(this)); + //if ( ! this._ffzUpdateVolume ) + // this._ffzUpdateVolume = debounce(this.ffzUpdateVolume.bind(this)); if ( ! this._ffzUpdateState ) this._ffzUpdateState = this.ffzUpdateState.bind(this); @@ -694,7 +694,7 @@ export default class PlayerBase extends Module { this.ffzStopAutoplay(); } - cls.prototype.ffzUpdateVolume = function() { + /*cls.prototype.ffzUpdateVolume = function() { if ( document.hidden ) return; @@ -708,7 +708,7 @@ export default class PlayerBase extends Module { player.setMuted(muted); } } - } + }*/ cls.prototype.ffzUninstall = function() { if ( this._ffz_state_raf ) @@ -1136,8 +1136,8 @@ export default class PlayerBase extends Module { this.addGainSlider(inst, false); this.addMetadata(inst); - if ( inst._ffzUpdateVolume ) - inst._ffzUpdateVolume(); + //if ( inst._ffzUpdateVolume ) + // inst._ffzUpdateVolume(); this.emit(':update-gui', inst); } diff --git a/src/sites/twitch-twilight/modules/bttv_compat.js b/src/sites/twitch-twilight/modules/bttv_compat.js index bdc371ac..a58ee5f5 100644 --- a/src/sites/twitch-twilight/modules/bttv_compat.js +++ b/src/sites/twitch-twilight/modules/bttv_compat.js @@ -40,6 +40,7 @@ export default class BTTVCompat extends Module { const settings = await this.awaitSettings(), waiter = () => this.updateContext(settings); + settings.on('changed.clickTwitchEmotes', waiter); settings.on('changed.bttvGIFEmotes', waiter); waiter(); @@ -62,6 +63,8 @@ export default class BTTVCompat extends Module { updateContext(settings) { this.settings.updateContext({ bttv: { + loaded: true, + emote_menu: settings.get('clickTwitchEmotes'), gifs: settings.get('bttvGIFEmotes') } }); diff --git a/src/sites/twitch-twilight/modules/chat/emote_menu.jsx b/src/sites/twitch-twilight/modules/chat/emote_menu.jsx index 800b3019..7da875f0 100644 --- a/src/sites/twitch-twilight/modules/chat/emote_menu.jsx +++ b/src/sites/twitch-twilight/modules/chat/emote_menu.jsx @@ -200,15 +200,19 @@ export default class EmoteMenu extends Module { }); this.settings.add('chat.emote-menu.icon', { - requires: ['chat.emote-menu.enabled'], + requires: ['chat.emote-menu.enabled', 'context.bttv.emote_menu'], default: false, process(ctx, val) { - return ctx.get('chat.emote-menu.enabled') ? val : false + if ( ! ctx.get('chat.emote-menu.enabled') ) + return false; + + return ctx.get('context.bttv.emote_menu') || val; }, ui: { path: 'Chat > Emote Menu >> Appearance', title: 'Replace the emote menu icon with the FFZ icon for that classic feel.', + description: '**Note:** This setting may be forcibly enabled if other emote menus are detected, to ensure you can visually identify the FFZ Emote Menu.', component: 'setting-check-box' } }); @@ -367,7 +371,6 @@ export default class EmoteMenu extends Module { this.chat.context.on('changed:chat.emote-menu.enabled', () => this.EmoteMenu.forceUpdate()); - //const fup = () => this.MenuWrapper.forceUpdate(); const rebuild = () => { for(const inst of this.MenuWrapper.instances) inst.rebuildData(); @@ -379,18 +382,12 @@ export default class EmoteMenu extends Module { this.chat.context.on('changed:chat.fix-bad-emotes', rebuild); this.chat.context.on('changed:chat.emote-menu.sort-emotes', rebuild); this.chat.context.on('changed:chat.emote-menu.sort-tiers-last', rebuild); - //this.chat.context.on('changed:chat.emote-menu.show-heading', fup); - //this.chat.context.on('changed:chat.emote-menu.show-search', fup); - //this.chat.context.on('changed:chat.emote-menu.reduced-padding', fup); - //this.chat.context.on('changed:chat.emote-menu.combine-tabs', fup); this.chat.context.on('changed:chat.emoji.style', this.updateEmojiVariables, this); - this.chat.context.on('changed:chat.emote-menu.icon', val => + this.chat.context.getChanges('chat.emote-menu.icon', val => this.css_tweaks.toggle('emote-menu', val)); - this.css_tweaks.toggle('emote-menu', this.chat.context.get('chat.emote-menu.icon')); - this.updateEmojiVariables(); this.css_tweaks.setVariable('emoji-menu--sheet', `//cdn.frankerfacez.com/static/emoji/images/sheet-twemoji-36.png`); diff --git a/src/sites/twitch-twilight/modules/chat/index.js b/src/sites/twitch-twilight/modules/chat/index.js index bb105f57..b3822187 100644 --- a/src/sites/twitch-twilight/modules/chat/index.js +++ b/src/sites/twitch-twilight/modules/chat/index.js @@ -875,8 +875,6 @@ export default class ChatHook extends Module { this.chat.context.on('changed:chat.filtering.highlight-mentions', this.updateMentionCSS, this); this.chat.context.on('changed:chat.filtering.highlight-tokens', this.updateMentionCSS, this); this.chat.context.on('changed:chat.filtering.mention-color', this.updateMentionCSS, this); - this.chat.context.on('changed:chat.filtering.clickable-mentions', val => this.css_tweaks.toggle('clickable-mentions', val)); - this.chat.context.on('changed:chat.filtering.bold-mentions', val => this.css_tweaks.toggle('chat-mention-no-bold', ! val)); this.chat.context.on('changed:chat.pin-resubs', val => { if ( val ) { this.updateInlineCallouts(); @@ -889,46 +887,74 @@ export default class ChatHook extends Module { this.CalloutSelector.forceUpdate(); }, this); - this.chat.context.on('changed:chat.input.show-mod-view', val => this.css_tweaks.toggleHide('mod-view', ! val)); - this.css_tweaks.toggleHide('mod-view', ! this.chat.context.get('chat.input.show-mod-view')); + this.chat.context.getChanges('chat.input.show-mod-view', val => + this.css_tweaks.toggleHide('mod-view', ! val)); - this.chat.context.on('changed:chat.lines.alternate', val => { - this.css_tweaks.toggle('chat-rows', val); - this.updateMentionCSS(); - }); + /*this.chat.context.on('changed:chat.input.show-mod-view', val => this.css_tweaks.toggleHide('mod-view', ! val)); + this.css_tweaks.toggleHide('mod-view', ! this.chat.context.get('chat.input.show-mod-view'));*/ - this.chat.context.on('changed:chat.lines.padding', val => + this.chat.context.getChanges('chat.lines.padding', val => this.css_tweaks.toggle('chat-padding', val)); - this.chat.context.on('changed:chat.bits.show', val => + /*this.chat.context.on('changed:chat.lines.padding', val => + this.css_tweaks.toggle('chat-padding', val)); + this.css_tweaks.toggle('chat-padding', this.chat.context.get('chat.lines.padding'));*/ + + this.chat.context.getChanges('chat.bits.show', val => this.css_tweaks.toggle('hide-bits', !val)); - this.chat.context.on('changed:chat.bits.show-pinned', val => + + /*this.chat.context.on('changed:chat.bits.show', val => + this.css_tweaks.toggle('hide-bits', !val)); + this.css_tweaks.toggle('hide-bits', !this.chat.context.get('chat.bits.show'));*/ + + this.chat.context.getChanges('chat.bits.show-pinned', val => this.css_tweaks.toggleHide('pinned-cheer', !val)); - this.chat.context.on('changed:chat.filtering.deleted-style', val => { + /*this.chat.context.on('changed:chat.bits.show-pinned', val => + this.css_tweaks.toggleHide('pinned-cheer', !val)); + this.css_tweaks.toggleHide('pinned-cheer', !this.chat.context.get('chat.bits.show-pinned'));*/ + + this.chat.context.getChanges('chat.filtering.deleted-style', val => { this.css_tweaks.toggle('chat-deleted-strike', val === 1 || val === 2); this.css_tweaks.toggle('chat-deleted-fade', val < 2); }); - const val = this.chat.context.get('chat.filtering.deleted-style'); - this.css_tweaks.toggle('chat-deleted-strike', val === 1 || val === 2); - this.css_tweaks.toggle('chat-deleted-fade', val < 2); + this.chat.context.getChanges('chat.filtering.clickable-mentions', val => + this.css_tweaks.toggle('clickable-mentions', val)); - this.css_tweaks.toggle('clickable-mentions', this.chat.context.get('chat.filtering.clickable-mentions')); - this.css_tweaks.toggle('chat-mention-no-bold', ! this.chat.context.get('chat.filtering.bold-mentions')); + /*this.chat.context.on('changed:chat.filtering.clickable-mentions', val => + this.css_tweaks.toggle('clickable-mentions', val)); + this.css_tweaks.toggle('clickable-mentions', this.chat.context.get('chat.filtering.clickable-mentions'));*/ - this.chat.context.on('changed:chat.hide-community-highlights', val => this.css_tweaks.toggleHide('community-highlights', val)); + this.chat.context.getChanges('chat.filtering.bold-mentions', val => + this.css_tweaks.toggle('chat-mention-no-bold', ! val)); - this.css_tweaks.toggleHide('community-highlights', this.chat.context.get('chat.hide-community-highlights')); - this.css_tweaks.toggleHide('pinned-cheer', !this.chat.context.get('chat.bits.show-pinned')); - this.css_tweaks.toggle('hide-bits', !this.chat.context.get('chat.bits.show')); - this.css_tweaks.toggle('chat-rows', this.chat.context.get('chat.lines.alternate')); - this.css_tweaks.toggle('chat-padding', this.chat.context.get('chat.lines.padding')); + /*this.chat.context.on('changed:chat.filtering.bold-mentions', val => + this.css_tweaks.toggle('chat-mention-no-bold', ! val)); + this.css_tweaks.toggle('chat-mention-no-bold', ! this.chat.context.get('chat.filtering.bold-mentions'));*/ + + this.chat.context.getChanges('chat.hide-community-highlights', val => + this.css_tweaks.toggleHide('community-highlights', val)); + + /*this.chat.context.on('changed:chat.hide-community-highlights', val => + this.css_tweaks.toggleHide('community-highlights', val)); + this.css_tweaks.toggleHide('community-highlights', this.chat.context.get('chat.hide-community-highlights'));*/ + + this.chat.context.getChanges('chat.lines.alternate', val => { + this.css_tweaks.toggle('chat-rows', val); + this.updateMentionCSS(); + }); + + /*this.chat.context.on('changed:chat.lines.alternate', val => { + this.css_tweaks.toggle('chat-rows', val); + this.updateMentionCSS(); + }); + this.css_tweaks.toggle('chat-rows', this.chat.context.get('chat.lines.alternate'));*/ this.updateChatCSS(); this.updateColors(); this.updateLineBorders(); - this.updateMentionCSS(); + //this.updateMentionCSS(); this.RaidController.on('mount', this.wrapRaidController, this); this.RaidController.on('update', this.noAutoRaids, this); diff --git a/src/sites/twitch-twilight/modules/css_tweaks/index.js b/src/sites/twitch-twilight/modules/css_tweaks/index.js index 63ea3326..80bc8b3c 100644 --- a/src/sites/twitch-twilight/modules/css_tweaks/index.js +++ b/src/sites/twitch-twilight/modules/css_tweaks/index.js @@ -16,11 +16,11 @@ const CLASSES = { '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)', + 'side-rec-channels': '.side-nav .recommended-channels,.side-nav .side-nav-section + .side-nav-section:not(.online-friends):not(.bd--shelf)', //'side-rec-friends': '.side-nav .recommended-friends', 'side-friends': '.side-nav .online-friends', 'side-closed-friends': '.side-nav--collapsed .online-friends', - 'side-closed-rec-channels': '.side-nav--collapsed .recommended-channels,.side-nav--collapsed .side-nav-section + .side-nav-section:not(.online-friends)', + 'side-closed-rec-channels': '.side-nav--collapsed .recommended-channels,.side-nav--collapsed .side-nav-section + .side-nav-section:not(.online-friends):not(.bd--shelf)', 'side-offline-channels': '.ffz--side-nav-card-offline', 'side-rerun-channels': '.side-nav .ffz--side-nav-card-rerun', 'modview-hide-info': '.modview-player-widget__hide-stream-info', @@ -28,6 +28,7 @@ const CLASSES = { 'community-highlights': '.community-highlight-stack__card', 'prime-offers': '.top-nav__prime', + 'discover-luna': '.top-nav__external-link[data-a-target="try-presto-link"]', 'player-gain-volume': '.video-player__container[data-compressed="true"] .volume-slider__slider-container:not(.ffz--player-gain)', @@ -61,7 +62,6 @@ export default class CSSTweaks extends Module { this.chunks = {}; this.chunks_loaded = false; - // Layout this.settings.add('metadata.modview.hide-info', { @@ -333,6 +333,15 @@ export default class CSSTweaks extends Module { changed: val => this.toggleHide('prime-offers', !val) }); + this.settings.add('layout.hide-discover-luna', { + default: false, + ui: { + path: 'Appearance > Layout >> Top Navigation', + title: 'Hide the "Discover Luna" link.', + component: 'setting-check-box' + }, + changed: val => this.toggleHide('discover-luna', val) + }); // Chat @@ -446,6 +455,7 @@ export default class CSSTweaks extends Module { this.toggle('hide-side-nav', !this.settings.get('layout.side-nav.show')); //this.toggleHide('side-rec-friends', !this.settings.get('layout.side-nav.show-rec-friends')); 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.toggle('hide-unfollow-button', this.settings.get('channel.hide-unfollow')); diff --git a/src/sites/twitch-twilight/modules/css_tweaks/styles/portrait.scss b/src/sites/twitch-twilight/modules/css_tweaks/styles/portrait.scss index e2c96a1b..21640eae 100644 --- a/src/sites/twitch-twilight/modules/css_tweaks/styles/portrait.scss +++ b/src/sites/twitch-twilight/modules/css_tweaks/styles/portrait.scss @@ -70,7 +70,7 @@ .right-column { display: unset !important; position: fixed !important; - z-index: 4000; + z-index: 2000; bottom: 0 !important; left: 0 !important; right: 0 !important; diff --git a/src/sites/twitch-twilight/modules/directory/game.jsx b/src/sites/twitch-twilight/modules/directory/game.jsx index 181dff0b..560f19c9 100644 --- a/src/sites/twitch-twilight/modules/directory/game.jsx +++ b/src/sites/twitch-twilight/modules/directory/game.jsx @@ -51,7 +51,7 @@ export default class Game extends SiteModule { }); this.settings.provider.on('changed', key => { - if ( key === 'directory.game.blocked-games' || key === 'directory.game.hidden-thumbnails' ) { + if ( key === 'directory.game.blocked-games' || key === 'directory.game.hidden-thumbnails' || key === 'directory.game.blocked-tags' ) { this.parent.updateCards(); for(const inst of this.GameHeader.instances) diff --git a/src/sites/twitch-twilight/modules/directory/index.jsx b/src/sites/twitch-twilight/modules/directory/index.jsx index d015c3bc..0347fb30 100644 --- a/src/sites/twitch-twilight/modules/directory/index.jsx +++ b/src/sites/twitch-twilight/modules/directory/index.jsx @@ -47,6 +47,11 @@ export default class Directory extends SiteModule { DIR_ROUTES, null, 0, 0 ); + this.DirectoryGameCard = this.elemental.define( + 'directory-game-card', '.game-card[data-a-id]', + DIR_ROUTES, null, 0, 0 + ); + this.DirectoryShelf = this.fine.define( 'directory-shelf', n => n.shouldRenderNode && n.props && n.props.shelf, @@ -213,9 +218,34 @@ export default class Directory extends SiteModule { this.DirectoryCard.on('unmount', this.clearCard, this); this.DirectoryCard.each(el => this.updateCard(el)); + this.DirectoryGameCard.on('mount', this.updateGameCard, this); + this.DirectoryGameCard.on('mutate', this.updateGameCard, this); + //this.DirectoryGameCard.on('unmount', this.clearGameCard, this); + this.DirectoryGameCard.each(el => this.updateGameCard(el)); + const t = this; this.DirectoryShelf.ready(cls => { + const old_should_render = cls.prototype.shouldRenderNode; + cls.prototype.shouldRenderNode = function(node, ...args) { + try { + let game; + if ( node.__typename === 'Game' ) + game = node.name; + else if ( node.game ) + game = node.game.name; + + if ( game && t.settings.provider.get('directory.game.blocked-games', []).includes(game) ) + return false; + + } catch(err) { + t.log.capture(err); + t.log.error(err); + } + + return old_should_render.call(this, node, ...args); + } + const old_render = cls.prototype.render; cls.prototype.render = function() { try { @@ -234,87 +264,45 @@ export default class Directory extends SiteModule { this.DirectoryShelf.forceUpdate(); }); - - /*this.DirectoryCard.ready((cls, instances) => { - //const old_render = cls.prototype.render, - const old_render_iconic = cls.prototype.renderIconicImage, - old_render_titles = cls.prototype.renderTitles; - - /*cls.prototype.render = function() { - if ( get('props.streamType', this) === 'rerun' && t.settings.get('directory.hide-vodcasts') ) - return null; - - return old_render.call(this); - }* - - cls.prototype.renderIconicImage = function() { - if ( this.props.context !== CARD_CONTEXTS.SingleChannelList && - ! t.settings.get('directory.show-channel-avatars') ) - return; - - return old_render_iconic.call(this); - } - - cls.prototype.renderTitles = function() { - const nodes = get(get('props.channelLogin', this), t.following.hosts); - if ( this.props.hostedByChannelLogin == null || ! nodes || ! nodes.length ) - return old_render_titles.call(this); - - const channel = nodes[0].hosting, - stream = channel.stream, - game = stream && stream.game, - - channel_url = `/${channel.login}`, - game_url = game && `/directory/game/${stream.game.name}`, - - user_link = {channel.displayName}, - game_link = game && {game.name}; - - return (
- -

{stream.title}

-
-
-
-

{ - game ? - game.id == CREATIVE_ID ? - t.i18n.tList('directory.user-creative', '{user} being {game}', { - user: user_link, - game: game_link - }) : - t.i18n.tList('directory.user-playing', '{user} playing {game}', { - user: user_link, - game: game_link - }) - : user_link - }

-
-
-

{ - nodes.length > 1 ? - t.i18n.t('directory.hosted.by-many', 'Hosted by {count,number} channel{count,en_plural}', nodes.length) : - t.i18n.tList('directory.hosted.by-one', 'Hosted by {user}', { - user: {nodes[0].displayName} - }) - }

-
-
-
); - } - - this.DirectoryCard.forceUpdate(); - - for(const inst of instances) - this.updateCard(inst); - }); - - this.DirectoryCard.on('update', this.updateCard, this); - this.DirectoryCard.on('mount', this.updateCard, this); - this.DirectoryCard.on('unmount', this.clearCard, this);*/ } + updateGameCard(el) { + const react = this.fine.getReactInstance(el); + if ( ! react ) + return; + + const props = react.return?.memoizedProps; + if ( ! props?.trackingProps?.category ) + return; + + const game = props.trackingProps.category, + tags = props.tagListProps?.tags; + + let bad_tag = false; + + if ( Array.isArray(tags) ) { + const bad_tags = this.settings.provider.get('directory.game.blocked-tags', []); + if ( bad_tags.length ) { + for(const tag of tags) { + if ( tag?.id && bad_tags.includes(tag.id) ) { + bad_tag = true; + break; + } + } + } + } + + const should_hide = bad_tag || this.settings.provider.get('directory.game.blocked-games', []).includes(game); + + let hide_container = el.closest('.tw-tower > div'); + if ( ! hide_container ) + hide_container = el; + + if ( hide_container.querySelectorAll('a[data-a-target="tw-box-art-card-link"]').length < 2 ) + hide_container.classList.toggle('tw-hide', should_hide); + } + updateCard(el) { const react = this.fine.getReactInstance(el); @@ -340,7 +328,7 @@ export default class Directory extends SiteModule { el.dataset.ffzType = props.streamType; if ( Array.isArray(tags) ) { - const bad_tags = this.settings.provider.get('directory.game.hidden-tags', []); + const bad_tags = this.settings.provider.get('directory.game.blocked-tags', []); if ( bad_tags.length ) { for(const tag of tags) { if ( tag?.id && bad_tags.includes(tag.id) ) { @@ -368,6 +356,8 @@ export default class Directory extends SiteModule { updateCards() { this.DirectoryCard.each(el => this.updateCard(el)); + this.DirectoryGameCard.each(el => this.updateGameCard(el)); + this.DirectoryShelf.forceUpdate(); this.emit(':update-cards'); } @@ -381,7 +371,7 @@ export default class Directory extends SiteModule { if ( ! document.contains(el) ) return this.clearUptime(el); - const container = el.querySelector('.tw-media-card-image__corners'), + const container = el.querySelector('a[data-a-target="preview-card-image-link"] > div'), setting = this.settings.get('directory.uptime'); if ( ! container || setting === 0 || props.viewCount || props.animatedImageProps ) diff --git a/src/utilities/compat/subpump.js b/src/utilities/compat/subpump.js index 5eb84836..eb4d6489 100644 --- a/src/utilities/compat/subpump.js +++ b/src/utilities/compat/subpump.js @@ -99,7 +99,7 @@ export default class Subpump extends Module { } } catch(err) { - this.log.error('Error processing PubSub event.', err); + t.log.error('Error processing PubSub event.', err); } return orig_message.call(this, e); diff --git a/src/utilities/compat/webmunch.js b/src/utilities/compat/webmunch.js index ba5f6481..791d2aab 100644 --- a/src/utilities/compat/webmunch.js +++ b/src/utilities/compat/webmunch.js @@ -474,6 +474,9 @@ export default class WebMunch extends Module { this._required_ids.add(id); + if ( ! require.m[id] ) + this.log.warn('Tried requiring module that isn\'t loaded', id); + const mod = require(id); if ( mod ) { const ret = predicate(mod); diff --git a/src/utilities/dialog.js b/src/utilities/dialog.js index a5fdd5e9..dae63719 100644 --- a/src/utilities/dialog.js +++ b/src/utilities/dialog.js @@ -24,6 +24,8 @@ export class Dialog extends EventEmitter { this._maximized = options.maximized || false; this._exclusive = options.exclusive || false; + this.prepend = options.prepend || false; + this._element = null; this._visible = false; @@ -149,7 +151,10 @@ export class Dialog extends EventEmitter { if ( el instanceof Promise ) { el.then(e => { this._element = e; - container.appendChild(e); + if ( this.prepend ) + container.insertBefore(e, container.firstChild); + else + container.appendChild(e); this.emit('show'); }).catch(err => { this.emit('error', err); @@ -161,7 +166,10 @@ export class Dialog extends EventEmitter { this._element = el; } - container.appendChild(this._element); + if ( this.prepend ) + container.insertBefore(this._element, container.firstChild); + else + container.appendChild(this._element); this.emit('show'); } @@ -185,8 +193,12 @@ export class Dialog extends EventEmitter { old_container.classList.remove('ffz-has-dialog'); this._element.remove(); - if ( container ) - container.appendChild(this._element); + if ( container ) { + if ( this.prepend ) + container.insertBefore(this._element, container.firstChild); + else + container.appendChild(this._element); + } this.emit('resize'); } diff --git a/src/utilities/logging.js b/src/utilities/logging.js index 06df7456..da0a3aed 100644 --- a/src/utilities/logging.js +++ b/src/utilities/logging.js @@ -45,6 +45,19 @@ export class Logger { this.children = {}; } + hi(core) { + const VER = core.constructor.version_info; + this.info(`FrankerFaceZ v${VER} (s:${core.host} f:${core.flavor} b:${VER.build} c:${VER.commit || 'null'})`); + + try { + const loc = new URL(location); + loc.search = ''; + this.info(`Initial URL: ${loc}`); + } catch(err) { + this.warn(`Unable to read location.`, err); + } + } + get(name, level) { if ( ! this.children[name] ) this.children[name] = new Logger(this, (this.name ? `${this.name}.${name}` : name), level); diff --git a/src/utilities/tooltip.js b/src/utilities/tooltip.js index a429fda2..e9c43d8c 100644 --- a/src/utilities/tooltip.js +++ b/src/utilities/tooltip.js @@ -301,7 +301,8 @@ export class Tooltip { inner.classList.add(`${opts.innerClass}--align-${tip.align}`); if ( tip.add_class ) { - inner.classList.add(tip.add_class); + for(const cls of Array.isArray(tip.add_class) ? tip.add_class : [tip.add_class]) + inner.classList.add(cls); tip.add_class = undefined; } diff --git a/styles/native/tag.scss b/styles/native/tag.scss index 5c3be3bb..1d4e403a 100644 --- a/styles/native/tag.scss +++ b/styles/native/tag.scss @@ -39,6 +39,11 @@ width: 1.6rem; } + .ffz__tooltip & { + background: rgba(128,128,128,0.3); + color: var(--color-text-tooltip); + } + &--overlay { background: rgba(0,0,0,0.3); border: var(--border-width-tag) solid var(--color-border-input-overlay);