1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-08-07 14:50:56 +00:00
* Added: Settings for independently changing the colors of chat on Twitch.
* Fixed: Incorrect color being applied to Stream Chat.
* Changed: Style of in-line message reply tags.
* Changed: Set more users to request link info from the API than the socket service. (75% vs old 50%)
This commit is contained in:
SirStendec 2020-11-23 18:12:07 -05:00
parent c97928fbb7
commit 2cfc613518
10 changed files with 180 additions and 27 deletions

View file

@ -1,7 +1,7 @@
{ {
"name": "frankerfacez", "name": "frankerfacez",
"author": "Dan Salvato LLC", "author": "Dan Salvato LLC",
"version": "4.20.49", "version": "4.20.50",
"description": "FrankerFaceZ is a Twitch enhancement suite.", "description": "FrankerFaceZ is a Twitch enhancement suite.",
"license": "Apache-2.0", "license": "Apache-2.0",
"scripts": { "scripts": {

View file

@ -11,8 +11,8 @@
"name": "API-Based Link Lookups", "name": "API-Based Link Lookups",
"description": "Use the new API to look up links instead of the socket cluster.", "description": "Use the new API to look up links instead of the socket cluster.",
"groups": [ "groups": [
{"value": true, "weight": 50}, {"value": true, "weight": 75},
{"value": false, "weight": 50} {"value": false, "weight": 25}
] ]
} }
} }

View file

