From 80148e5579d88560eb19e3aa26015cae4d8bc231 Mon Sep 17 00:00:00 2001 From: SirStendec Date: Sat, 15 Jun 2019 03:58:06 -0400 Subject: [PATCH] 4.4.2 * Changed: Use the new Twitch Data module for fetching stream up-time when it isn't known, rather than forcing queries to re-fetch. * Changed: Add a method to Twitch Data for looking up stream up-time. * Fixed: The autocompletion component should not swallow key-presses when modifier keys are being held. * Fixed: Issue when comparing against `null` with `deep_equals`. --- res/font/ffz-fontello.eot | Bin 24432 -> 25400 bytes res/font/ffz-fontello.svg | 8 + res/font/ffz-fontello.ttf | Bin 24248 -> 25216 bytes res/font/ffz-fontello.woff | Bin 15340 -> 15760 bytes res/font/ffz-fontello.woff2 | Bin 12880 -> 13228 bytes src/main.js | 2 +- .../modules/directory/browse_popular.js | 4 +- .../modules/directory/following.jsx | 10 +- .../modules/directory/game.jsx | 8 +- .../modules/directory/index.jsx | 40 ++- src/std-components/autocomplete.vue | 15 + src/utilities/data/stream-fetch.gql | 10 + src/utilities/data/stream-single.gql | 9 + src/utilities/object.js | 2 + src/utilities/twitch-data.js | 334 ++++++++++++++---- styles/icons.scss | 5 +- 16 files changed, 363 insertions(+), 84 deletions(-) create mode 100644 src/utilities/data/stream-fetch.gql create mode 100644 src/utilities/data/stream-single.gql diff --git a/res/font/ffz-fontello.eot b/res/font/ffz-fontello.eot index fe672350c14a970eef1d540c0d8f16e76142efb1..d7f8d3a1dfe04becbcd77b4aeb49f4c99f51aba6 100644 GIT binary patch delta 1719 zcmZvc`%hbC7{{OIoSxIu)6xo-a%;D?j2Z{K6;hZ5DX@*P7KUA97Z;^+bx?XTI+;J! zpVVy2gcV~Pe}E<<#;m`nF(&%M;(n58mPq0jV`fGcM_M)=>4f^c=WH#zoYU|7+}`); zdp_rq{vN-+f@0GE!255{h(6t{l3Je$%q8vsU@rjl4MZb~aQte7;x7P1-N3tXr?~jv zMJkO_-8rm`M9<7jAEo#s0HZPznN%qM0>%AgrIGRXhOfVKxClT$53sLpbSN@tyLQ_R z(ES_LeWR3+QhYr?53PYMqtWCzE z!1f2uiAZ#)xnpRJVkZE%ro<-W&3o=S01i>iwXGqyz14Fm1(^KI((H19&myV#3gU~eEPHWT>57ER(d&8p0Q`@Gwqp3@=LD5af5Pq z^SS=arOZ<1LFVB~)yhIHm;8aRsX^*<=Fxc$&cXToISuT*z|N$bpE2%-E;s-|+L1^r zSCeVZXfd%J^0REDBbfS0ca}@s07#Rdk?c)P&_wo@CfH5(t|oYe?6M~C17ylIK{Hvq zCTJl`^qGJzJkzcTTFLfnf&f{10+!)pb7Sqy{3scz{)S0hzP9ws)^VjKrZEy7Iq|S7Pm!o^{=WbKK;($5d zsnp9lp;fGQxwm60`n;QwI#pUN>n4kpGtqiEE8|tO&Bj_&ztnPLOiBo}zZ3itABHk` ziEdRV9EPKTzSp`;yv()j<|MvkBGz znE5np7xk9~A!R7#fo0Y}K1hAkelpq$Zt0j_Mw7@A8`5+`3p6cH(zNrku0Yd(9H6dK zKt3U&$m0_@d4>}?dPG#5I>M>bZNy11%RJQ#C!@BJLjFN|jQ0`Uny2QyNU`3<=p{7V zEI|)W9zXZF%0nI2?>~zcr-&URL&MWx3&<<-#9E&L`?FT7WC)*+Gj%NRqikPKDYI`` zn*RYKPp>b);@0r7$2Qp%Y{XDf3H~l|^wHq_^eqd890E<`my*Mwxm_jYP33ngj#ON! z3|GbNCH4u2)$#47KR35K!8z|Lcinf_xx?=HYI?B3><6j5YuO delta 751 zcmYk3Ur19?9LK+Bcdj)D#U4W4mUj_G7#Rxc)JnI?Vd2bTScYr3KMuCMx~B_$3SsUJOf-_)u#2 z66NAn0iz;RQGP`E zU|&3uEWGv=vNVvPL&aEsZ@{zYECbGdp#|x9AStm)vkaVzQ5LTS;-MyYXoK>7K(`_F z4&IXH+vwPbrF9T7*&IHLfGmZA)Bba3wl;T69*td z4_&TWeW*TFN7W^DMJv&4T8-w?#4^;@~)WoP!hO90w=Kzd2|ouW{PYLY;LEXp_8^12=hwgHz;L4o;Ilb8v<{$3d$S zG%i#r3-vLhl6Ai`*@~jhdH^>E36-EqTOR3+aE5sl;0LFi)k_AusCi}?dDJQDAOH{0u}$cFs!66K4!Ah*RH(u HJu&|S0*C1; diff --git a/res/font/ffz-fontello.svg b/res/font/ffz-fontello.svg index 7a1d4eb1..61b5077b 100644 --- a/res/font/ffz-fontello.svg +++ b/res/font/ffz-fontello.svg @@ -114,6 +114,10 @@ + + + + @@ -128,6 +132,10 @@ + + + + diff --git a/res/font/ffz-fontello.ttf b/res/font/ffz-fontello.ttf index 73be6fc14e0271b7e5925ea1accf701f4fcbc161..41678442fc98081ac7b168f7954a243245363bc9 100644 GIT binary patch delta 1725 zcmZuxZERCj7=GXT)!W;yW3%hNI%qpqBO465r2{+I7clk>MF&%&Yxc>ut~Xn8_^bR< zg9JBx~w1mC<@mC_}1vcD2-I6(YZ2OI=gEY<+eOIUjeA>gCj1(v|W&tP)zKQm1PN)}hz4 z1*uZ>Q;)@r*DW?1D@avh-kOjc5ouK;e4O_~KDl<(TntR=O%$q?jyc zjVkh}tkBJMDDv7)Sy5!1rvY+iHD^F`R+zmK(d>_yP2CR3a8(pz#ylR_$SNpZR7b0) zpes-NdDqn~dnWHC@(oU=UPPCh4bX8(%g=qK>7jLNOV3M-Q=}bJ zhPr2k%}8FDR;=zhVSm?2on8A6n0WeV0d8&czwv~lXIg8p zJ$kM6_iY^gDmY&%#gc@|REmM`Nv#T%^f&sPCj3fFF+Lu>(l)y*w_ta{{lepgKNb0l z!}eVJc!{;-+s%J&X>@>N&RO7Ga#gteuDMeB%xD_`+G7*#KAxU+rE6NoR&2v|?1=3< s{4wSlCqonA?fs#taf4=^Qlkq;I*Ux26Br9`Kc!}+ZI%{u`ad!M51F=(NdN!< delta 749 zcmY+BUr19?9LK+Rch0p93?E{;E$^+c!pO=bqZIT;C0gG| zd4jADhOY$XU%xyFln(*ULdfqO+VrVzH_&;O_78+;L9g)jlpj#u7K+5;#TWg>3@xPS zr9ybb=XKB8tAS(RsbD}IO&}8@J?&luop62Fq zi>g_*stu}Bol>)EL0!&U^66p`$YQ-_;lG-tQq4@UDDTyXB1dQ5S|7LZ?-&CO`Kl&K zm(j^0Uy$20#tPHg4SD)%rKdyLp}nISoda?N8p#U`G?5n>umh@@fo8ImffjND0}is2 zfmZSq0|&`j1`d&z7-%CG7@cUR$ua|UNZ!JLi#)@?Ve)4Nj*!1FaFm>8phJ08{;giI zHHGzx=z3?cmJQp#p09BHhLNXB0GaKv3x6%IoM`0S^8T(Lve{#kTRjsypH&&E;?-J9 zt>uGNu(@rMn*%kKHP?kR!nlwUE5&QnyY`RWimtnbr)FnwLYeJ-$jLYRx|I38N2Wgx C?Cie) diff --git a/res/font/ffz-fontello.woff b/res/font/ffz-fontello.woff index c32dc3eca8784926d64f5be4d1c71ef668996cf1..c28493086caba3198e54e6f71bda13c581b1657b 100644 GIT binary patch delta 13521 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 diff --git a/res/font/ffz-fontello.woff2 b/res/font/ffz-fontello.woff2 index e211fd39431f5b23fc2069dab15d154efdc5a512..8481f2dd04cacfc0ce542d19bad612456391c7c0 100644 GIT binary patch literal 13228 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 literal 12880 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 diff --git a/src/main.js b/src/main.js index 66a800cf..3114d80c 100644 --- a/src/main.js +++ b/src/main.js @@ -151,7 +151,7 @@ ${typeof x[1] === 'string' ? x[1] : JSON.stringify(x[1], null, 4)}` FrankerFaceZ.Logger = Logger; const VER = FrankerFaceZ.version_info = { - major: 4, minor: 4, revision: 1, + major: 4, minor: 4, revision: 2, commit: __git_commit__, build: __webpack_hash__, toString: () => diff --git a/src/sites/twitch-twilight/modules/directory/browse_popular.js b/src/sites/twitch-twilight/modules/directory/browse_popular.js index df7b8d73..b458de14 100644 --- a/src/sites/twitch-twilight/modules/directory/browse_popular.js +++ b/src/sites/twitch-twilight/modules/directory/browse_popular.js @@ -23,10 +23,10 @@ export default class BrowsePopular extends SiteModule { onEnable() { // Popular Directory Channel Cards - this.apollo.ensureQuery( + /*this.apollo.ensureQuery( 'BrowsePage_Popular', 'data.streams.edges.0.node.createdAt' - ); + );*/ } modifyStreams(res) { // eslint-disable-line class-methods-use-this diff --git a/src/sites/twitch-twilight/modules/directory/following.jsx b/src/sites/twitch-twilight/modules/directory/following.jsx index cf44d58c..b58100aa 100644 --- a/src/sites/twitch-twilight/modules/directory/following.jsx +++ b/src/sites/twitch-twilight/modules/directory/following.jsx @@ -169,7 +169,7 @@ export default class Following extends SiteModule { } ensureQueries () { - this.apollo.ensureQuery( + /*this.apollo.ensureQuery( 'FollowedChannels_RENAME2', 'data.currentUser.followedLiveUsers.nodes.0.stream.createdAt' ); @@ -182,7 +182,7 @@ export default class Following extends SiteModule { this.apollo.ensureQuery( 'RecommendedChannels', 'data.currentUser.recommendations.liveRecommendations.nodes.0.createdAt' - ); + );*/ if ( this.router.current_name !== 'dir-following' ) return; @@ -197,11 +197,11 @@ export default class Following extends SiteModule { get('data.currentUser.followedHosts.nodes.0.hosting.stream.createdAt', n) !== undefined ); - else if ( bit === 'live' ) + /*else if ( bit === 'live' ) this.apollo.ensureQuery( 'FollowingLive_CurrentUser', 'data.currentUser.followedLiveUsers.nodes.0.stream.createdAt' - ); + );*/ else if ( bit === 'hosts' ) this.apollo.ensureQuery( @@ -217,7 +217,7 @@ export default class Following extends SiteModule { } destroyHostMenu(event) { - if (!event || event && event.target && event.target.closest('.ffz-channel-selector-outer') === null && Date.now() > this.hostMenuBuffer) { + if (!event || ! this.hostMenu || event && event.target && event.target.closest('.ffz-channel-selector-outer') === null && Date.now() > this.hostMenuBuffer) { this.hostMenuPopper && this.hostMenuPopper.destroy(); this.hostMenu && this.hostMenu.remove(); this.hostMenuPopper = this.hostMenu = undefined; diff --git a/src/sites/twitch-twilight/modules/directory/game.jsx b/src/sites/twitch-twilight/modules/directory/game.jsx index 9a48dd24..48da8f76 100644 --- a/src/sites/twitch-twilight/modules/directory/game.jsx +++ b/src/sites/twitch-twilight/modules/directory/game.jsx @@ -29,11 +29,11 @@ export default class Game extends SiteModule { this.apollo.registerModifier('DirectoryPage_Game', GAME_QUERY); this.apollo.registerModifier('DirectoryPage_Game', res => { - setTimeout(() => + /*setTimeout(() => this.apollo.ensureQuery( 'DirectoryPage_Game', 'data.game.streams.edges.0.node.createdAt' - ), 500); + ), 500);*/ this.modifyStreams(res); }, false); @@ -62,10 +62,10 @@ export default class Game extends SiteModule { updateGameHeader(inst) { this.updateButtons(inst); - this.apollo.ensureQuery( + /*this.apollo.ensureQuery( 'DirectoryPage_Game', 'data.game.streams.edges.0.node.createdAt' - ); + );*/ } diff --git a/src/sites/twitch-twilight/modules/directory/index.jsx b/src/sites/twitch-twilight/modules/directory/index.jsx index fcf75c4b..d6c38574 100644 --- a/src/sites/twitch-twilight/modules/directory/index.jsx +++ b/src/sites/twitch-twilight/modules/directory/index.jsx @@ -38,6 +38,7 @@ export default class Directory extends SiteModule { this.inject('site.apollo'); this.inject('site.css_tweaks'); this.inject('site.web_munch'); + this.inject('site.twitch_data'); this.inject('i18n'); this.inject('settings'); @@ -200,7 +201,7 @@ export default class Directory extends SiteModule { this.DirectoryVideos.forceUpdate(); }) - this.DirectoryCard.ready(cls => { + this.DirectoryCard.ready((cls, instances) => { //const old_render = cls.prototype.render, const old_render_iconic = cls.prototype.renderIconicImage, old_render_titles = cls.prototype.renderTitles; @@ -272,13 +273,13 @@ export default class Directory extends SiteModule { // Game Directory Channel Cards // TODO: Better query handling. - this.apollo.ensureQuery( + /*this.apollo.ensureQuery( 'DirectoryPage_Game', 'data.game.streams.edges.0.node.createdAt' - ); + );*/ - //for(const inst of instances) - // this.updateCard(inst); + for(const inst of instances) + this.updateCard(inst); }); this.DirectoryCard.on('update', this.updateCard, this); @@ -373,12 +374,33 @@ export default class Directory extends SiteModule { updateUptime(inst, created_path) { const container = this.fine.getChildNode(inst), card = container && container.querySelector && container.querySelector('.preview-card-overlay'), - setting = this.settings.get('directory.uptime'), - created_at = inst.props && inst.props.createdAt || get(created_path, inst), - up_since = created_at && new Date(created_at), + setting = this.settings.get('directory.uptime'); + + if ( ! card || setting === 0 || ! inst.props || inst.props.viewCount || inst.props.animatedImageProps ) + return this.clearUptime(inst); + + let created_at = inst.props.createdAt || get(created_path, inst); + + if ( ! created_at ) { + if ( inst.ffz_stream_meta === undefined ) { + inst.ffz_stream_meta = null; + this.twitch_data.getStreamMeta(inst.props.channelId, inst.props.channelLogin).then(data => { + inst.ffz_stream_meta = data; + this.updateUptime(inst, created_path); + }); + } + + if ( inst.ffz_stream_meta ) + created_at = inst.ffz_stream_meta.createdAt; + } + + if ( ! created_at ) + return this.clearUptime(inst); + + const up_since = created_at && new Date(created_at), uptime = up_since && Math.floor((Date.now() - up_since) / 1000) || 0; - if ( ! card || setting === 0 || uptime < 1 ) + if ( uptime < 1 ) return this.clearUptime(inst); const up_text = duration_to_string(uptime, false, false, false, setting === 1); diff --git a/src/std-components/autocomplete.vue b/src/std-components/autocomplete.vue index 1b759330..407b4813 100644 --- a/src/std-components/autocomplete.vue +++ b/src/std-components/autocomplete.vue @@ -305,6 +305,9 @@ export default { }, onHome(event) { + if ( event.ctrlKey || event.shiftKey || event.altKey ) + return; + if ( ! this.open ) return; @@ -316,6 +319,9 @@ export default { }, onEnd(event) { + if ( event.ctrlKey || event.shiftKey || event.altKey ) + return; + if ( ! this.open ) return; @@ -327,6 +333,9 @@ export default { }, onUp(event) { + if ( event.ctrlKey || event.shiftKey || event.altKey ) + return; + if ( ! this.open ) return; @@ -341,6 +350,9 @@ export default { }, onDown(event) { + if ( event.ctrlKey || event.shiftKey || event.altKey ) + return; + if ( ! this.open ) return; @@ -363,6 +375,9 @@ export default { }, onEnter(event) { + if ( event.ctrlKey || event.shiftKey || event.altKey ) + return; + if ( ! this.open ) return; diff --git a/src/utilities/data/stream-fetch.gql b/src/utilities/data/stream-fetch.gql new file mode 100644 index 00000000..926586fa --- /dev/null +++ b/src/utilities/data/stream-fetch.gql @@ -0,0 +1,10 @@ +query FFZ_StreamFetch($ids: [ID!], $logins: [String!]) { + users(ids: $ids, logins: $logins) { + id + login + stream { + id + createdAt + } + } +} \ No newline at end of file diff --git a/src/utilities/data/stream-single.gql b/src/utilities/data/stream-single.gql new file mode 100644 index 00000000..b65dfc97 --- /dev/null +++ b/src/utilities/data/stream-single.gql @@ -0,0 +1,9 @@ +query FFZ_SingleStream($id: ID, $login: String) { + user(id: $id, login: $login) { + id + stream { + id + createdAt + } + } +} \ No newline at end of file diff --git a/src/utilities/object.js b/src/utilities/object.js index bdad79f1..9b908548 100644 --- a/src/utilities/object.js +++ b/src/utilities/object.js @@ -179,6 +179,8 @@ export function deep_equals(object, other, ignore_undefined = false, seen, other return false; if ( typeof object !== 'object' ) return false; + if ( (object === null) !== (other === null) ) + return false; if ( ! seen ) seen = new Set; diff --git a/src/utilities/twitch-data.js b/src/utilities/twitch-data.js index c1023ff0..212f5976 100644 --- a/src/utilities/twitch-data.js +++ b/src/utilities/twitch-data.js @@ -18,10 +18,14 @@ export default class TwitchData extends Module { this.inject('site.apollo'); this.inject('site.web_munch'); + this._waiting_stream_ids = new Map; + this._waiting_stream_logins = new Map; + this.tag_cache = new Map; this._waiting_tags = new Map; - this._loadTags = debounce(this._loadTags.bind(this), 50); + this._loadTags = debounce(this._loadTags, 50); + this._loadStreams = debounce(this._loadStreams, 50); } queryApollo(query, variables, options) { @@ -56,7 +60,7 @@ export default class TwitchData extends Module { return this._search; const apollo = this.apollo.client, - core = this.listeners.getCore(), + core = this.site.getCore(), search_module = this.web_munch.getModule('algolia-search'), SearchClient = search_module && search_module.a; @@ -121,55 +125,220 @@ export default class TwitchData extends Module { } + // ======================================================================== + // Stream Up-Type (Uptime and Type, for Directory Purposes) + // ======================================================================== + + getStreamMeta(id, login) { + return new Promise(async (s, f) => { + if ( id ) { + if ( this._waiting_stream_ids.has(id) ) + this._waiting_stream_ids.get(id).push([s, f]); + else + this._waiting_stream_ids.set(id, [[s, f]]); + } else if ( login ) { + if ( this._waiting_stream_logins.has(login) ) + this._waiting_stream_logins.get(login).push([s, f]); + else + this._waiting_stream_logins.set(login, [[s, f]]); + } else + f('id and login cannot both be null'); + + if ( ! this._loading_streams ) + this._loadStreams(); + }) + } + + async _loadStreams() { + if ( this._loading_streams ) + return; + + this._loading_streams = true; + + // Get the first 50... things. + const ids = [...this._waiting_stream_ids.keys()].slice(0, 50), + remaining = 50 - ids.length, + logins = remaining > 0 ? [...this._waiting_stream_logins.keys()].slice(0, remaining) : []; + + let nodes; + + try { + const data = await this.queryApollo({ + query: require('./data/stream-fetch.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_stream_ids.get(id); + this._waiting_stream_ids.delete(id); + + for(const pair of promises) + pair[1](err); + } + + for(const login of logins) { + const promises = this._waiting_stream_logins.get(login); + this._waiting_stream_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_stream_ids.get(node.id); + if ( promises ) { + this._waiting_stream_ids.delete(node.id); + for(const pair of promises) + pair[0](node.stream); + } + + promises = this._waiting_stream_logins.get(node.login); + if ( promises ) { + this._waiting_stream_logins.delete(node.login); + for(const pair of promises) + pair[0](node.stream); + } + } + + for(const id of id_set) { + const promises = this._waiting_stream_ids.get(id); + if ( promises ) { + this._waiting_stream_ids.delete(id); + for(const pair of promises) + pair[0](null); + } + } + + for(const login of login_set) { + const promises = this._waiting_stream_logins.get(login); + if ( promises ) { + this._waiting_stream_logins.delete(login); + for(const pair of promises) + pair[0](null); + } + } + + this._loading_streams = false; + + if ( this._waiting_stream_ids.size || this._waiting_stream_logins.size ) + this._loadStreams(); + } + + // ======================================================================== // Tags // ======================================================================== + memorizeTag(node, dispatch = true) { + // We want properly formed tags. + if ( ! node || ! node.id || ! node.tagName || ! node.localizedName ) + return; + + let old = null; + if ( this.tag_cache.has(node.id) ) + old = this.tag_cache.get(old); + + const match = node.isLanguageTag && LANGUAGE_MATCHER.exec(node.tagName), + lang = match && match[1] || null; + + const new_tag = { + id: node.id, + value: node.id, + is_language: node.isLanguageTag, + language: lang, + name: node.tagName, + label: node.localizedName + }; + + if ( node.localizedDescription ) + new_tag.description = node.localizedDescription; + + const tag = old ? Object.assign(old, new_tag) : new_tag; + this.tag_cache.set(tag.id, tag); + + if ( dispatch && tag.description && this._waiting_tags.has(tag.id) ) { + const promises = this._waiting_tags.get(tag.id); + this._waiting_tags.delete(tag.id); + for(const pair of promises) + pair[0](tag); + } + + return tag; + } + async _loadTags() { if ( this._loading_tags ) return; this._loading_tags = true; - const processing = this._waiting_tags; - this._waiting_tags = new Map; + + // Get the first 50 tags. + const ids = [...this._waiting_tags.keys()].slice(0, 50); + + let nodes try { const data = await this.queryApollo( require('./data/tags-fetch.gql'), { - ids: [...processing.keys()] + ids } ); - const nodes = get('data.contentTags', data); - if ( Array.isArray(nodes) ) - for(const node of nodes) { - const tag = { - id: node.id, - value: node.id, - is_language: node.isLanguageTag, - name: node.tagName, - label: node.localizedName, - description: node.localizedDescription - }; - - this.tag_cache.set(tag.id, tag); - const promises = processing.get(tag.id); - if ( promises ) - for(const pair of promises) - pair[0](tag); - - promises.delete(tag.id); - } - - for(const promises of processing.values()) - for(const pair of promises) - pair[0](null); + nodes = get('data.contentTags', data); } catch(err) { - for(const promises of processing.values()) + for(const id of ids) { + const promises = this._waiting_tags.get(id); + this._waiting_tags.delete(id); + for(const pair of promises) pair[1](err); + } + + return; + } + + const id_set = new Set(ids); + + if ( Array.isArray(nodes) ) + for(const node of nodes) { + const tag = this.memorizeTag(node, false), + promises = this._waiting_tags.get(tag.id); + + this._waiting_tags.delete(tag.id); + id_set.delete(tag.id); + + if ( promises ) + for(const pair of promises) + pair[0](tag); + } + + for(const id of id_set) { + const promises = this._waiting_tags.get(id); + this._waiting_tags.delete(id); + + for(const pair of promises) + pair[0](null); } this._loading_tags = false; @@ -179,6 +348,10 @@ export default class TwitchData extends Module { } getTag(id, want_description = false) { + // Make sure we weren't accidentally handed a tag object. + if ( id && id.id ) + id = id.id; + if ( this.tag_cache.has(id) ) { const out = this.tag_cache.get(id); if ( out && (out.description || ! want_description) ) @@ -197,6 +370,10 @@ export default class TwitchData extends Module { } getTagImmediate(id, callback, want_description = false) { + // Make sure we weren't accidentally handed a tag object. + if ( id && id.id ) + id = id.id; + let out = null; if ( this.tag_cache.has(id) ) out = this.tag_cache.get(id); @@ -223,17 +400,7 @@ export default class TwitchData extends Module { continue; seen.add(node.id); - const tag = { - id: node.id, - value: node.id, - is_language: node.isLanguageTag, - name: node.tagName, - label: node.localizedName, - description: node.localizedDescription - }; - - this.tag_cache.set(tag.id, tag); - out.push(tag); + out.push(this.memorizeTag(node)); } return out; @@ -258,46 +425,89 @@ export default class TwitchData extends Module { return out; } - async getMatchingTags(query, locale) { + async getMatchingTags(query, locale, category = null) { if ( ! locale ) locale = this.locale; - const data = await this.searchClient.queryForType( - 'tag', query, generateUUID(), { - hitsPerPage: 100, - facetFilters: [ + locale = locale.toLowerCase(); - ], - restrictSearchableAttributes: [ - `localizations.${locale}`, - 'tag_name' - ] - } - ); + let nodes; + + if ( category ) { + const data = await this.searchClient.queryForType( + 'stream_tag', query, generateUUID(), { + hitsPerPage: 100, + faceFilters: [ + `category_id:${category}` + ], + restrictSearchableAttributes: [ + `localizations.${locale}`, + 'tag_name' + ] + } + ); + + nodes = get('streamTags.hits', data); + + } else { + const data = await this.searchClient.queryForType( + 'tag', query, generateUUID(), { + hitsPerPage: 100, + facetFilters: [ + ['tag_scope:SCOPE_ALL', 'tag_scope:SCOPE_CATEGORY'] + ], + restrictSearchableAttributes: [ + `localizations.${locale}`, + 'tag_name' + ] + } + ); + + nodes = get('tags.hits', data); + } - const nodes = get('streamTags.hits', data); if ( ! Array.isArray(nodes) ) return []; const out = [], seen = new Set; for(const node of nodes) { - if ( ! node || seen.has(node.tag_id) ) + const tag_id = node.tag_id || node.objectID; + if ( ! node || seen.has(tag_id) ) continue; - seen.add(node.tag_id); - if ( ! this.tag_cache.has(node.tag_id) ) { + seen.add(tag_id); + if ( ! this.tag_cache.has(tag_id) ) { + const match = node.tag_name && LANGUAGE_MATCHER.exec(node.tag_name), + lang = match && match[1] || null; + const tag = { - id: node.tag_id, - value: node.tag_id, - is_language: node.tag_name && LANGUAGE_MATCHER.test(node.tag_name), + id: tag_id, + value: tag_id, + is_language: lang != null, + language: lang, label: node.localizations && (node.localizations[locale] || node.localizations['en-us']) || node.tag_name }; - this.tag_cache.set(tag.id); + if ( node.description_localizations ) { + const desc = node.description_localizations[locale] || node.description_localizations['en-us']; + if ( desc ) + tag.description = desc; + } + + this.tag_cache.set(tag.id, tag); out.push(tag); } else { - out.push(this.tag_cache.get(node.tag_id)); + const tag = this.tag_cache.get(tag_id); + if ( ! tag.description && node.description_localizations ) { + const desc = node.description_localizations[locale] || node.description_localizations['en-us']; + if ( desc ) { + tag.description = desc; + this.tag_cache.set(tag.id, tag); + } + } + + out.push(tag); } } diff --git a/styles/icons.scss b/styles/icons.scss index dce59a1e..cce8b72d 100644 --- a/styles/icons.scss +++ b/styles/icons.scss @@ -128,6 +128,8 @@ .ffz-i-link-ext:before { content: '\f08e'; } /* '' */ .ffz-i-twitter:before { content: '\f099'; } /* '' */ .ffz-i-github:before { content: '\f09b'; } /* '' */ +.ffz-i-sort-down:before { content: '\f0dd'; } /* '' */ +.ffz-i-sort-up:before { content: '\f0de'; } /* '' */ .ffz-i-gauge:before { content: '\f0e4'; } /* '' */ .ffz-i-download-cloud:before { content: '\f0ed'; } /* '' */ .ffz-i-upload-cloud:before { content: '\f0ee'; } /* '' */ @@ -135,6 +137,8 @@ .ffz-i-keyboard:before { content: '\f11c'; } /* '' */ .ffz-i-calendar-empty:before { content: '\f133'; } /* '' */ .ffz-i-ellipsis-vert:before { content: '\f142'; } /* '' */ +.ffz-i-sort-alt-up:before { content: '\f160'; } /* '' */ +.ffz-i-sort-alt-down:before { content: '\f161'; } /* '' */ .ffz-i-language:before { content: '\f1ab'; } /* '' */ .ffz-i-twitch:before { content: '\f1e8'; } /* '' */ .ffz-i-bell-off:before { content: '\f1f7'; } /* '' */ @@ -146,7 +150,6 @@ .ffz-i-window-restore:before { content: '\f2d2'; } /* '' */ .ffz-i-window-close:before { content: '\f2d3'; } /* '' */ - .ffz-i-pd-1:before { margin-right: 1rem } .ffz-i-pd-2:before { margin-right: 2rem } .ffz-i-pd-3:before { margin-right: 3rem } \ No newline at end of file