From 38e557e8093ad5fd529086940a3515ad8a9dc4fb Mon Sep 17 00:00:00 2001 From: SirStendec Date: Fri, 29 Mar 2024 13:33:14 -0400 Subject: [PATCH] 4.72.0 * Fixed: The button to expand chat not appearing when using theater mode along with Swap Sidebars. * Fixed: Emote / link cards not appearing correctly when using moderator view. * API Added: `searchParentNode(input: InputNode, criteria: (node: ReactNode) => boolean)` method to `site.fine` for finding React internal nodes, useful for locating stateless components for extracting props. * API Added: `getRenderers()`, `getActions()` methods for `chat.actions` to get bulk data. * API Added: `getBadge(id: string | number)` method for `chat.badges` to get a badge. * API Added: `getUser(...).getBadges()` method for `chat` to get a user's badges. * API Added: The `action-editor` component for `chat.actions` has an additional `extra_appearance_editor` field for adding additional inputs. * API Changed: The `removeAction(...keys: string[])` and `removeRenderer(...keys: string[])` methods for `chat.actions` now support multiple keys to allow for more efficient removal. --- package.json | 2 +- src/modules/chat/actions/actions.jsx | 100 +++++++++++------- src/modules/chat/badges.jsx | 5 + src/modules/chat/user.ts | 7 ++ src/modules/emote_card/components/card.vue | 6 +- .../main_menu/components/action-editor.vue | 42 +++++++- .../main_menu/components/chat-actions.vue | 3 +- .../css_tweaks/styles/swap-sidebars.scss | 7 +- src/sites/twitch-twilight/styles/fixes.scss | 5 +- src/sites/twitch-twilight/styles/main.scss | 2 +- src/utilities/compat/fine.ts | 43 +++++++- 11 files changed, 170 insertions(+), 52 deletions(-) diff --git a/package.json b/package.json index 36171324..d41c58da 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "frankerfacez", "author": "Dan Salvato LLC", - "version": "4.71.0", + "version": "4.72.0", "description": "FrankerFaceZ is a Twitch enhancement suite.", "private": true, "license": "Apache-2.0", diff --git a/src/modules/chat/actions/actions.jsx b/src/modules/chat/actions/actions.jsx index 54d07018..4e0012ee 100644 --- a/src/modules/chat/actions/actions.jsx +++ b/src/modules/chat/actions/actions.jsx @@ -27,6 +27,11 @@ export default class Actions extends Module { this.actions = {}; this.renderers = {}; + this.filterAction = (x) => x.appearance && + this.renderers[x.appearance.type] && + (! this.renderers[x.appearance.type].load || this.renderers[x.appearance.type].load(x.appearance)) && + (! x.action || this.actions[x.action]); + this.settings.add('chat.actions.size', { default: 16, ui: { @@ -82,11 +87,7 @@ export default class Actions extends Module { this.settings.add('chat.actions.hover', { process: (ctx, val) => - val.filter(x => x.appearance && - this.renderers[x.appearance.type] && - (! this.renderers[x.appearance.type].load || this.renderers[x.appearance.type].load(x.appearance)) && - (! x.action || this.actions[x.action]) - ), + val.filter(this.filterAction), default: [ {v: {action: 'pin', appearance: {type: 'icon', icon: 'ffz-i-pin'}, options: {}, display: {mod_icons: true}}}, @@ -119,11 +120,7 @@ export default class Actions extends Module { this.settings.add('chat.actions.inline', { // Filter out actions process: (ctx, val) => - val.filter(x => x.appearance && - this.renderers[x.appearance.type] && - (! this.renderers[x.appearance.type].load || this.renderers[x.appearance.type].load(x.appearance)) && - (! x.action || this.actions[x.action]) - ), + val.filter(this.filterAction), default: [ {v: {action: 'ban', appearance: {type: 'icon', icon: 'ffz-i-block'}, options: {}, display: {mod: true, mod_icons: true, deleted: false}}}, @@ -157,11 +154,7 @@ export default class Actions extends Module { this.settings.add('chat.actions.user-context', { // Filter out actions process: (ctx, val) => - val.filter(x => x.type || (x.appearance && - this.renderers[x.appearance.type] && - (! this.renderers[x.appearance.type].load || this.renderers[x.appearance.type].load(x.appearance)) && - (! x.action || this.actions[x.action]) - )), + val.filter(x => x.type || this.filterAction(x)), default: [], type: 'array_merge', @@ -187,11 +180,7 @@ export default class Actions extends Module { this.settings.add('chat.actions.room', { // Filter out actions process: (ctx, val) => - val.filter(x => x.type || (x.appearance && - this.renderers[x.appearance.type] && - (! this.renderers[x.appearance.type].load || this.renderers[x.appearance.type].load(x.appearance)) && - (! x.action || this.actions[x.action]) - )), + val.filter(x => x.type || this.filterAction(x)), default: [], type: 'array_merge', @@ -316,20 +305,24 @@ export default class Actions extends Module { } if ( is_dev ) { - overrides.removeAction = key => { - const existing = this.actions[key]; - if ( existing && existing.__source !== addon_id ) - module.log.warn('[DEV-CHECK] Removed un-owned action with actions.removeAction:', key, ' owner:', existing.__source ?? 'ffz'); + overrides.removeAction = (...key) => { + for(const entry of key) { + const existing = this.actions[entry]; + if ( existing && existing.__source !== addon_id ) + module.log.warn('[DEV-CHECK] Removed un-owned action with actions.removeAction:', entry, ' owner:', existing.__source ?? 'ffz'); + } - return this.removeAction(key); + return this.removeAction(...key); }; - overrides.removeRenderer = key => { - const existing = this.renderers[key]; - if ( existing && existing.__source !== addon_id ) - module.log.warn('[DEV-CHECK] Removed un-owned renderer with actions.removeRenderer:', key, ' owner:', existing.__source ?? 'ffz'); + overrides.removeRenderer = (...key) => { + for(const entry of key) { + const existing = this.renderers[entry]; + if ( existing && existing.__source !== addon_id ) + module.log.warn('[DEV-CHECK] Removed un-owned renderer with actions.removeRenderer:', entry, ' owner:', existing.__source ?? 'ffz'); + } - return this.removeRenderer(key); + return this.removeRenderer(...key); } warnings.actions = 'Please use addAction() or removeAction()'; @@ -367,22 +360,49 @@ export default class Actions extends Module { this._updateContexts(); } + getActions() { + return {...this.actions} + } - removeAction(key) { - if ( ! has(this.actions, key) ) - return; + getAction(key) { + return this.actions[key] ?? null; + } - delete this.actions[key]; - this._updateContexts(); + getRenderer(key) { + return this.renderers[key] ?? null; + } + + getRenderers() { + return {...this.renderers} + } + + removeAction(...keys) { + let changed = false; + for(const entry of keys) { + if ( ! has(this.actions, entry) ) + continue; + + delete this.actions[entry]; + changed = true; + } + + if ( changed ) + this._updateContexts(); } - removeRenderer(key) { - if ( ! has(this.renderers, key) ) - return; + removeRenderer(...keys) { + let changed = false; + for(const entry of keys) { + if ( ! has(this.renderers, entry) ) + return; - delete this.renderers[key]; - this._updateContexts(); + delete this.renderers[entry]; + changed = true; + } + + if ( changed ) + this._updateContexts(); } diff --git a/src/modules/chat/badges.jsx b/src/modules/chat/badges.jsx index 551cf1a4..de888f75 100644 --- a/src/modules/chat/badges.jsx +++ b/src/modules/chat/badges.jsx @@ -1223,6 +1223,11 @@ export default class Badges extends Module { } + getBadge(badge_id) { + return this.badges[badge_id] ?? null; + } + + removeBadge(badge_id, generate_css = true) { if ( ! this.badges[badge_id] ) return; diff --git a/src/modules/chat/user.ts b/src/modules/chat/user.ts index 3d42d2cb..50cb962e 100644 --- a/src/modules/chat/user.ts +++ b/src/modules/chat/user.ts @@ -154,6 +154,13 @@ export default class User { } + getBadges() { + if ( this.badges ) + return [...this.badges._cache]; + return []; + } + + getBadge(badge_id: string) { if ( this.badges ) for(const badge of this.badges._cache) diff --git a/src/modules/emote_card/components/card.vue b/src/modules/emote_card/components/card.vue index 433b0751..0d28a2fd 100644 --- a/src/modules/emote_card/components/card.vue +++ b/src/modules/emote_card/components/card.vue @@ -370,8 +370,8 @@ export default { if ( ! parent ) parent = document.body; - const box = el.getBoundingClientRect(), - pbox = parent.getBoundingClientRect(); + const box = el.getBoundingClientRect(); + let pbox = parent.getBoundingClientRect(); if ( box.top < pbox.top ) { el.style.top = `${el.offsetTop + (pbox.top - box.top)}px`; @@ -447,4 +447,4 @@ export default { } - \ No newline at end of file + diff --git a/src/modules/main_menu/components/action-editor.vue b/src/modules/main_menu/components/action-editor.vue index 27cfd4ab..6d85a8e9 100644 --- a/src/modules/main_menu/components/action-editor.vue +++ b/src/modules/main_menu/components/action-editor.vue @@ -79,6 +79,12 @@ v-if="renderer" v-model="edit_data.appearance" /> + +
@@ -128,6 +134,28 @@ +
+ + + +
+