diff --git a/src/main.js b/src/main.js
index fb84b059..490d3538 100644
--- a/src/main.js
+++ b/src/main.js
@@ -149,7 +149,7 @@ ${typeof x[1] === 'string' ? x[1] : JSON.stringify(x[1], null, 4)}`
FrankerFaceZ.Logger = Logger;
const VER = FrankerFaceZ.version_info = {
- major: 4, minor: 0, revision: 0, extra: '-rc16.3',
+ major: 4, minor: 0, revision: 0, extra: '-rc17',
commit: __git_commit__,
build: __webpack_hash__,
toString: () =>
diff --git a/src/modules/chat/badges.jsx b/src/modules/chat/badges.jsx
index a3d0c461..c2df36bd 100644
--- a/src/modules/chat/badges.jsx
+++ b/src/modules/chat/badges.jsx
@@ -155,67 +155,7 @@ export default class Badges extends Module {
path: 'Chat > Badges >> tabs ~> Visibility',
title: 'Visibility',
component: 'badge-visibility',
- data: () => {
- const twitch = [],
- game = [],
- ffz = [],
- addon = [];
-
- for(const key in this.twitch_badges)
- if ( has(this.twitch_badges, key) ) {
- const badge = this.twitch_badges[key],
- vs = [];
- let v = badge && (badge[1] || badge[0]);
-
- for(const key in badge)
- if ( has(badge, key) ) {
- const version = badge[key];
- if ( ! v )
- v = version;
-
- if ( version && version.image1x )
- vs.push({
- version: key,
- name: version.title,
- image: version.image1x,
- styleImage: `url("${version.image1x}")`
- });
- }
-
- if ( v )
- (badge.__game ? game : twitch).push({
- id: key,
- provider: 'twitch',
- name: v.title,
- color: 'transparent',
- image: v.image2x,
- versions: vs,
- styleImage: `url("${v.image2x}")`
- });
- }
-
- for(const key in this.badges)
- if ( has(this.badges, key) ) {
- const badge = this.badges[key],
- image = badge.urls ? (badge.urls[2] || badge.urls[1]) : badge.image;
-
- (/^addon/.test(key) ? addon : ffz).push({
- id: key,
- provider: 'ffz',
- name: badge.title,
- color: badge.color || 'transparent',
- image,
- styleImage: `url("${image}")`
- });
- }
-
- return [
- {title: 'Twitch', badges: twitch},
- {title: 'Twitch: Game', key: 'game', badges: game},
- {title: 'FrankerFaceZ', badges: ffz},
- {title: 'Add-on', badges: addon}
- ];
- }
+ data: () => this.getSettingsBadges(true)
}
});
@@ -247,6 +187,69 @@ export default class Badges extends Module {
});
}
+ getSettingsBadges(include_addons) {
+ const twitch = [],
+ game = [],
+ ffz = [],
+ addon = [];
+
+ for(const key in this.twitch_badges)
+ if ( has(this.twitch_badges, key) ) {
+ const badge = this.twitch_badges[key],
+ vs = [];
+ let v = badge && (badge[1] || badge[0]);
+
+ for(const key in badge)
+ if ( has(badge, key) ) {
+ const version = badge[key];
+ if ( ! v )
+ v = version;
+
+ if ( version && version.image1x )
+ vs.push({
+ version: key,
+ name: version.title,
+ image: version.image1x,
+ styleImage: `url("${version.image1x}")`
+ });
+ }
+
+ if ( v )
+ (badge.__game ? game : twitch).push({
+ id: key,
+ provider: 'twitch',
+ name: v.title,
+ color: 'transparent',
+ image: v.image2x,
+ versions: vs,
+ styleImage: `url("${v.image2x}")`
+ });
+ }
+
+ if ( include_addons )
+ for(const key in this.badges)
+ if ( has(this.badges, key) ) {
+ const badge = this.badges[key],
+ image = badge.urls ? (badge.urls[2] || badge.urls[1]) : badge.image;
+
+ (/^addon/.test(key) ? addon : ffz).push({
+ id: key,
+ provider: 'ffz',
+ name: badge.title,
+ color: badge.color || 'transparent',
+ image,
+ styleImage: `url("${image}")`
+ });
+ }
+
+ return [
+ {title: 'Twitch', badges: twitch},
+ {title: 'Twitch: Game', key: 'game', badges: game},
+ {title: 'FrankerFaceZ', badges: ffz},
+ {title: 'Add-on', badges: addon}
+ ];
+ }
+
onEnable() {
this.parent.context.on('changed:chat.badges.custom-mod', this.rebuildAllCSS, this);
@@ -278,9 +281,19 @@ export default class Badges extends Module {
if ( ! bd )
continue;
+ let title = bd.title || global_badge.title;
+ if ( d.data ) {
+ if ( d.badge === 'subscriber' ) {
+ title = this.i18n.t('badges.subscriber.months', '%{title} (%{count} Month%{count|en_plural})', {
+ title,
+ count: d.data
+ });
+ }
+ }
+
out.push(
{show_previews &&

}
- {bd.title || global_badge.title}
+ {title}
);
/*out.push(e('div', {className: 'ffz-badge-tip'}, [
@@ -332,6 +345,7 @@ export default class Badges extends Module {
out = [],
slotted = {},
twitch_badges = msg.badges || {},
+ dynamic_data = msg.badgeDynamicData || {},
user = msg.user || {},
user_id = user.id,
@@ -357,7 +371,8 @@ export default class Badges extends Module {
else
slot = last_slot++;
- const urls = badge_id === 'moderator' && custom_mod && room && room.data && room.data.mod_urls,
+ const data = dynamic_data[badge_id],
+ urls = badge_id === 'moderator' && custom_mod && room && room.data && room.data.mod_urls,
badges = [];
if ( urls ) {
@@ -366,14 +381,16 @@ export default class Badges extends Module {
provider: 'ffz',
image: urls[4] || urls[2] || urls[1],
color: '#34ae0a',
- title: bd ? bd.title : 'Moderator'
+ title: bd ? bd.title : 'Moderator',
+ data
});
} else
badges.push({
provider: 'twitch',
badge: badge_id,
- version
+ version,
+ data
});
slotted[slot] = {
diff --git a/src/modules/chat/index.js b/src/modules/chat/index.js
index 1460b50f..c578d9ac 100644
--- a/src/modules/chat/index.js
+++ b/src/modules/chat/index.js
@@ -186,6 +186,7 @@ export default class Chat extends Module {
ui: {
path: 'Chat > Behavior >> Deleted Messages',
title: 'Deleted Message Style',
+ description: 'This style will be applied to deleted messages showed in Detailed rendering mode to differentiate them from normal chat messages.',
component: 'setting-select-box',
data: [
{value: 0, title: 'Faded'},
@@ -200,8 +201,8 @@ export default class Chat extends Module {
default: false,
ui: {
path: 'Chat > Behavior >> Deleted Messages',
- title: 'Deleted Message Rendering',
- description: 'This, when set, overrides the mode selected in Twitch Chat settings. We do this to allow non-moderators access to the setting.',
+ title: 'Rendering Mode',
+ description: 'This, when set, overrides the mode selected in Twitch chat settings. We do this to allow non-moderators access to the setting.',
component: 'setting-select-box',
data: [
{value: false, title: 'Do Not Override'},
@@ -216,7 +217,7 @@ export default class Chat extends Module {
default: 1,
ui: {
path: 'Chat > Behavior >> Deleted Messages',
- title: 'Display Deletion Reason',
+ title: 'Display Reason',
component: 'setting-select-box',
data: [
{value: 0, title: 'Never'},
@@ -285,6 +286,177 @@ export default class Chat extends Module {
}
});
+ this.settings.add('chat.filtering.highlight-basic-users', {
+ default: [],
+ type: 'array_merge',
+ always_inherit: true,
+ ui: {
+ path: 'Chat > Filtering >> Highlight Users',
+ component: 'basic-terms',
+ colored: true,
+ words: false
+ }
+ });
+
+ this.settings.add('chat.filtering.highlight-basic-users--color-regex', {
+ requires: ['chat.filtering.highlight-basic-users'],
+ process(ctx) {
+ const val = ctx.get('chat.filtering.highlight-basic-users');
+ if ( ! val || ! val.length )
+ return null;
+
+ const colors = new Map;
+
+ for(const item of val) {
+ const c = item.c || null,
+ t = item.t;
+
+ let v = item.v;
+
+ if ( t === 'glob' )
+ v = glob_to_regex(v);
+
+ else if ( t !== 'raw' )
+ v = escape_regex(v);
+
+ if ( ! v || ! v.length )
+ continue;
+
+ try {
+ new RegExp(v);
+ } catch(err) {
+ continue;
+ }
+
+ if ( colors.has(c) )
+ colors.get(c).push(v);
+ else {
+ colors.set(c, [v]);
+ }
+ }
+
+ for(const [key, list] of colors) {
+ colors.set(key, new RegExp(`^${list.join('|')}$`, 'gi'));
+ }
+
+ return colors;
+ }
+ });
+
+
+ this.settings.add('chat.filtering.highlight-basic-users-blocked', {
+ default: [],
+ type: 'array_merge',
+ always_inherit: true,
+ ui: {
+ path: 'Chat > Filtering >> Blocked Users',
+ component: 'basic-terms',
+ removable: true,
+ words: false
+ }
+ });
+
+
+ this.settings.add('chat.filtering.highlight-basic-users-blocked--regex', {
+ requires: ['chat.filtering.highlight-basic-blocked'],
+ process(ctx) {
+ const val = ctx.get('chat.filtering.highlight-basic-users-blocked');
+ if ( ! val || ! val.length )
+ return null;
+
+ const out = [[], []];
+
+ for(const item of val) {
+ const t = item.t;
+ let v = item.v;
+
+ if ( t === 'glob' )
+ v = glob_to_regex(v);
+
+ else if ( t !== 'raw' )
+ v = escape_regex(v);
+
+ if ( ! v || ! v.length )
+ continue;
+
+ out[item.remove ? 1 : 0].push(v);
+ }
+
+ return out.map(data => {
+ if ( ! data.length )
+ return null;
+
+ return new RegExp(`^${data.join('|')}$`, 'gi');
+ });
+ }
+ });
+
+
+ this.settings.add('chat.filtering.highlight-basic-badges', {
+ default: [],
+ type: 'array_merge',
+ always_inherit: true,
+ ui: {
+ path: 'Chat > Filtering >> Highlight Badges',
+ component: 'badge-highlighting',
+ colored: true,
+ data: () => this.badges.getSettingsBadges()
+ }
+ });
+
+
+ this.settings.add('chat.filtering.highlight-basic-badges--colors', {
+ requires: ['chat.filtering.highlight-basic-badges'],
+ process(ctx) {
+ const val = ctx.get('chat.filtering.highlight-basic-badges');
+ if ( ! val || ! val.length )
+ return null;
+
+ const colors = new Map;
+
+ for(const item of val) {
+ const c = item.c || null,
+ v = item.v;
+
+ colors.set(v, c);
+ }
+
+ return colors;
+ }
+ });
+
+
+ this.settings.add('chat.filtering.highlight-basic-badges-blocked', {
+ default: [],
+ type: 'array_merge',
+ always_inherit: true,
+ ui: {
+ path: 'Chat > Filtering >> Blocked Badges',
+ component: 'badge-highlighting',
+ removable: true,
+ data: () => this.badges.getSettingsBadges()
+ }
+ });
+
+ this.settings.add('chat.filtering.highlight-basic-badges-blocked--list', {
+ requires: ['chat.filtering.highlight-basic-badges-blocked'],
+ process(ctx) {
+ const val = ctx.get('chat.filtering.highlight-basic-badges-blocked');
+ if ( ! val || ! val.length )
+ return null;
+
+ const out = [[], []];
+ for(const item of val)
+ if ( item.v )
+ out[item.remove ? 1 : 0].push(item.v);
+
+ if ( ! out[0].length && ! out[1].length )
+ return null;
+
+ return out;
+ }
+ });
+
this.settings.add('chat.filtering.highlight-basic-terms', {
default: [],
@@ -297,7 +469,6 @@ export default class Chat extends Module {
}
});
-
this.settings.add('chat.filtering.highlight-basic-terms--color-regex', {
requires: ['chat.filtering.highlight-basic-terms'],
process(ctx) {
@@ -636,10 +807,10 @@ export default class Chat extends Module {
if ( id && typeof id === 'number' )
id = `${id}`;
- if ( this.user_ids[id] )
+ if ( id && this.user_ids[id] )
user = this.user_ids[id];
- else if ( this.users[login] && ! no_login )
+ else if ( login && this.users[login] && ! no_login )
user = this.users[login];
if ( user && user.destroyed )
@@ -696,10 +867,10 @@ export default class Chat extends Module {
if ( id && typeof id === 'number' )
id = `${id}`;
- if ( this.room_ids[id] )
+ if ( id && this.room_ids[id] )
room = this.room_ids[id];
- else if ( this.rooms[login] && ! no_login )
+ else if ( login && this.rooms[login] && ! no_login )
room = this.rooms[login];
if ( room && room.destroyed )
@@ -863,7 +1034,9 @@ export default class Chat extends Module {
if ( ! user )
user = msg.user = {};
- user.color = user.color || user.chatColor || null;
+ const ext = msg.extension || {};
+
+ user.color = user.color || user.chatColor || ext.chatColor || null;
user.type = user.type || user.userType || null;
user.id = user.id || user.userID || null;
user.login = user.login || user.userLogin || null;
@@ -888,7 +1061,13 @@ export default class Chat extends Module {
// Standardize Badges
if ( ! msg.badges && user.displayBadges ) {
const b = msg.badges = {};
- for(const item of msg.user.displayBadges)
+ for(const item of user.displayBadges)
+ b[item.setID] = item.version;
+ }
+
+ if ( ! msg.badges && ext.displayBadges ) {
+ const b = msg.badges = {};
+ for(const item of ext.displayBadges)
b[item.setID] = item.version;
}
diff --git a/src/modules/chat/room.js b/src/modules/chat/room.js
index 8946ba56..51f939cc 100644
--- a/src/modules/chat/room.js
+++ b/src/modules/chat/room.js
@@ -185,10 +185,10 @@ export default class Room {
if ( id && typeof id === 'number' )
id = `${id}`;
- if ( this.user_ids[id] )
+ if ( id && this.user_ids[id] )
user = this.user_ids[id];
- else if ( this.users[login] && ! no_login )
+ else if ( login && this.users[login] && ! no_login )
user = this.users[login];
if ( user && user.destroyed )
diff --git a/src/modules/chat/tokenizers.jsx b/src/modules/chat/tokenizers.jsx
index 7cb50c39..120b58da 100644
--- a/src/modules/chat/tokenizers.jsx
+++ b/src/modules/chat/tokenizers.jsx
@@ -268,6 +268,119 @@ export const Mentions = {
// Custom Highlight Terms
// ============================================================================
+export const UserHighlights = {
+ type: 'user_highlight',
+ priority: 90,
+
+ process(tokens, msg, user) {
+ if ( user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own') )
+ return tokens;
+
+ const colors = this.context.get('chat.filtering.highlight-basic-users--color-regex');
+ if ( ! colors || ! colors.size )
+ return tokens;
+
+ const u = msg.user;
+ for(const [color, regex] of colors) {
+ if ( regex.test(u.login) || regex.test(u.displayName) ) {
+ msg.mentioned = true;
+ if ( color ) {
+ msg.mention_color = color;
+ return tokens;
+ }
+ }
+ }
+
+ return tokens;
+ }
+}
+
+export const BlockedUsers = {
+ type: 'user_block',
+ priority: 100,
+
+ process(tokens, msg, user) {
+ if ( user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own') )
+ return tokens;
+
+ const u = msg.user,
+ regexes = this.context.get('chat.filtering.highlight-basic-users-blocked--regex');
+ if ( ! regexes )
+ return tokens;
+
+ if ( regexes[1] && (regexes[1].test(u.login) || regexes[1].test(u.displayName)) ) {
+ msg.deleted = true;
+ msg.ffz_removed = true;
+ }
+
+ if ( ! msg.deleted && regexes[0] && (regexes[0].test(u.login) || regexes[0].test(u.displayName)) )
+ msg.deleted = true;
+
+ return tokens;
+ }
+}
+
+export const BadgeHighlights = {
+ type: 'badge_highlight',
+ priority: 80,
+
+ process(tokens, msg, user) {
+ if ( user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own') )
+ return tokens;
+
+ const badges = msg.badges;
+ if ( ! badges )
+ return tokens;
+
+ const colors = this.context.get('chat.filtering.highlight-basic-badges--colors');
+ if ( ! colors || ! colors.size )
+ return tokens;
+
+ for(const badge of Object.keys(badges)) {
+ if ( colors.has(badge) ) {
+ const color = colors.get(badge);
+ msg.mentioned = true;
+ if ( color ) {
+ msg.mention_color = color;
+ return tokens;
+ }
+ }
+ }
+
+ return tokens;
+ }
+}
+
+export const BlockedBadges = {
+ type: 'badge_block',
+ priority: 100,
+ process(tokens, msg, user) {
+ if ( user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own') )
+ return tokens;
+
+ const badges = msg.badges;
+ if ( ! badges )
+ return tokens;
+
+ const list = this.context.get('chat.filtering.highlight-basic-badges-blocked--list');
+ if ( ! list || (! list[0].length && ! list[1].length) )
+ return tokens;
+
+ for(const badge of Object.keys(badges)) {
+ if ( list[1].includes(badge) ) {
+ msg.deleted = true;
+ msg.ffz_removed = true;
+ return tokens;
+ }
+
+ if ( ! msg.deleted && list[0].includes(badge) )
+ msg.deleted = true;
+ }
+
+ return tokens;
+ }
+}
+
export const CustomHighlights = {
type: 'highlight',
priority: 100,
@@ -310,7 +423,7 @@ export const CustomHighlights = {
out.push({type: 'text', text: text.slice(idx, nix)});
msg.mentioned = true;
- msg.mention_color = color;
+ msg.mention_color = color || msg.mention_color;
out.push({
type: 'highlight',
diff --git a/src/modules/main_menu/components/badge-highlighting.vue b/src/modules/main_menu/components/badge-highlighting.vue
new file mode 100644
index 00000000..557cb070
--- /dev/null
+++ b/src/modules/main_menu/components/badge-highlighting.vue
@@ -0,0 +1,99 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/modules/main_menu/components/badge-term-editor.vue b/src/modules/main_menu/components/badge-term-editor.vue
new file mode 100644
index 00000000..9d479925
--- /dev/null
+++ b/src/modules/main_menu/components/badge-term-editor.vue
@@ -0,0 +1,213 @@
+
+
+
+
+
![]()
+
+
+
+ {{ t('setting.terms.invalid-badge', 'unknown/unloaded badge') }}
+
+
+ {{ current.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/modules/main_menu/components/basic-terms.vue b/src/modules/main_menu/components/basic-terms.vue
index efb3878e..a8c5dc0c 100644
--- a/src/modules/main_menu/components/basic-terms.vue
+++ b/src/modules/main_menu/components/basic-terms.vue
@@ -3,6 +3,7 @@
-
+
@@ -137,6 +137,10 @@ let id = 0;
export default {
props: {
term: Object,
+ words: {
+ type: Boolean,
+ default: true
+ },
colored: {
type: Boolean,
default: false
diff --git a/src/sites/twitch-twilight/modules/chat/line.js b/src/sites/twitch-twilight/modules/chat/line.js
index fc024443..9584e95d 100644
--- a/src/sites/twitch-twilight/modules/chat/line.js
+++ b/src/sites/twitch-twilight/modules/chat/line.js
@@ -36,13 +36,19 @@ export default class ChatLine extends Module {
this.ChatLine = this.fine.define(
'chat-line',
- n => n.renderMessageBody && n.props && !has(n.props, 'hasModPermissions'),
+ n => n.renderMessageBody && n.props && ! n.onExtensionNameClick && !has(n.props, 'hasModPermissions'),
+ Twilight.CHAT_ROUTES
+ );
+
+ this.ExtensionLine = this.fine.define(
+ 'extension-line',
+ n => n.renderMessageBody && n.onExtensionNameClick,
Twilight.CHAT_ROUTES
);
this.ChatRoomLine = this.fine.define(
'chat-room-line',
- n => n.renderMessageBody && n.props && has(n.props, 'hasModPermissions'),
+ n => n.renderMessageBody && n.props && ! n.onExtensionNameClick && has(n.props, 'hasModPermissions'),
Twilight.CHAT_ROUTES
);
@@ -78,7 +84,11 @@ export default class ChatLine extends Module {
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.highlight-basic-terms--color-regex', this.updateLines, this);
+ this.chat.context.on('changed:chat.filtering.highlight-basic-users--color-regex', this.updateLines, this);
+ this.chat.context.on('changed:chat.filtering.highlight-basic-badges--colors', this.updateLines, this);
this.chat.context.on('changed:chat.filtering.highlight-basic-blocked--regex', this.updateLines, this);
+ this.chat.context.on('changed:chat.filtering.highlight-basic-users-blocked--regex', this.updateLines, this);
+ this.chat.context.on('changed:chat.filtering.highlight-basic-badges-blocked--list', this.updateLines, this);
const t = this,
React = await this.web_munch.findModule('react');
@@ -692,6 +702,8 @@ export default class ChatLine extends Module {
}, out);
} catch(err) {
+ t.log.info(err);
+
t.log.capture(err, {
extra: {
props: this.props
@@ -704,6 +716,85 @@ export default class ChatLine extends Module {
// Do this after a short delay to hopefully reduce the chance of React
// freaking out on us.
setTimeout(() => this.ChatLine.forceUpdate());
+ });
+
+ this.ExtensionLine.ready(cls => {
+ const old_render = cls.prototype.render;
+
+ cls.prototype.render = function() { try {
+ if ( ! this.props.installedExtensions )
+ return null;
+
+ const msg = t.chat.standardizeMessage(this.props.message),
+ ext = msg && msg.extension;
+ if( ! ext )
+ return null;
+
+ if ( ! this.props.installedExtensions.some(val => {
+ const e = val.extension;
+ return e && e.clientID === ext.clientID && e.version === ext.version;
+ }) )
+ return null;
+
+ const color = t.parent.colors.process(ext.chatColor);
+ let room = msg.roomLogin ? msg.roomLogin : msg.channel ? msg.channel.slice(1) : undefined;
+ if ( ! room && this.props.channelID ) {
+ const r = t.chat.getRoom(this.props.channelID, null, true);
+ if ( r && r.login )
+ room = msg.roomLogin = r.login;
+ }
+
+ const u = t.site.getUser(),
+ r = {id: this.props.channelID, login: room},
+
+ tokens = msg.ffz_tokens = msg.ffz_tokens || t.chat.tokenizeMessage(msg, u, r),
+ rich_content = FFZRichContent && t.chat.pluckRichContent(tokens, msg),
+ bg_css = msg.mentioned && msg.mention_color ? t.parent.inverse_colors.process(msg.mention_color) : null;
+
+ if ( ! tokens.length )
+ return null;
+
+ return e('div', {
+ className: `chat-line__message${msg.mentioned ? ' ffz-mentioned' : ''}${bg_css ? ' ffz-custom-color' : ''}`,
+ style: {backgroundColor: bg_css},
+ 'data-room-id': r.id,
+ 'data-room': r.login,
+ 'data-extension': ext.clientID
+ }, [
+ this.props.showTimestamps && e('span', {
+ className: 'chat-line__timestamp'
+ }, t.chat.formatTime(msg.timestamp)),
+ e('span', {
+ className: 'chat-line__message--badges'
+ }, t.chat.badges.render(msg, e)),
+ e('button', {
+ className: 'chat-line__username notranslate',
+ style: { color },
+ onClick: this.onExtensionNameClick
+ }, e('span', {
+ className: 'chat-author__display-name'
+ }, ext.displayName)),
+ e('span', null, ': '),
+ e('span', {
+ className: 'message'
+ }, t.chat.renderTokens(tokens, e)),
+ rich_content && e(FFZRichContent, rich_content)
+ ]);
+
+ } catch(err) {
+ t.log.info(err);
+ t.log.capture(err, {
+ extra: {
+ props: this.props
+ }
+ });
+
+ return old_render.call(this);
+ } }
+
+ // Do this after a short delay to hopefully reduce the chance of React
+ // freaking out on us.
+ setTimeout(() => this.ExtensionLine.forceUpdate());
})
}
@@ -722,6 +813,14 @@ export default class ChatLine extends Module {
}
}
+ for(const inst of this.ExtensionLine.instances) {
+ const msg = inst.props.message;
+ if ( msg ) {
+ msg.ffz_tokens = null;
+ msg.mentioned = msg.mention_color = null;
+ }
+ }
+
for(const inst of this.ChatRoomLine.instances) {
const msg = inst.props.message;
if ( msg ) {
@@ -737,6 +836,7 @@ export default class ChatLine extends Module {
}
this.ChatLine.forceUpdate();
+ this.ExtensionLine.forceUpdate();
this.ChatRoomLine.forceUpdate();
this.WhisperLine.forceUpdate();