mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-02 16:08:31 +00:00
4.25.0
* Fixed: Smooth Scrolling no longer causing chat to scroll. (Closes #1068) * Fixed: Issue with users using certain external stylesheets causing chat messages to become impossible to read on mouse hover. (Closes #1066) * Fixed: Issues with badge sorting causing some badges to be overridden when they shouldn't be. * Changed: Improve caching of badge data, such that re-rendering chat lines requires less computation. * Changed: Refactor how chat lines listen for settings changes to reduce code duplication. * Changed: Refactor how chat lines are invalidated to minimize work when changing settings. * API Added: `chat:rerender-lines` event that, when emitted, causes all chat lines to be re-rendered. * API Added: `chat:update-line-tokens` event that, when emitted, causes all chat lines to have their tokens invalidated and recalculated. * API Added: `chat:update-line-badges` event that, when emitted, causes all chat lines to have their cached badges invalidated and recalculated. * API Changed: `chat:update-lines-by-user` now has extra properties for separately invalidating tokens or badges. The full signature is `chat:update-lines-by-user(id, login, invalidate_tokens = true, invalidate_badges = true)`
This commit is contained in:
parent
d5478d71cd
commit
3c1d61993a
10 changed files with 256 additions and 121 deletions
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "frankerfacez",
|
"name": "frankerfacez",
|
||||||
"author": "Dan Salvato LLC",
|
"author": "Dan Salvato LLC",
|
||||||
"version": "4.24.1",
|
"version": "4.25.0",
|
||||||
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
|
|
@ -49,10 +49,10 @@ const CSS_BADGES = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BADGE_POSITIONS = {
|
export const BADGE_POSITIONS = {
|
||||||
|
staff: -2,
|
||||||
|
admin: -1,
|
||||||
|
global_mod: -1,
|
||||||
broadcaster: 0,
|
broadcaster: 0,
|
||||||
staff: 0,
|
|
||||||
admin: 0,
|
|
||||||
global_mod: 0,
|
|
||||||
mod: 1,
|
mod: 1,
|
||||||
moderator: 1,
|
moderator: 1,
|
||||||
twitchbot: 1,
|
twitchbot: 1,
|
||||||
|
@ -396,6 +396,7 @@ export default class Badges extends Module {
|
||||||
|
|
||||||
onEnable() {
|
onEnable() {
|
||||||
this.parent.context.on('changed:chat.badges.custom-mod', this.rebuildAllCSS, this);
|
this.parent.context.on('changed:chat.badges.custom-mod', this.rebuildAllCSS, this);
|
||||||
|
this.parent.context.on('changed:chat.badges.custom-vip', this.rebuildAllCSS, this);
|
||||||
this.parent.context.on('changed:chat.badges.style', this.rebuildAllCSS, this);
|
this.parent.context.on('changed:chat.badges.style', this.rebuildAllCSS, this);
|
||||||
this.parent.context.on('changed:theme.is-dark', this.rebuildAllCSS, this);
|
this.parent.context.on('changed:theme.is-dark', this.rebuildAllCSS, this);
|
||||||
this.parent.context.on('changed:theme.tooltips-dark', this.rebuildAllCSS, this);
|
this.parent.context.on('changed:theme.tooltips-dark', this.rebuildAllCSS, this);
|
||||||
|
@ -417,9 +418,32 @@ export default class Badges extends Module {
|
||||||
|
|
||||||
const room_id = container?.dataset?.roomId,
|
const room_id = container?.dataset?.roomId,
|
||||||
room_login = container?.dataset?.room,
|
room_login = container?.dataset?.room,
|
||||||
data = JSON.parse(target.dataset.badgeData),
|
|
||||||
out = [];
|
out = [];
|
||||||
|
|
||||||
|
let data;
|
||||||
|
if ( target.dataset.badgeData )
|
||||||
|
data = JSON.parse(target.dataset.badgeData);
|
||||||
|
else {
|
||||||
|
const badge_idx = target.dataset.badgeIdx,
|
||||||
|
fine = this.resolve('site.fine');
|
||||||
|
|
||||||
|
if ( fine ) {
|
||||||
|
let message;
|
||||||
|
message = container[fine.accessor]?.return?.stateNode?.props?.message;
|
||||||
|
if ( ! message )
|
||||||
|
message = fine.searchParent(container, n => n.props?.message)?.props?.message;
|
||||||
|
if ( ! message )
|
||||||
|
message = fine.searchParent(container, n => n.props?.node)?.props?.node?._ffz_message;
|
||||||
|
if ( ! message )
|
||||||
|
message = fine.searchParent(container, n => n.props?.messageContext)?.props?.messageContext?.comment?._ffz_message;
|
||||||
|
|
||||||
|
if ( message?._ffz_message)
|
||||||
|
message = message._ffz_message;
|
||||||
|
if ( message )
|
||||||
|
data = message.ffz_badge_cache?.[badge_idx]?.[1]?.badges;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( data == null )
|
if ( data == null )
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
|
@ -565,11 +589,9 @@ export default class Badges extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
render(msg, createElement, skip_hide = false, skip_click = false) { // eslint-disable-line class-methods-use-this
|
cacheBadges(msg, skip_hide = false) {
|
||||||
if ( ! msg.badges && ! msg.ffz_badges )
|
if ( msg.ffz_badge_cache )
|
||||||
return null;
|
return msg.ffz_badge_cache;
|
||||||
|
|
||||||
// TODO: A lot of this can be cached
|
|
||||||
|
|
||||||
const hidden_badges = skip_hide ? {} : (this.parent.context.get('chat.badges.hidden') || {}),
|
const hidden_badges = skip_hide ? {} : (this.parent.context.get('chat.badges.hidden') || {}),
|
||||||
badge_style = this.parent.context.get('chat.badges.style'),
|
badge_style = this.parent.context.get('chat.badges.style'),
|
||||||
|
@ -584,8 +606,7 @@ export default class Badges extends Module {
|
||||||
|
|
||||||
tb = this.twitch_badges,
|
tb = this.twitch_badges,
|
||||||
|
|
||||||
out = [],
|
slotted = new Map,
|
||||||
slotted = {},
|
|
||||||
twitch_badges = msg.badges || {},
|
twitch_badges = msg.badges || {},
|
||||||
dynamic_data = msg.badgeDynamicData || {},
|
dynamic_data = msg.badgeDynamicData || {},
|
||||||
|
|
||||||
|
@ -648,7 +669,7 @@ export default class Badges extends Module {
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
|
|
||||||
slotted[slot] = {
|
slotted.set(slot, {
|
||||||
id: badge_id,
|
id: badge_id,
|
||||||
props: {
|
props: {
|
||||||
'data-provider': 'twitch',
|
'data-provider': 'twitch',
|
||||||
|
@ -657,7 +678,7 @@ export default class Badges extends Module {
|
||||||
style: {}
|
style: {}
|
||||||
},
|
},
|
||||||
badges
|
badges
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( Array.isArray(badges) ) {
|
if ( Array.isArray(badges) ) {
|
||||||
|
@ -677,7 +698,7 @@ export default class Badges extends Module {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const slot = has(badge, 'slot') ? badge.slot : full_badge.slot,
|
const slot = has(badge, 'slot') ? badge.slot : full_badge.slot,
|
||||||
old_badge = slotted[slot],
|
old_badge = slotted.get(slot),
|
||||||
urls = badge.urls || (badge.image ? {1: badge.image} : null),
|
urls = badge.urls || (badge.image ? {1: badge.image} : null),
|
||||||
color = badge.color || full_badge.color || 'transparent',
|
color = badge.color || full_badge.color || 'transparent',
|
||||||
no_invert = badge.no_invert,
|
no_invert = badge.no_invert,
|
||||||
|
@ -725,17 +746,18 @@ export default class Badges extends Module {
|
||||||
style
|
style
|
||||||
};
|
};
|
||||||
|
|
||||||
slotted[slot] = {
|
slotted.set(slot, {
|
||||||
id: badge.id,
|
id: badge.id,
|
||||||
props,
|
props,
|
||||||
badges: [bd],
|
badges: [bd],
|
||||||
content: badge.content || full_badge.content
|
content: badge.content || full_badge.content
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (no_invert) {
|
if (no_invert) {
|
||||||
slotted[slot].full_size = true;
|
const old = slotted.get(slot);
|
||||||
slotted[slot].no_invert = true;
|
old.full_size = true;
|
||||||
|
old.no_invert = true;
|
||||||
|
|
||||||
style.background = 'unset';
|
style.background = 'unset';
|
||||||
style.backgroundSize = 'unset';
|
style.backgroundSize = 'unset';
|
||||||
|
@ -762,28 +784,43 @@ export default class Badges extends Module {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const slot in slotted)
|
return msg.ffz_badge_cache = Array.from(slotted).sort((a,b) => a[0] - b[0]);
|
||||||
if ( has(slotted, slot) ) {
|
}
|
||||||
const data = slotted[slot],
|
|
||||||
props = data.props;
|
|
||||||
|
|
||||||
let content = maybe_call(data.content, this, data, msg, createElement);
|
|
||||||
if ( content && ! Array.isArray(content) )
|
|
||||||
content = [content];
|
|
||||||
|
|
||||||
props.className = `ffz-tooltip ffz-badge${content ? ' tw-pd-x-05' : ''}${data.full_size ? ' ffz-full-size' : ''}${data.no_invert ? ' ffz-no-invert' : ''}`;
|
render(msg, createElement, skip_hide = false, skip_click = false) {
|
||||||
props.key = `${props['data-provider']}-${props['data-badge']}`;
|
if ( ! msg.badges && ! msg.ffz_badges )
|
||||||
props['data-tooltip-type'] = 'badge';
|
return null;
|
||||||
props['data-badge-data'] = JSON.stringify(data.badges);
|
|
||||||
|
|
||||||
if ( ! skip_click )
|
if ( ! msg.ffz_badge_cache )
|
||||||
props.onClick = this.handleClick;
|
this.cacheBadges(msg, skip_hide);
|
||||||
|
|
||||||
if ( data.replaced )
|
if ( ! msg.ffz_badge_cache.length )
|
||||||
props['data-replaced'] = data.replaced;
|
return null;
|
||||||
|
|
||||||
out.push(createElement('span', props, content || undefined));
|
const out = [];
|
||||||
}
|
for(let i=0, l = msg.ffz_badge_cache.length; i < l; i++) {
|
||||||
|
const data = msg.ffz_badge_cache[i][1],
|
||||||
|
props = data.props;
|
||||||
|
|
||||||
|
let content = maybe_call(data.content, this, data, msg, createElement);
|
||||||
|
if ( content && ! Array.isArray(content) )
|
||||||
|
content = [content];
|
||||||
|
|
||||||
|
props.className = `ffz-tooltip ffz-badge${content ? ' tw-pd-x-05' : ''}${data.full_size ? ' ffz-full-size' : ''}${data.no_invert ? ' ffz-no-invert' : ''}`;
|
||||||
|
props.key = `${props['data-provider']}-${props['data-badge']}`;
|
||||||
|
props['data-tooltip-type'] = 'badge';
|
||||||
|
props['data-badge-idx'] = i;
|
||||||
|
//props['data-badge-data'] = JSON.stringify(data.badges);
|
||||||
|
|
||||||
|
if ( ! skip_click )
|
||||||
|
props.onClick = this.handleClick;
|
||||||
|
|
||||||
|
if ( data.replaced )
|
||||||
|
props['data-replaced'] = data.replaced;
|
||||||
|
|
||||||
|
out.push(createElement('span', props, content || undefined));
|
||||||
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1185,7 +1185,7 @@ export default class Chat extends Module {
|
||||||
else
|
else
|
||||||
this.color_cache = null;
|
this.color_cache = null;
|
||||||
|
|
||||||
this.emit(':update-lines');
|
this.emit(':update-line-tokens');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1209,7 +1209,7 @@ export default class Chat extends Module {
|
||||||
this.socket = this.resolve('socket');
|
this.socket = this.resolve('socket');
|
||||||
|
|
||||||
if ( this.context.get('chat.filtering.color-mentions') )
|
if ( this.context.get('chat.filtering.color-mentions') )
|
||||||
this.createColorCache().then(() => this.emit(':update-lines'));
|
this.createColorCache().then(() => this.emit(':update-line-tokens'));
|
||||||
|
|
||||||
for(const key in TOKENIZERS)
|
for(const key in TOKENIZERS)
|
||||||
if ( has(TOKENIZERS, key) )
|
if ( has(TOKENIZERS, key) )
|
||||||
|
|
|
@ -8,6 +8,7 @@ import Module from 'utilities/module';
|
||||||
|
|
||||||
import {createElement} from 'react';
|
import {createElement} from 'react';
|
||||||
import { split_chars } from 'utilities/object';
|
import { split_chars } from 'utilities/object';
|
||||||
|
import { RERENDER_SETTINGS, UPDATE_BADGE_SETTINGS, UPDATE_TOKEN_SETTINGS } from 'utilities/constants';
|
||||||
|
|
||||||
export default class Line extends Module {
|
export default class Line extends Module {
|
||||||
constructor(...args) {
|
constructor(...args) {
|
||||||
|
@ -33,26 +34,25 @@ export default class Line extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
onEnable() {
|
onEnable() {
|
||||||
this.chat.context.on('changed:chat.me-style', this.updateLines, this);
|
this.on('chat.overrides:changed', id => this.updateLinesByUser(id, null, false, false), this);
|
||||||
this.chat.context.on('changed:chat.emotes.enabled', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.emotes.2x', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.emotes.animated', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.emoji.style', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.bits.stack', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.badges.style', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.badges.hidden', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.badges.custom-mod', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.rich.enabled', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.rich.hide-tokens', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.rich.all-links', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.rich.minimum-level', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.name-format', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:tooltip.link-images', this.maybeUpdateLines, this);
|
|
||||||
this.chat.context.on('changed:tooltip.link-nsfw-images', this.maybeUpdateLines, this);
|
|
||||||
|
|
||||||
this.on('chat:update-lines-by-user', this.updateLinesByUser, this);
|
this.on('chat:update-lines-by-user', this.updateLinesByUser, this);
|
||||||
this.on('chat:update-lines', this.updateLines, this);
|
this.on('chat:update-lines', this.updateLines, this);
|
||||||
this.on('i18n:update', this.updateLines, this);
|
this.on('chat:rerender-lines', this.rerenderLines, this);
|
||||||
|
this.on('chat:update-line-tokens', this.updateLineTokens, this);
|
||||||
|
this.on('chat:update-line-badges', this.updateLineBadges, this);
|
||||||
|
this.on('i18n:update', this.rerenderLines, this);
|
||||||
|
|
||||||
|
for(const setting of RERENDER_SETTINGS)
|
||||||
|
this.chat.context.on(`changed:${setting}`, this.rerenderLines, this);
|
||||||
|
|
||||||
|
for(const setting of UPDATE_TOKEN_SETTINGS)
|
||||||
|
this.chat.context.on(`changed:${setting}`, this.updateLineTokens, this);
|
||||||
|
|
||||||
|
for(const setting of UPDATE_BADGE_SETTINGS)
|
||||||
|
this.chat.context.on(`changed:${setting}`, this.updateLineBadges, this);
|
||||||
|
|
||||||
|
this.chat.context.on('changed:tooltip.link-images', this.maybeUpdateLines, this);
|
||||||
|
this.chat.context.on('changed:tooltip.link-nsfw-images', this.maybeUpdateLines, this);
|
||||||
|
|
||||||
this.site = this.resolve('site');
|
this.site = this.resolve('site');
|
||||||
|
|
||||||
|
@ -138,11 +138,27 @@ export default class Line extends Module {
|
||||||
this.updateLines();
|
this.updateLines();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
updateLines() {
|
updateLines() {
|
||||||
|
return this._updateLines();
|
||||||
|
}
|
||||||
|
|
||||||
|
rerenderLines() {
|
||||||
|
this.ChatLine.forceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLineTokens() {
|
||||||
|
return this._updateLines(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLineBadges() {
|
||||||
|
return this._updateLines(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateLines(clear_tokens = true, clear_badges = true) { // eslint-disable-line no-unused-vars
|
||||||
for(const inst of this.ChatLine.instances) {
|
for(const inst of this.ChatLine.instances) {
|
||||||
const msg = inst.props.node;
|
const msg = inst.props.node;
|
||||||
if ( msg )
|
// TODO: Selective state clear.
|
||||||
|
if ( msg?._ffz_message )
|
||||||
msg._ffz_message = null;
|
msg._ffz_message = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -673,7 +673,8 @@ export default class ChatHook extends Module {
|
||||||
ic.mode = mode;
|
ic.mode = mode;
|
||||||
ic.contrast = contrast;
|
ic.contrast = contrast;
|
||||||
|
|
||||||
this.updateChatLines();
|
this.chat_line.rerenderLines();
|
||||||
|
//this.updateChatLines();
|
||||||
this.updateMentionCSS();
|
this.updateMentionCSS();
|
||||||
this.emit(':update-colors');
|
this.emit(':update-colors');
|
||||||
}
|
}
|
||||||
|
@ -844,11 +845,6 @@ export default class ChatHook extends Module {
|
||||||
this.chat.context.on('changed:chat.filtering.highlight-mentions', this.updateMentionCSS, this);
|
this.chat.context.on('changed:chat.filtering.highlight-mentions', this.updateMentionCSS, this);
|
||||||
this.chat.context.on('changed:chat.filtering.highlight-tokens', this.updateMentionCSS, this);
|
this.chat.context.on('changed:chat.filtering.highlight-tokens', this.updateMentionCSS, this);
|
||||||
this.chat.context.on('changed:chat.filtering.mention-color', this.updateMentionCSS, this);
|
this.chat.context.on('changed:chat.filtering.mention-color', this.updateMentionCSS, this);
|
||||||
this.chat.context.on('changed:chat.fix-bad-emotes', this.updateChatLines, this);
|
|
||||||
this.chat.context.on('changed:chat.points.allow-highlight', this.updateChatLines, this);
|
|
||||||
this.chat.context.on('changed:chat.filtering.display-deleted', this.updateChatLines, this);
|
|
||||||
this.chat.context.on('changed:chat.filtering.display-mod-action', this.updateChatLines, this);
|
|
||||||
this.chat.context.on('changed:chat.replies.style', this.updateChatLines, this);
|
|
||||||
this.chat.context.on('changed:chat.filtering.clickable-mentions', val => this.css_tweaks.toggle('clickable-mentions', val));
|
this.chat.context.on('changed:chat.filtering.clickable-mentions', val => this.css_tweaks.toggle('clickable-mentions', val));
|
||||||
this.chat.context.on('changed:chat.filtering.bold-mentions', val => this.css_tweaks.toggle('chat-mention-no-bold', ! val));
|
this.chat.context.on('changed:chat.filtering.bold-mentions', val => this.css_tweaks.toggle('chat-mention-no-bold', ! val));
|
||||||
this.chat.context.on('changed:chat.pin-resubs', val => {
|
this.chat.context.on('changed:chat.pin-resubs', val => {
|
||||||
|
@ -2382,9 +2378,9 @@ export default class ChatHook extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
updateChatLines() {
|
/*updateChatLines() {
|
||||||
this.chat_line.updateLines();
|
this.chat_line.updateLines();
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
@ -2541,7 +2537,8 @@ export default class ChatHook extends Module {
|
||||||
this._ffz_old_bits = new_bits;
|
this._ffz_old_bits = new_bits;
|
||||||
|
|
||||||
room.updateBitsConfig(formatBitsConfig(config));
|
room.updateBitsConfig(formatBitsConfig(config));
|
||||||
this.updateChatLines();
|
this.chat_line.updateLineTokens();
|
||||||
|
//this.updateChatLines();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2688,7 +2685,8 @@ export default class ChatHook extends Module {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
room.updateBadges(badges);
|
room.updateBadges(badges);
|
||||||
this.updateChatLines();
|
this.chat_line.updateLineBadges();
|
||||||
|
//this.updateChatLines();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateRoomRules(cont, rules) { // eslint-disable-line class-methods-use-this
|
updateRoomRules(cont, rules) { // eslint-disable-line class-methods-use-this
|
||||||
|
|
|
@ -9,7 +9,7 @@ import Module from 'utilities/module';
|
||||||
|
|
||||||
import RichContent from './rich_content';
|
import RichContent from './rich_content';
|
||||||
import { has } from 'utilities/object';
|
import { has } from 'utilities/object';
|
||||||
import { KEYS } from 'utilities/constants';
|
import { KEYS, RERENDER_SETTINGS, UPDATE_BADGE_SETTINGS, UPDATE_TOKEN_SETTINGS } from 'utilities/constants';
|
||||||
import { print_duration } from 'utilities/time';
|
import { print_duration } from 'utilities/time';
|
||||||
import { FFZEvent } from 'utilities/events';
|
import { FFZEvent } from 'utilities/events';
|
||||||
import { getRewardTitle, getRewardCost, isHighlightedReward } from './points';
|
import { getRewardTitle, getRewardCost, isHighlightedReward } from './points';
|
||||||
|
@ -55,42 +55,25 @@ export default class ChatLine extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
async onEnable() {
|
async onEnable() {
|
||||||
this.on('chat.overrides:changed', id => this.updateLinesByUser(id), this);
|
this.on('chat.overrides:changed', id => this.updateLinesByUser(id, null, false, false), this);
|
||||||
this.on('chat:update-lines-by-user', this.updateLinesByUser, this);
|
this.on('chat:update-lines-by-user', this.updateLinesByUser, this);
|
||||||
this.on('chat:update-lines', this.updateLines, this);
|
this.on('chat:update-lines', this.updateLines, this);
|
||||||
this.on('i18n:update', this.updateLines, this);
|
this.on('chat:rerender-lines', this.rerenderLines, this);
|
||||||
|
this.on('chat:update-line-tokens', this.updateLineTokens, this);
|
||||||
|
this.on('chat:update-line-badges', this.updateLineBadges, this);
|
||||||
|
this.on('i18n:update', this.rerenderLines, this);
|
||||||
|
|
||||||
|
for(const setting of RERENDER_SETTINGS)
|
||||||
|
this.chat.context.on(`changed:${setting}`, this.rerenderLines, this);
|
||||||
|
|
||||||
|
for(const setting of UPDATE_TOKEN_SETTINGS)
|
||||||
|
this.chat.context.on(`changed:${setting}`, this.updateLineTokens, this);
|
||||||
|
|
||||||
|
for(const setting of UPDATE_BADGE_SETTINGS)
|
||||||
|
this.chat.context.on(`changed:${setting}`, this.updateLineBadges, this);
|
||||||
|
|
||||||
this.chat.context.on('changed:chat.name-format', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.me-style', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.emotes.enabled', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.emotes.2x', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.emotes.animated', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.emoji.style', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.bits.stack', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.badges.style', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.badges.hidden', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.badges.custom-mod', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.rituals.show', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.subs.show', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.subs.compact', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.rich.enabled', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.rich.hide-tokens', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.rich.all-links', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.rich.minimum-level', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:tooltip.link-images', this.maybeUpdateLines, this);
|
this.chat.context.on('changed:tooltip.link-images', this.maybeUpdateLines, this);
|
||||||
this.chat.context.on('changed:tooltip.link-nsfw-images', this.maybeUpdateLines, this);
|
this.chat.context.on('changed:tooltip.link-nsfw-images', this.maybeUpdateLines, this);
|
||||||
this.chat.context.on('changed:chat.actions.inline', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.filtering.show-deleted', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.filtering.process-own', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.timestamp-format', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.filtering.mention-priority', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:chat.filtering.debug', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:__filter:highlight-terms', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:__filter:highlight-users', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:__filter:highlight-badges', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:__filter:block-terms', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:__filter:block-users', this.updateLines, this);
|
|
||||||
this.chat.context.on('changed:__filter:block-badges', this.updateLines, this);
|
|
||||||
|
|
||||||
this.on('chat:get-tab-commands', e => {
|
this.on('chat:get-tab-commands', e => {
|
||||||
if ( this.experiments.getTwitchAssignmentByName('chat_replies') === 'control' )
|
if ( this.experiments.getTwitchAssignmentByName('chat_replies') === 'control' )
|
||||||
|
@ -882,7 +865,7 @@ other {# messages were deleted by a moderator.}
|
||||||
'data-test-selector': 'chat-message-highlight'
|
'data-test-selector': 'chat-message-highlight'
|
||||||
}),
|
}),
|
||||||
e('div', {
|
e('div', {
|
||||||
className: 'chat-line__message-container'
|
className: 'chat-line__message-container tw-relative'
|
||||||
}, [
|
}, [
|
||||||
this.props.repliesAppearancePreference && this.props.repliesAppearancePreference === 'expanded' ? this.renderReplyLine() : null,
|
this.props.repliesAppearancePreference && this.props.repliesAppearancePreference === 'expanded' ? this.renderReplyLine() : null,
|
||||||
out
|
out
|
||||||
|
@ -1013,14 +996,19 @@ other {# messages were deleted by a moderator.}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
updateLinesByUser(id, login) {
|
updateLinesByUser(id, login, clear_tokens = true, clear_badges = true) {
|
||||||
for(const inst of this.ChatLine.instances) {
|
for(const inst of this.ChatLine.instances) {
|
||||||
const msg = inst.props.message,
|
const msg = inst.props.message,
|
||||||
user = msg?.user;
|
user = msg?.user;
|
||||||
if ( user && ((id && id == user.id) || (login && login == user.login)) ) {
|
if ( user && ((id && id == user.id) || (login && login == user.login)) ) {
|
||||||
msg.ffz_tokens = null;
|
if ( clear_badges )
|
||||||
msg.ffz_badges = null;
|
msg.ffz_badges = msg.ffz_badge_cache = null;
|
||||||
msg.highlights = msg.mentioned = msg.mention_color = msg.color_priority = null;
|
|
||||||
|
if ( clear_tokens ) {
|
||||||
|
msg.ffz_tokens = null;
|
||||||
|
msg.highlights = msg.mentioned = msg.mention_color = msg.color_priority = null;
|
||||||
|
}
|
||||||
|
|
||||||
inst.forceUpdate();
|
inst.forceUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1042,21 +1030,45 @@ other {# messages were deleted by a moderator.}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLines() {
|
updateLines() {
|
||||||
|
return this._updateLines();
|
||||||
|
}
|
||||||
|
|
||||||
|
rerenderLines() {
|
||||||
|
return this._updateLines(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLineTokens() {
|
||||||
|
return this._updateLines(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLineBadges() {
|
||||||
|
return this._updateLines(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateLines(clear_tokens = true, clear_badges = true) {
|
||||||
for(const inst of this.ChatLine.instances) {
|
for(const inst of this.ChatLine.instances) {
|
||||||
const msg = inst.props.message;
|
const msg = inst.props.message;
|
||||||
if ( msg ) {
|
if ( msg ) {
|
||||||
msg.ffz_tokens = null;
|
if ( clear_badges )
|
||||||
msg.ffz_badges = null;
|
msg.ffz_badge_cache = msg.ffz_badges = null;
|
||||||
msg.highlights = msg.mentioned = msg.mention_color = msg.mention_priority = msg.clear_priority = null;
|
|
||||||
|
if ( clear_tokens ) {
|
||||||
|
msg.ffz_tokens = null;
|
||||||
|
msg.highlights = msg.mentioned = msg.mention_color = msg.mention_priority = msg.clear_priority = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const inst of this.ExtensionLine.instances) {
|
for(const inst of this.ExtensionLine.instances) {
|
||||||
const msg = inst.props.message;
|
const msg = inst.props.message;
|
||||||
if ( msg ) {
|
if ( msg ) {
|
||||||
msg.ffz_tokens = null;
|
if ( clear_badges )
|
||||||
msg.ffz_badges = null;
|
msg.ffz_badge_cache = msg.ffz_badges = null;
|
||||||
msg.highlights = msg.mentioned = msg.mention_color = msg.mention_priority = msg.clear_priority = null;
|
|
||||||
|
if ( clear_tokens ) {
|
||||||
|
msg.ffz_tokens = null;
|
||||||
|
msg.highlights = msg.mentioned = msg.mention_color = msg.mention_priority = msg.clear_priority = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -362,7 +362,7 @@ export default class Scroller extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
const smoothAnimation = () => {
|
const smoothAnimation = () => {
|
||||||
if ( this.state.isPaused || ! this.state.isAutoScrolling )
|
if ( this.state.isPaused )
|
||||||
return this.ffz_is_smooth_scrolling = false;
|
return this.ffz_is_smooth_scrolling = false;
|
||||||
|
|
||||||
// See how much time has passed to get a step based off the delta
|
// See how much time has passed to get a step based off the delta
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {print_duration} from 'utilities/time';
|
||||||
import {formatBitsConfig} from '../chat';
|
import {formatBitsConfig} from '../chat';
|
||||||
|
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
|
import { RERENDER_SETTINGS, UPDATE_BADGE_SETTINGS, UPDATE_TOKEN_SETTINGS } from 'src/utilities/constants';
|
||||||
|
|
||||||
const SUB_REGEX = /^([^\s]+) subscribed ([^.]+)\. They've subscribed for (\d+) months(?:[^!]+streak)?!/;
|
const SUB_REGEX = /^([^\s]+) subscribed ([^.]+)\. They've subscribed for (\d+) months(?:[^!]+streak)?!/;
|
||||||
const SUB_TIERS = {
|
const SUB_TIERS = {
|
||||||
|
@ -91,12 +92,24 @@ export default class VideoChatHook extends Module {
|
||||||
|
|
||||||
|
|
||||||
async onEnable() {
|
async onEnable() {
|
||||||
this.chat.context.on('changed:chat.video-chat.enabled', this.updateLines, this);
|
this.chat.context.on('changed:chat.video-chat.enabled', this.rerenderLines, this);
|
||||||
this.chat.context.on('changed:chat.video-chat.timestamps', this.updateLines, this);
|
this.chat.context.on('changed:chat.video-chat.timestamps', this.rerenderLines, this);
|
||||||
this.on('chat.overrides:changed', id => this.updateLinesByUser(id), this);
|
this.on('chat.overrides:changed', id => this.updateLinesByUser(id, null, false, false), this);
|
||||||
this.on('chat:update-lines', this.updateLines, this);
|
|
||||||
this.on('chat:update-lines-by-user', this.updateLinesByUser, this);
|
this.on('chat:update-lines-by-user', this.updateLinesByUser, this);
|
||||||
this.on('i18n:update', this.updateLines, this);
|
this.on('chat:update-lines', this.updateLines, this);
|
||||||
|
this.on('chat:rerender-lines', this.rerenderLines, this);
|
||||||
|
this.on('chat:update-line-tokens', this.updateLineTokens, this);
|
||||||
|
this.on('chat:update-line-badges', this.updateLineBadges, this);
|
||||||
|
this.on('i18n:update', this.rerenderLines, this);
|
||||||
|
|
||||||
|
for(const setting of RERENDER_SETTINGS)
|
||||||
|
this.chat.context.on(`changed:${setting}`, this.rerenderLines, this);
|
||||||
|
|
||||||
|
for(const setting of UPDATE_TOKEN_SETTINGS)
|
||||||
|
this.chat.context.on(`changed:${setting}`, this.updateLineTokens, this);
|
||||||
|
|
||||||
|
for(const setting of UPDATE_BADGE_SETTINGS)
|
||||||
|
this.chat.context.on(`changed:${setting}`, this.updateLineBadges, this);
|
||||||
|
|
||||||
this.VideoChatController.on('mount', this.chatMounted, this);
|
this.VideoChatController.on('mount', this.chatMounted, this);
|
||||||
this.VideoChatController.on('unmount', this.chatUnmounted, this);
|
this.VideoChatController.on('unmount', this.chatUnmounted, this);
|
||||||
|
@ -311,9 +324,7 @@ export default class VideoChatHook extends Module {
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
style={{color}}
|
style={{color}}
|
||||||
>{
|
>{t.chat.formatUser(user, createElement)}</a>
|
||||||
t.chat.formatUser(user, createElement)
|
|
||||||
}</a>
|
|
||||||
<div data-test-selector="comment-message-selector" class="tw-inline video-chat__message">
|
<div data-test-selector="comment-message-selector" class="tw-inline video-chat__message">
|
||||||
<span>{is_action ? ' ' : ': '}</span>
|
<span>{is_action ? ' ' : ': '}</span>
|
||||||
<span
|
<span
|
||||||
|
@ -440,6 +451,22 @@ export default class VideoChatHook extends Module {
|
||||||
|
|
||||||
|
|
||||||
updateLines() {
|
updateLines() {
|
||||||
|
return this._updateLines();
|
||||||
|
}
|
||||||
|
|
||||||
|
rerenderLines() {
|
||||||
|
this.VideoChatLine.forceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLineTokens() {
|
||||||
|
return this._updateLines(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLineBadges() {
|
||||||
|
return this._updateLines(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateLines(clear_tokens = true, clear_badges = true) { // eslint-disable-line no-unused-vars
|
||||||
for(const inst of this.VideoChatLine.instances) {
|
for(const inst of this.VideoChatLine.instances) {
|
||||||
const context = inst.props.messageContext;
|
const context = inst.props.messageContext;
|
||||||
if ( ! context.comment )
|
if ( ! context.comment )
|
||||||
|
|
|
@ -24,7 +24,8 @@ function getRequireRegex(name) {
|
||||||
const NAMES = [
|
const NAMES = [
|
||||||
'webpackJsonp',
|
'webpackJsonp',
|
||||||
'webpackChunktwitch_twilight',
|
'webpackChunktwitch_twilight',
|
||||||
'webpackChunktwitch_sunlight'
|
'webpackChunktwitch_sunlight',
|
||||||
|
'webpackJsonp_N_E'
|
||||||
];
|
];
|
||||||
|
|
||||||
const HARD_MODULES = [
|
const HARD_MODULES = [
|
||||||
|
|
|
@ -32,6 +32,50 @@ export const BAD_HOTKEYS = [
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
export const RERENDER_SETTINGS = [
|
||||||
|
'chat.name-format',
|
||||||
|
'chat.me-style',
|
||||||
|
'chat.rituals.show',
|
||||||
|
'chat.subs.show',
|
||||||
|
'chat.subs.compact',
|
||||||
|
'chat.actions.inline',
|
||||||
|
'chat.timestamp-format',
|
||||||
|
'chat.points.allow-highlight',
|
||||||
|
'chat.filtering.display-deleted',
|
||||||
|
'chat.filtering.display-mod-action',
|
||||||
|
'chat.replies.style'
|
||||||
|
];
|
||||||
|
|
||||||
|
export const UPDATE_BADGE_SETTINGS = [
|
||||||
|
'chat.badges.style',
|
||||||
|
'chat.badges.hidden',
|
||||||
|
'chat.badges.custom-mod',
|
||||||
|
'chat.badges.custom-vip',
|
||||||
|
];
|
||||||
|
|
||||||
|
export const UPDATE_TOKEN_SETTINGS = [
|
||||||
|
'chat.emotes.enabled',
|
||||||
|
'chat.emotes.2x',
|
||||||
|
'chat.emotes.animated',
|
||||||
|
'chat.emoji.style',
|
||||||
|
'chat.bits.stack',
|
||||||
|
'chat.rich.enabled',
|
||||||
|
'chat.rich.hide-tokens',
|
||||||
|
'chat.rich.all-links',
|
||||||
|
'chat.rich.minimum-level',
|
||||||
|
'chat.filtering.process-own',
|
||||||
|
'chat.filtering.mention-priority',
|
||||||
|
'chat.filtering.debug',
|
||||||
|
'chat.fix-bad-emotes',
|
||||||
|
'__filter:highlight-terms',
|
||||||
|
'__filter:highlight-users',
|
||||||
|
'__filter:highlight-badges',
|
||||||
|
'__filter:block-terms',
|
||||||
|
'__filter:block-users',
|
||||||
|
'__filter:block-badges'
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
export const KEYS = {
|
export const KEYS = {
|
||||||
Tab: 9,
|
Tab: 9,
|
||||||
Enter: 13,
|
Enter: 13,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue