mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-07-24 11:38:30 +00:00
Add convenience method for creating CSS variable or setting blocks of CSS directly in css_tweaks. Start using those variables for things like chat width. Add the ability to highlight messages with mentions in them. Fix Sidebar Swap and Theatre Mode. Closes #312
This commit is contained in:
parent
a45dc472b7
commit
6da5d4c8b5
14 changed files with 213 additions and 49 deletions
|
@ -1,4 +1,18 @@
|
|||
<div class="list-header">4.0.0-beta1.3<span>@c89ba74a13dda449dfec</span> <time datetime="2017-11-16">(2017-11-16)</time></div>
|
||||
<div class="list-header">4.0.0-beta1.3<span>@e82e3deb4ad3e3f1b253</span> <time datetime="2017-11-17">(2017-11-17)</time></div>
|
||||
<ul class="chat-menu-content menu-side-padding">
|
||||
<li>Added: Chat > Behavior > General > Scrollback Length</li>
|
||||
<li>Added: Chat > Filtering > Appearance > Highlight Mentions</li>
|
||||
<li>Fixed: Tooltips with the WOT extension installed.</li>
|
||||
<li>Fixed: Swap Sidebars not working in Theatre Mode.</li>
|
||||
<li>Fixed: Scroll to Change Volume not allowing you to increase the volume on Firefox.</li>
|
||||
</ul>
|
||||
|
||||
<div class="list-header">4.0.0-beta1.3<span>@0c55f4f15b6397d644f4</span> <time datetime="2017-11-17">(2017-11-17)</time></div>
|
||||
<ul class="chat-menu-content menu-side-padding">
|
||||
<li>Fixed: The Stream Uptime display sometimes failing to appear.</li>
|
||||
</ul>
|
||||
|
||||
<div class="list-header">4.0.0-beta1.3<span>@fb9568932222b25ebd88</span> <time datetime="2017-11-16">(2017-11-16)</time></div>
|
||||
<ul class="chat-menu-content menu-side-padding">
|
||||
<li>Added: Automatic Theatre Mode</li>
|
||||
<li>Added: Hide Whispers in Theatre Mode</li>
|
||||
|
|
|
@ -52,6 +52,41 @@ export default class Chat extends Module {
|
|||
// Settings
|
||||
// ========================================================================
|
||||
|
||||
this.settings.add('chat.scrollback-length', {
|
||||
default: 150,
|
||||
ui: {
|
||||
path: 'Chat > Behavior >> General',
|
||||
title: 'Scrollback Length',
|
||||
description: 'Keep up to this many lines in chat. Setting this too high will create lage.',
|
||||
component: 'setting-text-box',
|
||||
process(val) {
|
||||
val = parseInt(val, 10);
|
||||
if ( isNaN(val) || ! isFinite(val) || val < 1 )
|
||||
val = 150;
|
||||
|
||||
return val;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.settings.add('chat.filtering.highlight-mentions', {
|
||||
default: false,
|
||||
ui: {
|
||||
path: 'Chat > Filtering >> Appearance',
|
||||
title: 'Highlight messages that mention you.',
|
||||
component: 'setting-check-box'
|
||||
}
|
||||
});
|
||||
|
||||
this.settings.add('chat.filtering.highlight-tokens', {
|
||||
default: false,
|
||||
ui: {
|
||||
path: 'Chat > Filtering >> Appearance',
|
||||
title: 'Highlight matched words in chat.',
|
||||
component: 'setting-check-box'
|
||||
}
|
||||
});
|
||||
|
||||
this.settings.add('tooltip.images', {
|
||||
default: true,
|
||||
ui: {
|
||||
|
@ -417,11 +452,11 @@ export default class Chat extends Module {
|
|||
}
|
||||
|
||||
|
||||
tokenizeMessage(msg) {
|
||||
tokenizeMessage(msg, user) {
|
||||
let tokens = [{type: 'text', text: msg.message}];
|
||||
|
||||
for(const tokenizer of this.__tokenizers)
|
||||
tokens = tokenizer.process.call(this, tokens, msg);
|
||||
tokens = tokenizer.process.call(this, tokens, msg, user);
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
|
|
@ -201,14 +201,25 @@ export const Mentions = {
|
|||
|
||||
render(token, e) {
|
||||
return e('strong', {
|
||||
className: 'chat-line__message-mention'
|
||||
}, `@${token.recipient}`);
|
||||
className: `chat-line__message-mention${token.me ? ' ffz--mention-me' : ''}`
|
||||
}, `${token.text}`);
|
||||
},
|
||||
|
||||
process(tokens, msg) {
|
||||
process(tokens, msg, user) {
|
||||
if ( ! tokens || ! tokens.length )
|
||||
return tokens;
|
||||
|
||||
let regex, login, display;
|
||||
if ( user && user.login ) {
|
||||
login = user.login.toLowerCase();
|
||||
display = user.display && user.display.toLowerCase();
|
||||
if ( display === login )
|
||||
display = null;
|
||||
|
||||
regex = new RegExp(`([^\\w@#%\\-+=:~]|\\b)?(@?(${user.login.toLowerCase()}${display ? `|${display}` : ''})|@([^\\u0000-\\u007F]+|\\w+)+)([^\\w.\\/@#%&()\\-+=:?~]|\\s|\\b|$)`, 'gi');
|
||||
} else
|
||||
regex = MENTION_REGEX;
|
||||
|
||||
const out = [];
|
||||
for(const token of tokens) {
|
||||
if ( token.type !== 'text' ) {
|
||||
|
@ -216,19 +227,27 @@ export const Mentions = {
|
|||
continue;
|
||||
}
|
||||
|
||||
MENTION_REGEX.lastIndex = 0;
|
||||
regex.lastIndex = 0;
|
||||
const text = token.text;
|
||||
let idx = 0, match;
|
||||
|
||||
while((match = MENTION_REGEX.exec(text))) {
|
||||
const nix = match.index + (match[1] ? match[1].length : 0);
|
||||
while((match = regex.exec(text))) {
|
||||
const nix = match.index + (match[1] ? match[1].length : 0),
|
||||
m = match[3] || match[4],
|
||||
ml = m.toLowerCase(),
|
||||
me = ml === login || ml === display;
|
||||
|
||||
if ( idx !== nix )
|
||||
out.push({type: 'text', text: text.slice(idx, nix)});
|
||||
|
||||
if ( me )
|
||||
msg.mentioned = true;
|
||||
|
||||
out.push({
|
||||
type: 'mention',
|
||||
recipient: match[3],
|
||||
length: match[3].length + 1
|
||||
text: match[2],
|
||||
me,
|
||||
recipient: m
|
||||
});
|
||||
|
||||
idx = nix + match[2].length;
|
||||
|
|
|
@ -17,7 +17,7 @@ import SettingsMenu from './settings_menu';
|
|||
|
||||
|
||||
const ChatTypes = (e => {
|
||||
/*e[e.Post = 0] = 'Post';
|
||||
e[e.Post = 0] = 'Post';
|
||||
e[e.Action = 1] = 'Action';
|
||||
e[e.PostWithMention = 2] = 'PostWithMention';
|
||||
e[e.Ban = 3] = 'Ban';
|
||||
|
@ -27,9 +27,9 @@ const ChatTypes = (e => {
|
|||
e[e.AutoModMessageAllowed = 7] = 'AutoModMessageAllowed';
|
||||
e[e.AutoModMessageDenied = 8] = 'AutoModMessageDenied';
|
||||
e[e.Connected = 9] = 'Connected';
|
||||
e[e.Disconnected = 10] = 'Disconnected';*/
|
||||
e[e.Disconnected = 10] = 'Disconnected';
|
||||
e[e.Reconnect = 11] = 'Reconnect';
|
||||
/*e[e.Hosting = 12] = 'Hosting';
|
||||
e[e.Hosting = 12] = 'Hosting';
|
||||
e[e.Unhost = 13] = 'Unhost';
|
||||
e[e.Subscription = 14] = 'Subscription';
|
||||
e[e.Resubscription = 15] = 'Resubscription';
|
||||
|
@ -38,14 +38,14 @@ const ChatTypes = (e => {
|
|||
e[e.SubscriberOnlyMode = 18] = 'SubscriberOnlyMode';
|
||||
e[e.FollowerOnlyMode = 19] = 'FollowerOnlyMode';
|
||||
e[e.SlowMode = 20] = 'SlowMode';
|
||||
e[e.RoomMods = 21] = 'RoomMods';*/
|
||||
e[e.RoomMods = 21] = 'RoomMods';
|
||||
e[e.RoomState = 22] = 'RoomState';
|
||||
/*e[e.Raid = 23] = 'Raid';
|
||||
e[e.Raid = 23] = 'Raid';
|
||||
e[e.Unraid = 24] = 'Unraid';
|
||||
e[e.Notice = 25] = 'Notice';
|
||||
e[e.Info = 26] = 'Info';*/
|
||||
e[e.Info = 26] = 'Info';
|
||||
e[e.BadgesUpdated = 27] = 'BadgesUpdated';
|
||||
//e[e.Purchase = 28] = 'Purchase';
|
||||
e[e.Purchase = 28] = 'Purchase';
|
||||
return e;
|
||||
})({});
|
||||
|
||||
|
@ -239,29 +239,19 @@ export default class ChatHook extends Module {
|
|||
updateChatCSS() {
|
||||
const width = this.chat.context.get('chat.width'),
|
||||
size = this.chat.context.get('chat.font-size'),
|
||||
font = this.chat.context.get('chat.font-family');
|
||||
lh = Math.round((20/12) * size);
|
||||
|
||||
if ( size === 12 )
|
||||
this.css_tweaks.style.delete('chat-font-size');
|
||||
else {
|
||||
const lh = Math.round((20/12) * size);
|
||||
this.css_tweaks.style.set('chat-font-size',`.chat-list{font-size:${size}px;line-height:${lh}px}`);
|
||||
}
|
||||
let font = this.chat.context.get('chat.font-family') || 'inherit';
|
||||
if ( font.indexOf(' ') !== -1 && font.indexOf(',') === -1 && font.indexOf('"') === -1 && font.indexOf("'") === -1 )
|
||||
font = `"${font}"`;
|
||||
|
||||
if ( ! font )
|
||||
this.css_tweaks.style.delete('chat-font-family');
|
||||
else {
|
||||
let val = font;
|
||||
if ( font.indexOf(' ') !== -1 && val.indexOf(',') === -1 && val.indexOf('"') === -1 && val.indexOf("'") === -1 )
|
||||
val = `"${val}"`;
|
||||
this.css_tweaks.style.set('chat-font-family', `.chat-list{font-family:${val}}`);
|
||||
}
|
||||
this.css_tweaks.setVariable('chat-font-size', `${size}px`);
|
||||
this.css_tweaks.setVariable('chat-line-height', `${lh}px`);
|
||||
this.css_tweaks.setVariable('chat-font-family', font);
|
||||
this.css_tweaks.setVariable('chat-width', `${width}px`);
|
||||
|
||||
|
||||
if ( width === 340 )
|
||||
this.css_tweaks.style.delete('chat-width');
|
||||
else
|
||||
this.css_tweaks.style.set('chat-width', `.whispers--theatre-mode.whispers--right-column-expanded{right:${width}px!important}.persistent-player--theatre,.channel-page__video-player--theatre-mode{width:calc(100% - ${width}px)!important}.channel-page__right-column{width:${width}px!important}`);
|
||||
this.css_tweaks.toggle('chat-font', size === 12 && ! font);
|
||||
this.css_tweaks.toggle('chat-width', width !== 340);
|
||||
}
|
||||
|
||||
updateLineBorders() {
|
||||
|
@ -273,6 +263,13 @@ export default class ChatHook extends Module {
|
|||
this.css_tweaks.toggle('chat-borders-wide', mode === 4);
|
||||
}
|
||||
|
||||
updateMentionCSS() {
|
||||
const enabled = this.chat.context.get('chat.filtering.highlight-mentions');
|
||||
this.css_tweaks.toggle('chat-mention-token', this.chat.context.get('chat.filtering.highlight-tokens'));
|
||||
this.css_tweaks.toggle('chat-mention-bg', enabled);
|
||||
this.css_tweaks.toggle('chat-mention-bg-alt', enabled && this.chat.context.get('chat.lines.alternate'));
|
||||
}
|
||||
|
||||
|
||||
onEnable() {
|
||||
this.on('site.web_munch:loaded', () => {
|
||||
|
@ -290,9 +287,13 @@ export default class ChatHook extends Module {
|
|||
this.chat.context.on('changed:chat.adjustment-contrast', this.updateColors, this);
|
||||
this.chat.context.on('changed:theme.is-dark', this.updateColors, this);
|
||||
this.chat.context.on('changed:chat.lines.borders', this.updateLineBorders, 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.lines.alternate', val =>
|
||||
this.css_tweaks.toggle('chat-rows', val));
|
||||
this.chat.context.on('changed:chat.lines.alternate', val => {
|
||||
this.css_tweaks.toggle('chat-rows', val);
|
||||
this.updateMentionCSS();
|
||||
});
|
||||
|
||||
this.chat.context.on('changed:chat.lines.padding', val =>
|
||||
this.css_tweaks.toggle('chat-padding', val));
|
||||
|
@ -310,6 +311,7 @@ export default class ChatHook extends Module {
|
|||
this.updateChatCSS();
|
||||
this.updateColors();
|
||||
this.updateLineBorders();
|
||||
this.updateMentionCSS();
|
||||
|
||||
this.ChatController.on('mount', this.chatMounted, this);
|
||||
this.ChatController.on('unmount', this.removeRoom, this);
|
||||
|
@ -360,8 +362,9 @@ export default class ChatHook extends Module {
|
|||
|
||||
cls.prototype.toArray = function() {
|
||||
const buf = this.buffer,
|
||||
size = t.chat.context.get('chat.scrollback-length'),
|
||||
ct = t.chatTypes || ChatTypes,
|
||||
target = buf.length - this.maxSize;
|
||||
target = buf.length - size;
|
||||
|
||||
if ( target > 0 ) {
|
||||
let removed = 0, last;
|
||||
|
|
|
@ -53,8 +53,10 @@ export default class ChatLine extends Module {
|
|||
|
||||
|
||||
cls.prototype.render = function() {
|
||||
const msg = this.props.message,
|
||||
is_action = msg.type === 1,
|
||||
const types = t.chat.chatTypes || {},
|
||||
|
||||
msg = this.props.message,
|
||||
is_action = msg.type === types.Action,
|
||||
user = msg.user,
|
||||
color = t.parent.colors.process(user.color),
|
||||
/*bg_rgb = Color.RGBA.fromHex(user.color),
|
||||
|
@ -67,11 +69,11 @@ export default class ChatLine extends Module {
|
|||
if ( ! msg.message && msg.messageParts )
|
||||
detokenizeMessage(msg);
|
||||
|
||||
const tokens = t.chat.tokenizeMessage(msg),
|
||||
const tokens = t.chat.tokenizeMessage(msg, {login: this.props.currentUserLogin, display: this.props.currentUserDisplayName}),
|
||||
fragment = t.chat.renderTokens(tokens, e);
|
||||
|
||||
const out = e('div', {
|
||||
className: 'chat-line__message',
|
||||
className: `chat-line__message ${msg.mentioned ? 'ffz-mentioned' : ''}`,
|
||||
//style: { backgroundColor: bg_css },
|
||||
'data-room-id': this.props.channelID,
|
||||
'data-room': room,
|
||||
|
|
|
@ -199,6 +199,16 @@ export default class CSSTweaks extends Module {
|
|||
}
|
||||
|
||||
|
||||
set(key, val) { return this.style.set(key, val) }
|
||||
delete(key) { return this.style.delete(key) }
|
||||
|
||||
setVariable(key, val, scope = 'body') {
|
||||
this.style.set(`var--${key}`, `${scope} { --ffz-${key}: ${val}; }`);
|
||||
}
|
||||
|
||||
deleteVariable(key) { this.style.delete(`var--${key}`) }
|
||||
|
||||
|
||||
populate() {
|
||||
if ( this.chunks_loaded )
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
.chat-list {
|
||||
font-size: var(--ffz-chat-font-size);
|
||||
line-height: var(--ffz-chat-line-height);
|
||||
font-family: var(--ffz-chat-font-family);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
.chat-line__message.ffz-mentioned {
|
||||
&:nth-child(2n+0) {
|
||||
background-color: rgba(255,127,127,.4);
|
||||
|
||||
.theme--dark & {
|
||||
background-color: rgba(255,0,0,.3);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
.chat-line__message.ffz-mentioned {
|
||||
background-color: rgba(255,127,127,.2);
|
||||
|
||||
.theme--dark & {
|
||||
background-color: rgba(255,0,0,.2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
.ffz--mention-me {
|
||||
border-radius: .5rem;
|
||||
padding: .3rem;
|
||||
font-weight: 700;
|
||||
|
||||
color: #fff;
|
||||
background: rgba(0,0,0,0.5);
|
||||
|
||||
.theme--dark & {
|
||||
color: #000;
|
||||
background-color: rgba(255,255,255,0.5);
|
||||
}
|
||||
}
|
|
@ -3,13 +3,13 @@
|
|||
.chat-line__raid,
|
||||
.chat-line__subscribe,
|
||||
.chat-line__message {
|
||||
background-color: transparent !important;
|
||||
background-color: transparent;
|
||||
|
||||
&:nth-child(2n+0) {
|
||||
background-color: rgba(0,0,0,0.1) !important;
|
||||
background-color: rgba(0,0,0,0.1);
|
||||
|
||||
.theme--dark & {
|
||||
background-color: rgba(255,255,255,0.05) !important;
|
||||
background-color: rgba(255,255,255,0.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
body .whispers--theatre-mode.whispers--right-column-expanded {
|
||||
right: var(--ffz-chat-width);
|
||||
}
|
||||
|
||||
body .persistent-player--theatre,
|
||||
body .channel-page__video-player--theatre-mode {
|
||||
width: calc(100% - var(--ffz-chat-width));
|
||||
}
|
||||
|
||||
body .channel-page__right-column {
|
||||
width: var(--ffz-chat-width);
|
||||
}
|
|
@ -31,3 +31,19 @@
|
|||
border-right-color: #2c2541;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.right-column.right-column--theatre {
|
||||
right: unset !important;
|
||||
left: 0 !important;
|
||||
}
|
||||
|
||||
.channel-page__video-player--theatre-mode {
|
||||
left: unset !important;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
body .whispers--theatre-mode.whispers--right-column-expanded {
|
||||
left: var(--ffz-chat-width) !important;
|
||||
right: 0 !important;
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
font-style: normal;
|
||||
}
|
||||
|
||||
//[data-a-target="emote-picker-button"] figure:before,
|
||||
[class^="ffz-i-"]:before, [class*=" ffz-i-"]:before {
|
||||
font-family: "ffz-fontello";
|
||||
font-style: normal;
|
||||
|
@ -49,13 +50,31 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//[data-a-target="emote-picker-button"] figure:before,
|
||||
.ffz-i-zreknarf:before {
|
||||
content: '\e801'; /* '' */
|
||||
width: 1.3em;
|
||||
margin: .5rem .05rem 0;
|
||||
}
|
||||
|
||||
/*[data-a-target="emote-picker-button"] {
|
||||
.tw-button-icon__icon {
|
||||
padding: .25rem .4rem;
|
||||
|
||||
figure {
|
||||
display: inline;
|
||||
|
||||
&:before {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
svg {
|
||||
display: none
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
.ffz-i-cancel:before { content: '\e800'; } /* '' */
|
||||
.ffz-i-search:before { content: '\e802'; } /* '' */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue