1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-06-27 21:05:53 +00:00
* 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`.
This commit is contained in:
SirStendec 2019-06-15 03:58:06 -04:00
parent 275248ca36
commit 80148e5579
16 changed files with 363 additions and 84 deletions

Binary file not shown.

View file

@ -114,6 +114,10 @@
<glyph glyph-name="github" unicode="&#xf09b;" d="M429 779q116 0 215-58t156-156 57-215q0-140-82-252t-211-155q-15-3-22 4t-7 17q0 1 0 43t0 75q0 54-29 79 32 3 57 10t53 22 45 37 30 58 11 84q0 67-44 115 21 51-4 114-16 5-46-6t-51-25l-21-13q-52 15-107 15t-108-15q-8 6-23 15t-47 22-47 7q-25-63-5-114-44-48-44-115 0-47 12-83t29-59 45-37 52-22 57-10q-21-20-27-58-12-5-25-8t-32-3-36 12-31 35q-11 18-27 29t-28 14l-11 1q-12 0-16-2t-3-7 5-8 7-6l4-3q12-6 24-21t18-29l6-13q7-21 24-34t37-17 39-3 31 1l13 3q0-22 0-50t1-30q0-10-8-17t-22-4q-129 43-211 155t-82 252q0 117 58 215t155 156 216 58z m-267-616q2 4-3 7-6 1-8-1-1-4 4-7 5-3 7 1z m18-19q4 3-1 9-6 5-9 2-4-3 1-9 5-6 9-2z m16-25q6 4 0 11-4 7-9 3-5-3 0-10t9-4z m24-23q4 4-2 10-7 7-11 2-5-5 2-11 6-6 11-1z m32-14q1 6-8 9-8 2-10-4t7-9q8-3 11 4z m35-3q0 7-10 6-9 0-9-6 0-7 10-6 9 0 9 6z m32 5q-1 7-10 5-9-1-8-8t10-4 8 7z" horiz-adv-x="857.1" />
<glyph glyph-name="sort-down" unicode="&#xf0dd;" d="M571 243q0-15-10-25l-250-250q-11-11-25-11t-25 11l-250 250q-11 10-11 25t11 25 25 11h500q14 0 25-11t10-25z" horiz-adv-x="571.4" />
<glyph glyph-name="sort-up" unicode="&#xf0de;" d="M571 457q0-14-10-25t-25-11h-500q-15 0-25 11t-11 25 11 25l250 250q10 11 25 11t25-11l250-250q10-10 10-25z" horiz-adv-x="571.4" />
<glyph glyph-name="gauge" unicode="&#xf0e4;" d="M214 207q0 30-21 51t-50 21-51-21-21-51 21-50 51-21 50 21 21 50z m107 250q0 30-20 51t-51 21-50-21-21-51 21-50 50-21 51 21 20 50z m239-268l57 213q3 14-5 27t-21 16-27-3-17-22l-56-213q-33-3-60-25t-35-55q-11-43 11-81t66-50 81 11 50 66q9 33-4 65t-40 51z m369 18q0 30-21 51t-51 21-50-21-21-51 21-50 50-21 51 21 21 50z m-358 357q0 30-20 51t-51 21-50-21-21-51 21-50 50-21 51 21 20 50z m250-107q0 30-20 51t-51 21-50-21-21-51 21-50 50-21 51 21 20 50z m179-250q0-145-79-269-10-17-30-17h-782q-20 0-30 17-79 123-79 269 0 102 40 194t106 160 160 107 194 39 194-39 160-107 106-160 40-194z" horiz-adv-x="1000" />
<glyph glyph-name="download-cloud" unicode="&#xf0ed;" d="M714 332q0 8-5 13t-13 5h-125v196q0 8-5 13t-12 5h-108q-7 0-12-5t-5-13v-196h-125q-8 0-13-5t-5-13q0-8 5-13l196-196q5-5 13-5t13 5l196 196q5 6 5 13z m357-125q0-89-62-151t-152-63h-607q-103 0-177 73t-73 177q0 72 39 134t105 92q-1 17-1 24 0 118 84 202t202 84q87 0 159-49t105-129q40 35 93 35 59 0 101-42t42-101q0-43-23-77 72-17 119-76t46-133z" horiz-adv-x="1071.4" />
@ -128,6 +132,10 @@
<glyph glyph-name="ellipsis-vert" unicode="&#xf142;" d="M214 154v-108q0-22-15-37t-38-16h-107q-23 0-38 16t-16 37v108q0 22 16 38t38 15h107q22 0 38-15t15-38z m0 285v-107q0-22-15-38t-38-15h-107q-23 0-38 15t-16 38v107q0 23 16 38t38 16h107q22 0 38-16t15-38z m0 286v-107q0-22-15-38t-38-16h-107q-23 0-38 16t-16 38v107q0 22 16 38t38 16h107q22 0 38-16t15-38z" horiz-adv-x="214.3" />
<glyph glyph-name="sort-alt-up" unicode="&#xf160;" d="M411 46q0-6-6-13l-178-178q-5-5-13-5-6 0-12 5l-179 179q-8 9-4 19 4 11 17 11h107v768q0 8 5 13t13 5h107q8 0 13-5t5-13v-768h107q8 0 13-5t5-13z m589-71v-107q0-8-5-13t-13-5h-464q-8 0-13 5t-5 13v107q0 8 5 13t13 5h464q8 0 13-5t5-13z m-107 286v-107q0-8-5-13t-13-5h-357q-8 0-13 5t-5 13v107q0 8 5 13t13 5h357q8 0 13-5t5-13z m-107 285v-107q0-7-5-12t-13-6h-250q-8 0-13 6t-5 12v107q0 8 5 13t13 5h250q8 0 13-5t5-13z m-107 286v-107q0-8-5-13t-13-5h-143q-8 0-13 5t-5 13v107q0 8 5 13t13 5h143q8 0 13-5t5-13z" horiz-adv-x="1000" />
<glyph glyph-name="sort-alt-down" unicode="&#xf161;" d="M679-25v-107q0-8-5-13t-13-5h-143q-8 0-13 5t-5 13v107q0 8 5 13t13 5h143q8 0 13-5t5-13z m-268 71q0-6-6-13l-178-178q-5-5-13-5-6 0-12 5l-179 179q-8 9-4 19 4 11 17 11h107v768q0 8 5 13t13 5h107q8 0 13-5t5-13v-768h107q8 0 13-5t5-13z m375 215v-107q0-8-5-13t-13-5h-250q-8 0-13 5t-5 13v107q0 8 5 13t13 5h250q8 0 13-5t5-13z m107 285v-107q0-7-5-12t-13-6h-357q-8 0-13 6t-5 12v107q0 8 5 13t13 5h357q8 0 13-5t5-13z m107 286v-107q0-8-5-13t-13-5h-464q-8 0-13 5t-5 13v107q0 8 5 13t13 5h464q8 0 13-5t5-13z" horiz-adv-x="1000" />
<glyph glyph-name="language" unicode="&#xf1ab;" d="M365 248q-1-1-7 1t-18 6l-11 5q-24 11-48 28-4 2-23 17t-21 16q-38-57-75-101-45-53-59-61-2-1-11-3t-10 0q3 3 46 52 12 13 48 64t43 66q10 17 29 55t20 43q-5 1-61-18-5-2-16-5t-19-5-10-3q-1-1-1-6t0-5q-3-5-18-8-12-4-26 0-10 2-15 11-3 4-3 13 3 1 13 3t17 3q32 9 59 18 55 20 56 20 6 1 24 11t25 12q5 1 12 4t8 3 3 0q2-7 0-18 0-2-7-16t-15-29-9-19q-14-28-43-73l35-16q7-3 42-18t38-15q2-1 5-14t3-18z m-114 272q1-9-3-16-6-13-28-21-16-7-33-7-15 2-27 15-8 8-10 23l0 1q2-1 11-3t15 0 32 9q20 7 31 8 9 0 12-9z m389-72l35-127-77 23z m-618-447l387 130v576l-387-130v-576z m692 177l57-17-101 367-56 17-120-299 57-18 25 62 118-36z m-280 537l319-103v212z m173-738l88-8-30-89-22 37q-73-46-154-60-32-7-51-7h-47q-44 0-111 22t-102 47q-5 4-5 9 0 5 3 8t7 3q2 0 10-5t17-9 12-6q40-21 89-34t87-14q54 0 94 8t87 28q9 4 17 9t19 11 16 9z m250 602v-602l-432 137q-8-3-209-71t-205-68q-8 0-10 7 0 1-1 2v602q2 5 2 5 3 3 11 6 60 20 84 28v214l311-110q1 0 90 31t176 60 90 30q11 0 11-12v-233z" horiz-adv-x="857.1" />
<glyph glyph-name="twitch" unicode="&#xf1e8;" d="M500 608v-242h-81v242h81z m222 0v-242h-81v242h81z m0-424l141 141v444h-666v-585h182v-121l121 121h222z m222 666v-565l-242-242h-182l-121-122h-121v122h-222v646l61 161h827z" horiz-adv-x="1000" />

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Before After
Before After

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -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: () =>

View file

@ -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

View file

@ -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;

View file

@ -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'
);
);*/
}

View file

@ -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);

View file

@ -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;

View file

@ -0,0 +1,10 @@
query FFZ_StreamFetch($ids: [ID!], $logins: [String!]) {
users(ids: $ids, logins: $logins) {
id
login
stream {
id
createdAt
}
}
}

View file

@ -0,0 +1,9 @@
query FFZ_SingleStream($id: ID, $login: String) {
user(id: $id, login: $login) {
id
stream {
id
createdAt
}
}
}

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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 }