diff --git a/package.json b/package.json index 586ae562..fae76293 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "frankerfacez", "author": "Dan Salvato LLC", - "version": "4.20.26", + "version": "4.20.27", "description": "FrankerFaceZ is a Twitch enhancement suite.", "license": "Apache-2.0", "scripts": { diff --git a/src/modules/chat/components/chat-rich.vue b/src/modules/chat/components/chat-rich.vue index ee2257f2..804a5137 100644 --- a/src/modules/chat/components/chat-rich.vue +++ b/src/modules/chat/components/chat-rich.vue @@ -40,7 +40,6 @@ export default { watch: { data() { this.reset(); - this.load(); }, events() { @@ -57,6 +56,7 @@ export default { beforeDestroy() { this.unlisten(); + this.clearRefresh(); }, methods: { @@ -64,7 +64,7 @@ export default { if ( tokenizer ) this.has_tokenizer = true; else { - tokenizer = await import(/* webpack-chunk-name: 'rich_tokens' */ 'utilities/rich_tokens'); + tokenizer = await import(/* webpackChunkName: 'rich_tokens' */ 'utilities/rich_tokens'); this.has_tokenizer = true; } }, @@ -74,25 +74,33 @@ export default { if ( this.events?.on ) { this._es = this.events; - this._es.on('chat:update-link-resolver', this.checkRefresh, this); + this._es.on('chat:update-link-resolver', this.checkReset, this); } }, unlisten() { if ( this._es?.off ) { - this._es.off('chat:update-link-resolver', this.checkRefresh, this); + this._es.off('chat:update-link-resolver', this.checkReset, this); this._es = null; } }, - checkRefresh(url) { + checkReset(url) { if ( ! url || (url && url === this.url) ) { this.reset(); - this.load(); } }, - reset() { + clearRefresh() { + if ( this._refresh_timer ) { + clearTimeout(this._refresh_timer); + this._refresh_timer = null; + } + }, + + reset(refresh = false) { + this.clearRefresh(); + this.loaded = false; this.error = null; this.accent = null; @@ -102,12 +110,15 @@ export default { this.urls = null; this.allow_media = false; this.allow_unsafe = false; + this.load(refresh); }, - async load() { + async load(refresh = false) { + this.clearRefresh(); + let data; try { - data = this.data.getData(); + data = this.data.getData(refresh); if ( data instanceof Promise ) { const to_wait = has(this.data, 'timeout') ? this.data.timeout : 1000; if ( to_wait ) @@ -137,6 +148,21 @@ export default { } } + if ( data.refresh ) { + try { + this.clearRefresh(); + + const then = new Date(data.refresh).getTime(), + delta = then - Date.now(); + + if ( delta > 0 ) + this._refresh_timer = setTimeout(() => this.load(true), delta + (100 * Math.floor(Math.random() * 100))); + + } catch(err) { + /* no op */ + } + } + this.loaded = true; this.error = data.error; this.accent = data.accent; diff --git a/src/modules/chat/emotes.js b/src/modules/chat/emotes.js index baa13ec6..55a92eaa 100644 --- a/src/modules/chat/emotes.js +++ b/src/modules/chat/emotes.js @@ -400,14 +400,15 @@ export default class Emotes extends Module { if ( ! fine ) return; - const chat = fine.searchParent(target, n => n.props && n.props.onEmoteClick); - if ( ! chat || ! chat.props || ! chat.props.message ) + const line = fine.searchParent(target, n => n.props && n.props.message), + opener = fine.searchParent(target, n => n.onShowEmoteCard, 200); + + if ( ! line || ! opener ) return; - const props = chat.props; - props.onEmoteClick({ - channelID: props.channelID || '', - channelLogin: props.channelLogin || '', + opener.onShowEmoteCard({ + channelID: line.props.channelID || '', + channelLogin: line.props.channelLogin || '', emoteID: ds.id, emoteCode: target.alt, sourceID: 'chat', diff --git a/src/modules/chat/index.js b/src/modules/chat/index.js index bc541a1b..1a5248b3 100644 --- a/src/modules/chat/index.js +++ b/src/modules/chat/index.js @@ -1560,11 +1560,11 @@ export default class Chat extends Module { } - get_link_info(url, no_promises) { + get_link_info(url, no_promises, refresh = false) { let info = this._link_info[url]; const expires = info && info[1]; - if ( expires && Date.now() > expires ) + if ( (info && info[0] && refresh) || (expires && Date.now() > expires) ) info = this._link_info[url] = null; if ( info && info[0] ) diff --git a/src/modules/chat/rich_providers.js b/src/modules/chat/rich_providers.js index b7826aff..35db2087 100644 --- a/src/modules/chat/rich_providers.js +++ b/src/modules/chat/rich_providers.js @@ -42,10 +42,10 @@ export const Links = { url: token.url, timeout: 0, - getData: async () => { + getData: async (refresh = false) => { let data; try { - data = await this.get_link_info(token.url); + data = await this.get_link_info(token.url, false, refresh); } catch(err) { return { url: token.url, diff --git a/src/modules/chat/tokenizers.jsx b/src/modules/chat/tokenizers.jsx index 29e930cc..e5506f13 100644 --- a/src/modules/chat/tokenizers.jsx +++ b/src/modules/chat/tokenizers.jsx @@ -56,7 +56,7 @@ export const Links = { show_unsafe = datasetBool(target.dataset.forceUnsafe) ?? this.context.get('tooltip.link-nsfw-images'); return Promise.all([ - import(/* webpack-chunk-name: 'rich_tokens' */ 'utilities/rich_tokens'), + import(/* webpackChunkName: 'rich_tokens' */ 'utilities/rich_tokens'), this.get_link_info(url) ]).then(([rich_tokens, data]) => { if ( ! data || (data.v || 1) > TOOLTIP_VERSION ) diff --git a/src/sites/twitch-twilight/modules/chat/rich_content.jsx b/src/sites/twitch-twilight/modules/chat/rich_content.jsx index dc93845f..61f22169 100644 --- a/src/sites/twitch-twilight/modules/chat/rich_content.jsx +++ b/src/sites/twitch-twilight/modules/chat/rich_content.jsx @@ -25,7 +25,7 @@ export default class RichContent extends Module { if ( this.has_tokenizer ) return; - this.tokenizer = await import(/* webpack-chunk-name: 'rich_tokens' */ 'utilities/rich_tokens'); + this.tokenizer = await import(/* webpackChunkName: 'rich_tokens' */ 'utilities/rich_tokens'); this.has_tokenizer = true; return this.tokenizer; } @@ -52,9 +52,11 @@ export default class RichContent extends Module { t.loadTokenizer().then(() => this.setState({...this.state, has_tokenizer: true})); } - async load() { + async load(refresh = false) { + this.clearRefresh(); + try { - let data = this.props.getData(); + let data = this.props.getData(refresh); if ( data instanceof Promise ) { const to_wait = has(this.props, 'timeout') ? this.props.timeout : 1000; if ( to_wait ) @@ -78,6 +80,21 @@ export default class RichContent extends Module { } }; + if ( data.refresh ) { + try { + this.clearRefresh(); + + const then = new Date(data.refresh).getTime(), + delta = then - Date.now(); + + if ( delta > 0 ) + this._refresh_timer = setTimeout(() => this.load(true), delta + (100 * Math.floor(Math.random() * 100))); + + } catch(err) { + /* no op */ + } + } + this.setState(Object.assign({ loaded: true, url: this.props.url, @@ -101,17 +118,26 @@ export default class RichContent extends Module { } } + clearRefresh() { + if ( this._refresh_timer ) { + clearTimeout(this._refresh_timer); + this._refresh_timer = null; + } + } + checkReload(url) { if ( ! url || (url && this.props.url === url) ) this.reload(); } - reload() { + reload(refresh = false) { + this.clearRefresh(); + this.setState({ loaded: false, error: false, has_tokenizer: t.has_tokenizer - }, () => this.load()); + }, () => this.load(refresh)); } componentDidMount() { @@ -122,6 +148,7 @@ export default class RichContent extends Module { componentWillUnmount() { t.off('chat:update-link-resolver', this.checkReload, this); + this.clearRefresh(); } renderCard() {