diff --git a/src/main.js b/src/main.js index bdd53f5a..1f53a092 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: '-rc21.8', + major: 4, minor: 0, revision: 0, extra: '-rc22', commit: __git_commit__, build: __webpack_hash__, toString: () => diff --git a/src/modules/chat/index.js b/src/modules/chat/index.js index 910a5fc1..e799658c 100644 --- a/src/modules/chat/index.js +++ b/src/modules/chat/index.js @@ -587,12 +587,11 @@ export default class Chat extends Module { default: false, ui: { component: 'setting-check-box', - path: 'Chat > Filtering >> Appearance', + path: 'Chat > Viewer Cards >> Behavior', title: 'Enable opening viewer cards by clicking mentions in chat.' } }); - this.settings.add('chat.filtering.highlight-mentions', { default: false, ui: { diff --git a/src/modules/chat/tokenizers.jsx b/src/modules/chat/tokenizers.jsx index 9da39fcf..c9e64837 100644 --- a/src/modules/chat/tokenizers.jsx +++ b/src/modules/chat/tokenizers.jsx @@ -13,7 +13,7 @@ import {TWITCH_EMOTE_BASE, REPLACEMENT_BASE, REPLACEMENTS} from 'utilities/const const EMOTE_CLASS = 'chat-image chat-line__message--emote', LINK_REGEX = /([^\w@#%\-+=:~])?((?:(https?:\/\/)?(?:[\w@#%\-+=:~]+\.)+[a-z]{2,6}(?:\/[\w./@#%&()\-+=:?~]*)?))([^\w./@#%&()\-+=:?~]|\s|$)/g, //MENTION_REGEX = /([^\w@#%\-+=:~])?(@([^\u0000-\u007F]+|\w+)+)([^\w./@#%&()\-+=:?~]|\s|$)/g; // eslint-disable-line no-control-regex - MENTION_REGEX = /^(['"*([{<\\/]*)(@?)((?:[^\u0000-\u007F]|[\w-])+)/; // eslint-disable-line no-control-regex + MENTION_REGEX = /^(['"*([{<\\/]*)(@)((?:[^\u0000-\u007F]|[\w-])+)/; // eslint-disable-line no-control-regex // ============================================================================ @@ -222,18 +222,17 @@ export const Mentions = { if ( ! tokens || ! tokens.length ) return tokens; - if ( user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own') ) - return tokens; + const can_highlight_user = user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own'); - let regex, login, display; - if ( user && user.login ) { + let regex, login, display, mentionable = false; + if ( user && user.login && ! can_highlight_user ) { login = user.login.toLowerCase(); display = user.displayName && user.displayName.toLowerCase(); if ( display === login ) display = null; + mentionable = true; regex = new RegExp(`^(['"*([{<\\/]*)(?:(@?)(${user.login.toLowerCase()}${display ? `|${display}` : ''})|@((?:[^\u0000-\u007F]|[\\w-])+))`, 'i'); - //regex = new RegExp(`([^\\w@#%\\-+=:~]|\\b)?(@?(${user.login.toLowerCase()}${display ? `|${display}` : ''})|@([^\\u0000-\\u007F]+|\\w+)+)([^\\w.\\/@#%&()\\-+=:?~]|\\s|\\b|$)`, 'gi'); } else regex = MENTION_REGEX; @@ -268,7 +267,7 @@ export const Mentions = { } else { recipient = match[3]; - mentioned = true; + mentioned = mentionable; } out.push({ diff --git a/src/modules/main_menu/components/setting-color-box.vue b/src/modules/main_menu/components/setting-color-box.vue new file mode 100644 index 00000000..3103ad9d --- /dev/null +++ b/src/modules/main_menu/components/setting-color-box.vue @@ -0,0 +1,69 @@ + + + \ No newline at end of file diff --git a/src/sites/twitch-twilight/modules/chat/index.js b/src/sites/twitch-twilight/modules/chat/index.js index 92a52173..62539881 100644 --- a/src/sites/twitch-twilight/modules/chat/index.js +++ b/src/sites/twitch-twilight/modules/chat/index.js @@ -18,6 +18,7 @@ import ChatLine from './line'; import SettingsMenu from './settings_menu'; import EmoteMenu from './emote_menu'; import Input from './input'; +import ViewerCards from './viewer_card'; const REGEX_EMOTES = { @@ -151,6 +152,7 @@ export default class ChatHook extends Module { this.inject(SettingsMenu); this.inject(EmoteMenu); this.inject(Input); + this.inject(ViewerCards); this.ChatService = this.fine.define( 'chat-service', @@ -355,6 +357,7 @@ export default class ChatHook extends Module { ic.contrast = contrast; this.updateChatLines(); + this.emit(':update-colors'); } diff --git a/src/sites/twitch-twilight/modules/chat/viewer_card.jsx b/src/sites/twitch-twilight/modules/chat/viewer_card.jsx new file mode 100644 index 00000000..2c8a7e3d --- /dev/null +++ b/src/sites/twitch-twilight/modules/chat/viewer_card.jsx @@ -0,0 +1,91 @@ +'use strict'; + +import Module from 'utilities/module'; + +// ============================================================================ +// Vanilla Viewer Cards +// ============================================================================ + +export default class ViewerCards extends Module { + constructor(...args) { + super(...args); + + this.inject('chat'); + this.inject('settings'); + this.inject('site.css_tweaks'); + this.inject('site.fine'); + + this.last_login = null; + + this.settings.add('chat.viewer-cards.highlight-chat', { + default: false, + ui: { + path: 'Chat > Viewer Cards >> Appearance', + title: 'Highlight messages from users with open viewer cards.', + component: 'setting-check-box' + } + }); + + this.settings.add('chat.viewer-cards.color', { + default: '', + ui: { + path: 'Chat > Viewer Cards >> Appearance', + title: 'Highlight Color', + component: 'setting-color-box' + } + }); + + this.settings.add('chat.viewer-cards.use-color', { + requires: ['chat.viewer-cards.highlight-chat', 'chat.viewer-cards.color'], + process(ctx) { + if ( ctx.get('chat.viewer-cards.highlight-chat') ) + return ctx.get('chat.viewer-cards.color'); + } + }) + + this.ViewerCard = this.fine.define( + 'chat-viewer-card', + n => n.toggleGiftPage && n.onWhisperButtonClick + ); + } + + onEnable() { + this.chat.context.on('changed:chat.viewer-cards.highlight-chat', this.refreshStyle, this); + this.chat.context.on('changed:chat.viewer-cards.color', this.refreshStyle, this); + this.on('..:update-colors', this.refreshStyle, this); + + this.ViewerCard.on('mount', this.updateCard, this); + this.ViewerCard.on('update', this.updateCard, this); + this.ViewerCard.on('unmount', this.unmountCard, this); + } + + refreshStyle() { + this.updateStyle(this.last_login); + } + + updateStyle(login) { + this.last_login = login; + if ( login && this.chat.context.get('chat.viewer-cards.highlight-chat') ) { + let color = this.chat.context.get('chat.viewer-cards.color'); + if ( color && color.length ) + color = this.parent.inverse_colors.process(color); + else if ( this.chat.context.get('theme.is-dark') ) + color = 'rgba(0,80,255,0.2)'; + else + color = 'rgba(128,170,255,0.2)'; + + this.css_tweaks.set('viewer-card-highlight', `body .chat-list .chat-line__message:not(.chat-line--inline):nth-child(1n+0)[data-user="${login}"] { + background-color: ${color} !important; +}`); + } else + this.css_tweaks.delete('viewer-card-highlight'); + } + + updateCard(inst) { + this.updateStyle(inst.props && inst.props.targetLogin); + } + + unmountCard() { + this.updateStyle(); + } +} \ No newline at end of file