diff --git a/package.json b/package.json index e1f0c4d4..f3f3fd5b 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "frankerfacez", "author": "Dan Salvato LLC", - "version": "4.22.2", + "version": "4.22.3", "description": "FrankerFaceZ is a Twitch enhancement suite.", "private": true, "license": "Apache-2.0", diff --git a/src/modules/chat/index.js b/src/modules/chat/index.js index 3c60e635..cf432e7a 100644 --- a/src/modules/chat/index.js +++ b/src/modules/chat/index.js @@ -873,7 +873,7 @@ export default class Chat extends Module { component: 'setting-text-box', type: 'number', process: 'to_int', - description: 'Mentions of your name have this priority for the purpose of highlighting. See [Chat > Filtering > Highlight](~) for more details.' + description: 'Mentions of your name have this priority for the purpose of highlighting. See [Chat > Filtering > Highlight](~chat.filtering.highlight) for more details.' } }); diff --git a/src/modules/main_menu/components/addon-list.vue b/src/modules/main_menu/components/addon-list.vue index de213704..d8fa0c5e 100644 --- a/src/modules/main_menu/components/addon-list.vue +++ b/src/modules/main_menu/components/addon-list.vue @@ -63,7 +63,7 @@ /> -
+
this.shouldShow(addon)); }, @@ -180,10 +184,8 @@ export default { if ( value && value.length ) for(const addon of this.item.getAddons()) - if ( addon.unlisted && addon.id === value ) { - this.unlisted.push(value); - break; - } + if ( addon.unlisted && (addon.id === value || (addon.short_name && addon.short_name.toLowerCase() === value) || (addon.name && addon.name.toLowerCase() === value)) ) + this.unlisted.push(addon.id); this.$refs.unlisted.value = ''; this.closeUnlisted(); diff --git a/src/modules/main_menu/components/home-page.vue b/src/modules/main_menu/components/home-page.vue index 2547c712..c167a786 100644 --- a/src/modules/main_menu/components/home-page.vue +++ b/src/modules/main_menu/components/home-page.vue @@ -267,23 +267,28 @@ export default { if ( addons ) for(const [key, addon] of Object.entries(addons)) { const enabled = addon_module.isAddonEnabled(key), - copy = { - key, - enabled, - icon: addon.icon, - name: addon.name, - name_i18n: addon.name_i18n, - updated: addon.updated, - settings: addon.settings, - version: addon.version - }; + is_new = addon.created && addon.created >= week_ago, + is_updated = enabled && addon.updated && addon.updated >= week_ago; - if ( addon.created && addon.created >= week_ago ) + if ( ! is_updated && ! (is_new && ! enabled && ! addon.unlisted) ) + continue; + + const copy = { + key, + enabled, + icon: addon.icon, + name: addon.name, + name_i18n: addon.name_i18n, + updated: addon.updated, + settings: addon.settings, + version: addon.version + }; + + if ( is_new ) new_out.push(copy); - if ( addon.updated && addon.updated >= week_ago && enabled ) { + if ( is_updated ) out.push(copy); - } } out.sort((a,b) => b.updated - a.updated); diff --git a/src/sites/twitch-twilight/modules/theme/index.js b/src/sites/twitch-twilight/modules/theme/index.js index 2d7c2a16..47d6f196 100644 --- a/src/sites/twitch-twilight/modules/theme/index.js +++ b/src/sites/twitch-twilight/modules/theme/index.js @@ -485,7 +485,7 @@ The CSS loaded by this setting is far too heavy and can cause performance issues this.toggleNormalizer(chat_bits.length || bits.length); if ( bits.length ) - this.css_tweaks.set('colors', `body {${bits.join('\n')}}.channel-info-content .tw-accent-region,.channel-info-content .gocjHQ{${accent_bits.join('\n')}}`); + this.css_tweaks.set('colors', `body,body .tw-root--theme-light,body .tw-root--theme-dark {${bits.join('\n')}}.channel-info-content .tw-accent-region,.channel-info-content .gocjHQ{${accent_bits.join('\n')}}`); else this.css_tweaks.delete('colors'); } diff --git a/src/utilities/data/user-bulk.gql b/src/utilities/data/user-bulk.gql new file mode 100644 index 00000000..ac8291b4 --- /dev/null +++ b/src/utilities/data/user-bulk.gql @@ -0,0 +1,8 @@ +query FFZ_UserBulk($ids: [ID!], $logins: [String!]) { + users(ids: $ids, logins: $logins) { + id + login + displayName + profileImageURL(width: 50) + } +} \ No newline at end of file diff --git a/src/utilities/filtering.js b/src/utilities/filtering.js index d589f77c..22bb8f5a 100644 --- a/src/utilities/filtering.js +++ b/src/utilities/filtering.js @@ -26,8 +26,15 @@ export function createTester(rules, filter_types, inverted = false, or = false, continue; } + // Construct the test. If no test is returned, we skip this filter. + // This can happen depending on configuration rendering a method + // pointless. + const test = type.createTest(rule.data, filter_types, rebuild); + if ( ! test ) + continue; + i++; - tests.push(type.createTest(rule.data, filter_types, rebuild)); + tests.push(test); names.push(`f${i}`); } diff --git a/src/utilities/twitch-data.js b/src/utilities/twitch-data.js index 98fab47a..1bdc1169 100644 --- a/src/utilities/twitch-data.js +++ b/src/utilities/twitch-data.js @@ -23,6 +23,9 @@ export default class TwitchData extends Module { this.inject('site.apollo'); + this._waiting_user_ids = new Map; + this._waiting_user_logins = new Map; + this._waiting_stream_ids = new Map; this._waiting_stream_logins = new Map; @@ -268,6 +271,130 @@ export default class TwitchData extends Module { } + /** + * Fetch basic information on a user from Twitch. This is automatically batched + * for performance, but not directly cached. Either an id or login must be provided. + * + * @param {Number|String} [id] The ID of the channel + * @param {String} [login] The username of the channel + * + * @returns {Promise} A basic user object. + */ + getUserBasic(id, login) { + return new Promise((s, f) => { + if ( id ) { + if ( this._waiting_user_ids.has(id) ) + this._waiting_user_ids.get(id).push([s,f]); + else + this._waiting_user_ids.set(id, [[s,f]]); + } else if ( login ) { + if ( this._waiting_user_logins.has(login) ) + this._waiting_user_logins.get(login).push([s,f]); + else + this._waiting_user_logins.set(login, [[s,f]]); + } else + f('id and login cannot both be null'); + + if ( ! this._loading_users ) + this._loadUsers(); + }) + } + + async _loadUsers() { + if ( this._loading_users ) + return; + + this._loading_users = true; + + // Get the first 50... things. + const ids = [...this._waiting_user_ids.keys()].slice(0, 50), + remaining = 50 - ids.length, + logins = remaining > 0 ? [...this._waiting_user_logins.keys()].slice(0, remaining) : []; + + let nodes; + + try { + const data = await this.queryApollo({ + query: await import(/* webpackChunkName: 'queries' */ './data/user-bulk.gql'), + variables: { + ids: ids.length ? ids : null, + logins: logins.length ? logins : null + } + }); + + nodes = get('data.users', data); + + } catch(err) { + for(const id of ids) { + const promises = this._waiting_user_ids.get(id); + this._waiting_user_ids.delete(id); + + for(const pair of promises) + pair[1](err); + } + + for(const login of logins) { + const promises = this._waiting_user_logins.get(login); + this._waiting_user_logins.delete(login); + + for(const pair of promises) + pair[1](err); + } + + return; + } + + const id_set = new Set(ids), + login_set = new Set(logins); + + if ( Array.isArray(nodes) ) + for(const node of nodes) { + if ( ! node || ! node.id ) + continue; + + id_set.delete(node.id); + login_set.delete(node.login); + + let promises = this._waiting_user_ids.get(node.id); + if ( promises ) { + this._waiting_user_ids.delete(node.id); + for(const pair of promises) + pair[0](node); + } + + promises = this._waiting_user_logins.get(node.login); + if ( promises ) { + this._waiting_user_logins.delete(node.login); + for(const pair of promises) + pair[0](node); + } + } + + for(const id of id_set) { + const promises = this._waiting_user_ids.get(id); + if ( promises ) { + this._waiting_user_ids.delete(id); + for(const pair of promises) + pair[0](null); + } + } + + for(const login of login_set) { + const promises = this._waiting_user_logins.get(login); + if ( promises ) { + this._waiting_user_logins.delete(login); + for(const pair of promises) + pair[0](null); + } + } + + this._loading_users = false; + + if ( this._waiting_user_ids.size || this._waiting_user_logins.size ) + this._loadUsers(); + } + + // ======================================================================== // Broadcast ID // ======================================================================== diff --git a/styles/native/card.scss b/styles/native/card.scss index 64e54e94..9bb9aeda 100644 --- a/styles/native/card.scss +++ b/styles/native/card.scss @@ -3,6 +3,8 @@ flex-shrink: 0; width: 100%; + &--size-1 { width: 1rem } + &--size-105 { width: 1.5rem } &--size-2 { width: 2rem } &--size-3 { width: 3rem } &--size-4 { width: 4rem }