@ -508,8 +508,8 @@ export default class Badges extends Module {
} }
render(msg, createElement) { // eslint-disable-line class-methods-use-this render(msg, createElement, skip_hide = false) { // eslint-disable-line class-methods-use-this
const hidden_badges = 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'),
custom_mod = this.parent.context.get('chat.badges.custom-mod'), custom_mod = this.parent.context.get('chat.badges.custom-mod'),
is_mask = badge_style > 5, is_mask = badge_style > 5,

View file

@ -251,7 +251,7 @@ export const Replies = {
} }
return (<strong return (<strong
class={`chat-line__message-mention ffz--pointer-events ffz-tooltip ffz--reply-mention ffz-i-reply${token.me ? ' ffz--mention-me' : ''}`} class={`chat-line__message-mention ffz--pointer-events ffz-tooltip ffz--reply-mention ffz-i-threads${token.me ? ' ffz--mention-me' : ''}`}
style={{color}} style={{color}}
data-tooltip-type="reply" data-tooltip-type="reply"
data-login={token.recipient} data-login={token.recipient}

View file

@ -4,7 +4,7 @@
// Chat Hooks // Chat Hooks
// ============================================================================ // ============================================================================
import {ColorAdjuster} from 'utilities/color'; import {Color, ColorAdjuster} from 'utilities/color';
import {get, has, make_enum, shallow_object_equals, set_equals, deep_equals} from 'utilities/object'; import {get, has, make_enum, shallow_object_equals, set_equals, deep_equals} from 'utilities/object';
import {WEBKIT_CSS as WEBKIT} from 'utilities/constants'; import {WEBKIT_CSS as WEBKIT} from 'utilities/constants';
import {FFZEvent} from 'utilities/events'; import {FFZEvent} from 'utilities/events';
@ -46,8 +46,7 @@ import ViewerCards from './viewer_card';
const MESSAGE_TYPES = make_enum( const MESSAGE_TYPES = make_enum(
'Post', 'Post',
'Action', 'Action'
'PostWithMention'
); );
const MOD_TYPES = make_enum( const MOD_TYPES = make_enum(
@ -137,7 +136,8 @@ const CHAT_TYPES = make_enum(
'InlinePrivateCallout', 'InlinePrivateCallout',
'ChannelPointsReward', 'ChannelPointsReward',
'CommunityChallengeContribution', 'CommunityChallengeContribution',
'CelebrationPurchase' 'CelebrationPurchase',
'LiveMessageSeparator'
); );
@ -592,13 +592,25 @@ export default class ChatHook extends Module {
c = this.colors, c = this.colors,
ic = this.inverse_colors; ic = this.inverse_colors;
let chat_color = this.chat.context.get('theme.color.chat-background') ||
this.chat.context.get('theme.color.background');
if ( ! Color.RGBA.fromCSS(chat_color) )
chat_color = is_dark ? '#191919' : '#E0E0E0';
let chat_text = this.chat.context.get('theme.color.chat-text') ||
this.chat.context.get('theme.color.text');
if ( ! Color.RGBA.fromCSS(chat_text) )
chat_text = is_dark ? '#dad8de' : '#19171c';
// TODO: Get the background color from the theme system. // TODO: Get the background color from the theme system.
// Updated: Use the lightest/darkest colors from alternating rows for better readibility. // Updated: Use the lightest/darkest colors from alternating rows for better readibility.
c._base = is_dark ? '#191919' : '#e0e0e0'; //#0e0c13' : '#faf9fa'; c._base = chat_color; // is_dark ? '#191919' : '#e0e0e0'; //#0e0c13' : '#faf9fa';
c.mode = mode; c.mode = mode;
c.contrast = contrast; c.contrast = contrast;
ic._base = is_dark ? '#dad8de' : '#19171c'; ic._base = chat_text; // is_dark ? '#dad8de' : '#19171c';
ic.mode = mode; ic.mode = mode;
ic.contrast = contrast; ic.contrast = contrast;
@ -749,6 +761,10 @@ export default class ChatHook extends Module {
this.chat.context.on('changed:chat.adjustment-mode', this.updateColors, this); this.chat.context.on('changed:chat.adjustment-mode', this.updateColors, this);
this.chat.context.on('changed:chat.adjustment-contrast', this.updateColors, this); 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:theme.is-dark', this.updateColors, this);
this.chat.context.on('changed:theme.color.background', this.updateColors, this);
this.chat.context.on('changed:theme.color.chat-background', this.updateColors, this);
this.chat.context.on('changed:theme.color.text', this.updateColors, this);
this.chat.context.on('changed:theme.color.chat-text', this.updateColors, this);
this.chat.context.on('changed:chat.lines.borders', this.updateLineBorders, 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-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);
@ -1687,6 +1703,7 @@ export default class ChatHook extends Module {
cls.prototype.flushRawMessages = function() { cls.prototype.flushRawMessages = function() {
try { try {
const out = [], const out = [],
ct = t.chat_types || CHAT_TYPES,
now = Date.now(), now = Date.now(),
raw_delay = t.chat.context.get('chat.delay'), raw_delay = t.chat.context.get('chat.delay'),
delay = raw_delay === -1 ? this.delayDuration : raw_delay, delay = raw_delay === -1 ? this.delayDuration : raw_delay,
@ -1706,6 +1723,18 @@ export default class ChatHook extends Module {
if ( do_remove !== 0 && (do_remove > 1 || ! see_deleted) && this.isDeletable(msg.event) && msg.event.deleted ) if ( do_remove !== 0 && (do_remove > 1 || ! see_deleted) && this.isDeletable(msg.event) && msg.event.deleted )
continue; continue;
const last = this.buffer[this.buffer.length - 1],
type = last?.type;
if ( type === ct.Connected ) {
const non_null = this.buffer.filter(x => x && ct[x.type] && ! NULL_TYPES.includes(ct[x.type]));
if ( non_null.length > 1 )
this.buffer.push({
type: ct.LiveMessageSeparator,
id: 'live-message-separator'
});
}
this.buffer.push(msg.event); this.buffer.push(msg.event);
changed = true; changed = true;

View file

@ -338,7 +338,7 @@ export default class ChatLine extends Module {
override_mode = t.chat.context.get('chat.filtering.display-deleted'), override_mode = t.chat.context.get('chat.filtering.display-deleted'),
msg = t.chat.standardizeMessage(this.props.message), msg = t.chat.standardizeMessage(this.props.message),
reply_tokens = reply_mode === 2 ? ( msg.ffz_reply = msg.ffz_reply || t.chat.tokenizeReply(this.props.reply) ) : null, reply_tokens = (reply_mode === 2 || (reply_mode === 1 && this.props.repliesAppearancePreference !== 'expanded')) ? ( msg.ffz_reply = msg.ffz_reply || t.chat.tokenizeReply(this.props.reply) ) : null,
is_action = msg.messageType === types.Action, is_action = msg.messageType === types.Action,
user = msg.user, user = msg.user,
@ -520,7 +520,7 @@ other {# messages were deleted by a moderator.}
let cls = `chat-line__message${show_class ? ' ffz--deleted-message' : ''}${twitch_clickable ? ' tw-relative' : ''}`, let cls = `chat-line__message${show_class ? ' ffz--deleted-message' : ''}${twitch_clickable ? ' tw-relative' : ''}`,
out = (tokens.length || ! msg.ffz_type) ? [ out = (tokens.length || ! msg.ffz_type) ? [
this.props.showTimestamps && e('span', { (this.props.showTimestamps || this.props.isHistorical) && e('span', {
className: 'chat-line__timestamp' className: 'chat-line__timestamp'
}, t.chat.formatTime(msg.timestamp)), }, t.chat.formatTime(msg.timestamp)),
//twitch_clickable ? //twitch_clickable ?
@ -864,7 +864,7 @@ other {# messages were deleted by a moderator.}
e('div', { e('div', {
className: 'chat-line__message-container' className: 'chat-line__message-container'
}, [ }, [
this.renderReplyLine(), this.props.repliesAppearancePreference === 'expanded' ? this.renderReplyLine() : null,
out out
]), ]),
e('div', { e('div', {

View file

@ -243,7 +243,7 @@ export default class RichContent extends Module {
class={`tw-border-radius-medium tw-elevation-1 ffz--chat-card tw-relative${this.state.unsafe ? ' ffz--unsafe' : ''}`} class={`tw-border-radius-medium tw-elevation-1 ffz--chat-card tw-relative${this.state.unsafe ? ' ffz--unsafe' : ''}`}
style={{'--ffz-color-accent': this.state.accent || null}} style={{'--ffz-color-accent': this.state.accent || null}}
> >
<div class="tw-border-radius-medium tw-c-background-base tw-flex tw-full-width"> <div class="tw-border-radius-medium tw-c-background-alt tw-flex tw-full-width">
{content} {content}
</div> </div>
</div>); </div>);

View file

@ -58,7 +58,7 @@ export default class ThemeEngine extends Module {
return val; return val;
}, },
ui: { ui: {
path: 'Appearance > Theme >> Fonts', path: 'Appearance > Theme >> Fonts @{"sort": 2}',
title: 'Font Size', title: 'Font Size',
description: '**Minimum:** `1`, **Maximum:** `25`, *Old Default:* `12`\n\nHow large should normal text be, in pixels. This may be affected by your browser\'s zoom and font settings.', description: '**Minimum:** `1`, **Maximum:** `25`, *Old Default:* `12`\n\nHow large should normal text be, in pixels. This may be affected by your browser\'s zoom and font settings.',
component: 'setting-text-box', component: 'setting-text-box',
@ -73,7 +73,7 @@ export default class ThemeEngine extends Module {
this.settings.add('theme.color.background', { this.settings.add('theme.color.background', {
default: '', default: '',
ui: { ui: {
path: 'Appearance > Theme >> Colors @{"description": "This is a quick preview of a new system coming soon to FrankerFaceZ. Expect heavy changes here, including separate Basic and Advanced modes, and better color selection."}', path: 'Appearance > Theme >> Colors @{"sort": 0, "description": "This is a quick preview of a new system coming soon to FrankerFaceZ. Expect heavy changes here, including separate Basic and Advanced modes, and better color selection."}',
title: 'Background', title: 'Background',
description: 'Try `#0E0C13` for something close to the old dark theme, or `#0E0E0E` for a nice dark gray. Transparent colors not allowed.', description: 'Try `#0E0C13` for something close to the old dark theme, or `#0E0E0E` for a nice dark gray. Transparent colors not allowed.',
component: 'setting-color-box', component: 'setting-color-box',
@ -132,6 +132,45 @@ export default class ThemeEngine extends Module {
changed: () => this.updateCSS() changed: () => this.updateCSS()
}); });
this.settings.add('theme.color.chat-background', {
default: '',
ui: {
path: 'Appearance > Theme >> Chat Colors @{"sort":1}',
title: 'Background',
component: 'setting-color-box',
sort: 0,
alpha: false
},
changed: () => this.updateCSS()
});
this.settings.add('theme.color.chat-text', {
default: '',
ui: {
path: 'Appearance > Theme >> Chat Colors',
title: 'Text',
description: 'If not set, this will automatically be set to white or black based on the brightness of the background.',
component: 'setting-color-box',
sort: 1
},
changed: () => this.updateCSS()
});
this.settings.add('theme.color.chat-accent', {
default: '',
ui: {
path: 'Appearance > Theme >> Chat Colors',
title: 'Accent',
description: 'The accent color is used for buttons, links, etc.',
component: 'setting-color-box',
alpha: false,
sort: 2
},
changed: () => this.updateCSS()
});
/*this.settings.add('theme.dark', { /*this.settings.add('theme.dark', {
requires: ['theme.is-dark'], requires: ['theme.is-dark'],
default: false, default: false,
@ -275,6 +314,7 @@ The CSS loaded by this setting is far too heavy and can cause performance issues
if ( text ) { if ( text ) {
bits.push(`--color-text-base: ${text.toCSS()};`); bits.push(`--color-text-base: ${text.toCSS()};`);
bits.push(`--color-text-input: ${text.toCSS()};`);
const hsla = text.toHSLA(), const hsla = text.toHSLA(),
alpha = hsla.a; alpha = hsla.a;
@ -325,7 +365,6 @@ The CSS loaded by this setting is far too heavy and can cause performance issues
} }
} }
// Tooltips // Tooltips
let tooltip_bg = Color.RGBA.fromCSS(this.settings.get('theme.color.tooltip.background')), let tooltip_bg = Color.RGBA.fromCSS(this.settings.get('theme.color.tooltip.background')),
tooltip_dark; tooltip_dark;
@ -358,13 +397,95 @@ The CSS loaded by this setting is far too heavy and can cause performance issues
bits.push(`--color-text-tooltip-alt-2: ${hsla._a(alpha - 0.4).toCSS()};`); bits.push(`--color-text-tooltip-alt-2: ${hsla._a(alpha - 0.4).toCSS()};`);
} }
if ( bits.length ) {
this.css_tweaks.set('colors', `body {${bits.join('\n')}}.channel-info-content .tw-accent-region{${accent_bits.join('\n')}}`); // Chat
this.toggleNormalizer(true); const chat_bits = [],
} else { chat_background = Color.RGBA.fromCSS(this.settings.get('theme.color.chat-background'));
this.css_tweaks.delete('colors'); let chat_dark = dark;
this.toggleNormalizer(false); if ( chat_background ) {
chat_background.a = 1;
chat_bits.push(`--color-background-body: ${chat_background.toCSS()};`);
const hsla = chat_background.toHSLA(),
luma = hsla.l;
chat_dark = luma < 0.5;
chat_bits.push(`--color-background-input-focus: ${chat_background.toCSS()};`);
chat_bits.push(`--color-background-base: ${hsla._l(luma + (chat_dark ? .05 : -.05)).toCSS()};`);
chat_bits.push(`--color-background-alt: ${hsla._l(luma + (chat_dark ? .1 : -.1)).toCSS()};`);
chat_bits.push(`--color-background-alt-2: ${hsla._l(luma + (chat_dark ? .15 : -.15)).toCSS()};`);
} }
let chat_text = Color.RGBA.fromCSS(this.settings.get('theme.color.chat-text'));
if ( ! chat_text && chat_background ) {
chat_text = Color.RGBA.fromCSS(chat_dark ? '#FFF' : '#000');
}
if ( chat_text ) {
chat_bits.push(`--color-text-base: ${chat_text.toCSS()};`);
chat_bits.push(`--color-text-input: ${chat_text.toCSS()};`);
const hsla = chat_text.toHSLA(),
alpha = hsla.a;
chat_bits.push(`--color-text-label: ${chat_text.toCSS()};`);
chat_bits.push(`--color-text-label-optional: ${hsla._a(alpha - 0.4).toCSS()};`);
chat_bits.push(`--color-text-alt: ${hsla._a(alpha - 0.2).toCSS()};`);
chat_bits.push(`--color-text-alt-2: ${hsla._a(alpha - 0.4).toCSS()};`);
}
// Accent
const chat_accent = Color.RGBA.fromCSS(this.settings.get('theme.color.chat-accent')),
chat_accent_bits = [];
//this.toggleAccentNormal(! accent);
if ( chat_accent ) {
chat_accent.a = 1;
const hsla = chat_accent.toHSLA(),
luma = hsla.l;
const colors = COLORS.map(x => {
if ( x === 0 )
return chat_accent.toCSS();
return hsla._l(luma + x).toCSS()
});
for(let i=0; i < colors.length; i++) {
chat_bits.push(`--ffz-color-accent-${i+1}:${colors[i]};`);
}
let source = chat_dark ? ACCENT_COLORS.dark : ACCENT_COLORS.light;
for(const [key,val] of Object.entries(source.c)) {
if ( typeof val !== 'number' )
continue;
chat_bits.push(`--color-${key}:${colors[val-1]};`);
}
source = chat_dark ? ACCENT_COLORS.accent_dark : ACCENT_COLORS.accent_light;
for(const [key,val] of Object.entries(source.c)) {
if ( typeof val !== 'number' )
continue;
chat_accent_bits.push(`--color-${key}:${colors[val-1]} !important;`);
}
}
if ( chat_bits.length )
this.css_tweaks.set('chat-colors', `.chat-shell {${chat_bits.join('\n')}}.chat-shell .tw-accent-region{${chat_accent_bits.join('\n')}}`);
else
this.css_tweaks.delete('chat-colors');
this.toggleNormalizer(chat_bits.length || bits.length);
if ( bits.length )
this.css_tweaks.set('colors', `body {${bits.join('\n')}}.channel-info-content .tw-accent-region{${accent_bits.join('\n')}}`);
else
this.css_tweaks.delete('colors');
} }
toggleAccentNormal(enable) { toggleAccentNormal(enable) {

View file

@ -93,7 +93,9 @@
white-space: nowrap; white-space: nowrap;
&:before { &:before {
font-size: 0.8em; font-size: 1.2em;
vertical-align: middle;
color: var(--color-text-base);
} }
background-color: rgba(0,0,0,0.15); background-color: rgba(0,0,0,0.15);

View file

@ -2,7 +2,6 @@
body, body,
.channel-header, .channel-header,
.channel-root__right-column, .channel-root__right-column,
.chat-room,
.chat-viewers__pane, .chat-viewers__pane,
.sunlight-tile, .sunlight-tile,
.multi-stream-player-layout, .multi-stream-player-layout,
@ -13,6 +12,8 @@
.clmgr-table__row, .clmgr-table__row,
.stream-manager--page-view .mosaic-window-body, .stream-manager--page-view .mosaic-window-body,
.room-upsell, .room-upsell,
.chat-room,
.qa-vod-chat,
.video-card { .video-card {
background-color: var(--color-background-base) !important; background-color: var(--color-background-base) !important;
} }