From f0d68527b859a91b962b2ce4050819d301ca7e1a Mon Sep 17 00:00:00 2001 From: SirStendec Date: Thu, 13 May 2021 15:54:21 -0400 Subject: [PATCH] 4.22.5 * Added: Setting to hide unrelated results from the FFZ Control Center when searching. This is now enabled by default. * Added: Setting to control whether the height of the Emote Menu is expanded. This is now disabled by default. * Changed: When searching in the FFZ Control Center, pills are displayed in the navigation tree showing how many matching results there are. * Changed: Update the method used for searching for channels and games, hopefully resulting in more accurate results. * Changed: When searching for users in an auto-complete field, display a check-mark for verified users. * Changed: When searching for users in an auto-complete field, respect the user's preference for rounded avatars. * Fixed: Lazy load Markdown when possible to save on initial download size. --- package.json | 2 +- .../main_menu/components/menu-container.vue | 12 ++- .../main_menu/components/menu-page.vue | 52 +++++++++- .../main_menu/components/menu-tree.vue | 30 +++++- src/modules/main_menu/index.js | 16 +++ src/modules/tooltips.js | 43 +------- src/settings/components/category.vue | 21 +--- src/settings/components/channel.vue | 21 +--- .../modules/chat/emote_menu.jsx | 17 +++- .../twitch-twilight/modules/menu_button.jsx | 11 ++- src/sites/twitch-twilight/styles/chat.scss | 50 ++++++---- src/std-components/autocomplete-game.vue | 22 +++++ src/std-components/autocomplete-user.vue | 35 +++++++ src/std-components/autocomplete.vue | 10 +- src/std-components/markdown.vue | 20 +++- src/std-components/tab-container.vue | 52 +++++++++- src/utilities/data/search-category.gql | 15 +-- src/utilities/data/search-user.gql | 18 ++-- src/utilities/data/user-bulk.gql | 3 + src/utilities/markdown.js | 52 +++++++++- src/utilities/twitch-data.js | 97 +++++++++++++------ 21 files changed, 435 insertions(+), 164 deletions(-) create mode 100644 src/std-components/autocomplete-game.vue create mode 100644 src/std-components/autocomplete-user.vue diff --git a/package.json b/package.json index 650a2a99..b8ce01d0 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "frankerfacez", "author": "Dan Salvato LLC", - "version": "4.22.4", + "version": "4.22.5", "description": "FrankerFaceZ is a Twitch enhancement suite.", "private": true, "license": "Apache-2.0", diff --git a/src/modules/main_menu/components/menu-container.vue b/src/modules/main_menu/components/menu-container.vue index 2999928a..1b804431 100644 --- a/src/modules/main_menu/components/menu-container.vue +++ b/src/modules/main_menu/components/menu-container.vue @@ -10,7 +10,7 @@
@@ -34,6 +34,16 @@ export default { return this.shouldShow(this.item); }, + visibleContents() { + if ( ! this.item || ! this.item.contents ) + return []; + + if ( ! this.context.matches_only ) + return this.item.contents; + + return this.item.contents.filter(item => this.shouldShow(item)); + }, + classes() { return [ 'ffz--menu-container', diff --git a/src/modules/main_menu/components/menu-page.vue b/src/modules/main_menu/components/menu-page.vue index 13debc12..1df77ad5 100644 --- a/src/modules/main_menu/components/menu-page.vue +++ b/src/modules/main_menu/components/menu-page.vue @@ -60,20 +60,21 @@
@@ -107,6 +108,26 @@ export default { } return out; + }, + + visibleItems() { + if ( ! this.item || ! this.item.items ) + return []; + + if ( ! this.context.matches_only ) + return this.item.items; + + return this.item.items.filter(item => this.shouldShow(item)); + }, + + visibleContents() { + if ( ! this.item || ! this.item.contents ) + return []; + + if ( ! this.context.matches_only ) + return this.item.contents; + + return this.item.contents.filter(item => this.shouldShow(item)); } }, @@ -118,6 +139,31 @@ export default { return item.no_filter || item.search_terms.includes(this.filter); }, + countMatches(item, seen) { + if ( ! this.filter || ! this.filter.length || ! item ) + return 0; + + if ( seen && seen.has(item) ) + return 0; + + if ( ! seen ) + seen = new Set; + + seen.add(item); + + let count = 0; + + for(const key of ['tabs', 'contents', 'items']) + if ( item[key] ) + for(const thing of item[key]) + count += this.countMatches(thing, seen); + + if ( item.setting && item.search_terms && item.search_terms.includes(this.filter) ) + count++; + + return count; + }, + markSeen(item) { this.$emit('mark-seen', item); }, diff --git a/src/modules/main_menu/components/menu-tree.vue b/src/modules/main_menu/components/menu-tree.vue index 0e80719a..2bef5f5d 100644 --- a/src/modules/main_menu/components/menu-tree.vue +++ b/src/modules/main_menu/components/menu-tree.vue @@ -35,7 +35,10 @@ {{ t(item.i18n_key, item.title) }} - + + {{ countMatches(item) }} + + {{ item.pill_i18n_key ? t(item.pill_i18n_key, item.pill) : item.pill }} @@ -117,6 +120,31 @@ export default { return false; }, + countMatches(item, seen) { + if ( ! this.filter || ! this.filter.length || ! item ) + return 0; + + if ( seen && seen.has(item) ) + return 0; + + if ( ! seen ) + seen = new Set; + + seen.add(item); + + let count = 0; + + for(const key of ['tabs', 'contents', 'items']) + if ( item[key] ) + for(const thing of item[key]) + count += this.countMatches(thing, seen); + + if ( item.setting && item.search_terms && item.search_terms.includes(this.filter) ) + count++; + + return count; + }, + containsCurrent(item) { let i = this.currentItem; while ( i ) { diff --git a/src/modules/main_menu/index.js b/src/modules/main_menu/index.js index 51bbe64d..b4443d33 100644 --- a/src/modules/main_menu/index.js +++ b/src/modules/main_menu/index.js @@ -203,6 +203,15 @@ export default class MainMenu extends Module { force_seen: true }); + this.settings.add('ffz.search.matches-only', { + default: true, + ui: { + path: 'Appearance > Control Center >> Search', + title: 'Hide items that do not match completely when searching.', + component: 'setting-check-box' + } + }); + this.on('settings:added-definition', (key, definition) => { this._addDefinitionToTree(key, definition); this.scheduleUpdate(); @@ -834,6 +843,7 @@ export default class MainMenu extends Module { can_proxy: context._context.can_proxy, proxied: context._context.proxied, has_update: this.has_update, + matches_only: settings.get('ffz.search.matches-only'), mod_icons: context.get('context.chat.showModIcons'), setProxied: val => { @@ -946,9 +956,14 @@ export default class MainMenu extends Module { } }, + _update_settings() { + _c.matches_only = settings.get('ffz.search.matches-only'); + }, + _add_user() { this._users++; if ( this._users === 1 ) { + settings.on(':changed:ffz.search.matches-only', this._update_settings, this); settings.on(':profile-toggled', this._profile_toggled, this); settings.on(':profile-created', this._profile_created, this); settings.on(':profile-changed', this._profile_changed, this); @@ -963,6 +978,7 @@ export default class MainMenu extends Module { _remove_user() { this._users--; if ( this._users === 0 ) { + settings.off(':changed:ffz.search.matches-only', this._update_settings, this); settings.off(':profile-toggled', this._profile_toggled, this); settings.off(':profile-created', this._profile_created, this); settings.off(':profile-changed', this._profile_changed, this); diff --git a/src/modules/tooltips.js b/src/modules/tooltips.js index aa9d9cef..fc409c0a 100644 --- a/src/modules/tooltips.js +++ b/src/modules/tooltips.js @@ -9,6 +9,7 @@ import {has, maybe_call, once} from 'utilities/object'; import Tooltip from 'utilities/tooltip'; import Module from 'utilities/module'; +import awaitMD, {getMD} from 'utilities/markdown'; export default class TooltipProvider extends Module { constructor(...args) { @@ -60,9 +61,9 @@ export default class TooltipProvider extends Module { this.types.markdown = (target, tip) => { tip.add_class = 'ffz-tooltip--markdown'; - const md = this.getMarkdown(); + const md = getMD(); if ( ! md ) - return this.loadMarkdown().then(md => md.render(target.dataset.title)); + return awaitMD().then(md => md.render(target.dataset.title)); return md.render(target.dataset.title); }; @@ -71,46 +72,8 @@ export default class TooltipProvider extends Module { this.types.html = target => target.dataset.title; this.onFSChange = this.onFSChange.bind(this); - - this.loadMarkdown = once(this.loadMarkdown); - } - getMarkdown(callback) { - if ( this._md ) - return this._md; - - if ( callback ) - this.loadMarkdown().then(md => callback(md)); - } - - async loadMarkdown() { // eslint-disable-line class-methods-use-this - if ( this._md ) - return this._md; - - const [MD, MILA] = await Promise.all([ - import(/* webpackChunkName: 'markdown' */ 'markdown-it'), - import(/* webpackChunkName: 'markdown' */ 'markdown-it-link-attributes') - ]); - - const md = this._md = new MD.default({ - html: false, - linkify: true - }); - - md.use(MILA.default, { - attrs: { - class: 'ffz-tooltip', - target: '_blank', - rel: 'noopener', - 'data-tooltip-type': 'link' - } - }); - - return md; - } - - onEnable() { const container = this.getRoot(); diff --git a/src/settings/components/category.vue b/src/settings/components/category.vue index 085b2bc4..df73ccde 100644 --- a/src/settings/components/category.vue +++ b/src/settings/components/category.vue @@ -26,26 +26,7 @@ class="tw-flex-grow-1" @selected="onSelected" > -
-
-
-
- - - -
-
-

- {{ slot.item.displayName }} -

-
-
-
-
+
diff --git a/src/settings/components/channel.vue b/src/settings/components/channel.vue index 67d9c298..ba57ff74 100644 --- a/src/settings/components/channel.vue +++ b/src/settings/components/channel.vue @@ -28,26 +28,7 @@ class="tw-flex-grow-1" @selected="onSelected" > -
-
-
-
- - - -
-
-

- {{ slot.item.displayName }} -

-
-
-
-
+
diff --git a/src/sites/twitch-twilight/modules/chat/emote_menu.jsx b/src/sites/twitch-twilight/modules/chat/emote_menu.jsx index 758f5462..c7162c95 100644 --- a/src/sites/twitch-twilight/modules/chat/emote_menu.jsx +++ b/src/sites/twitch-twilight/modules/chat/emote_menu.jsx @@ -222,6 +222,15 @@ export default class EmoteMenu extends Module { } }); + this.settings.add('chat.emote-menu.tall', { + default: false, + ui: { + path: 'Chat > Emote Menu >> Appearance', + title: 'Use extra height for the emote menu.', + component: 'setting-check-box' + } + }); + this.settings.add('chat.emote-menu.show-heading', { default: 1, ui: { @@ -1066,6 +1075,7 @@ export default class EmoteMenu extends Module { quickNav: t.chat.context.get('chat.emote-menu.show-quick-nav'), animated: t.chat.context.get('chat.emotes.animated'), showHeading: t.chat.context.get('chat.emote-menu.show-heading'), + tall: t.chat.context.get('chat.emote-menu.tall'), reducedPadding: t.chat.context.get('chat.emote-menu.reduced-padding'), combineTabs: t.chat.context.get('chat.emote-menu.combine-tabs'), showSearch: t.chat.context.get('chat.emote-menu.show-search'), @@ -1217,6 +1227,7 @@ export default class EmoteMenu extends Module { t.chat.context.on('changed:chat.emote-menu.show-heading', this.updateSettingState, this); t.chat.context.on('changed:chat.emote-menu.combine-tabs', this.updateSettingState, this); t.chat.context.on('changed:chat.emote-menu.show-search', this.updateSettingState, this); + t.chat.context.on('changed:chat.emote-menu.tall', this.updateSettingState, this); window.ffz_menu = this; } @@ -1231,6 +1242,7 @@ export default class EmoteMenu extends Module { t.chat.context.off('changed:chat.emote-menu.reduced-padding', this.updateSettingState, this); t.chat.context.off('changed:chat.emote-menu.combine-tabs', this.updateSettingState, this); t.chat.context.off('changed:chat.emote-menu.show-search', this.updateSettingState, this); + t.chat.context.off('changed:chat.emote-menu.tall', this.updateSettingState, this); if ( window.ffz_menu === this ) window.ffz_menu = null; @@ -1244,7 +1256,8 @@ export default class EmoteMenu extends Module { showHeading: t.chat.context.get('chat.emote-menu.show-heading'), reducedPadding: t.chat.context.get('chat.emote-menu.reduced-padding'), combineTabs: t.chat.context.get('chat.emote-menu.combine-tabs'), - showSearch: t.chat.context.get('chat.emote-menu.show-search') + showSearch: t.chat.context.get('chat.emote-menu.show-search'), + tall: t.chat.context.get('chat.emote-menu.tall') }); } @@ -2303,7 +2316,7 @@ export default class EmoteMenu extends Module { return (