mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-06 06:10:54 +00:00
4.20.18
* Added: Setting to apply username colors to chat mentions. (Closes #753) * Changed: Stream links now use a darker color. * Changed: Make the icon for FFZ's Alternative Viewer Count slightly larger. * Fixed: Crazy flickering when disabling hosting. * Fixed: Stream links showing up on the home page and not just the live page. * Fixed: Better detection for channels where the Host button should appear. * Fixed: FFZ's Alternative Viewer Count metadata not updating correctly when FS Chat is in use.
This commit is contained in:
parent
2f105eb3c4
commit
fa3d73e05a
10 changed files with 158 additions and 14 deletions
15
package-lock.json
generated
15
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "frankerfacez",
|
"name": "frankerfacez",
|
||||||
"version": "4.20.15",
|
"version": "4.20.17",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -5615,6 +5615,14 @@
|
||||||
"minimist": "^1.2.5"
|
"minimist": "^1.2.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mnemonist": {
|
||||||
|
"version": "0.38.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.0.tgz",
|
||||||
|
"integrity": "sha512-OrqILDYOEGVFooAbGid3/P9jdjWuZONlGHVyjfZnvg65+ZQ/QM5dOms+yADY/WURd1NFhCqjf/VJGFlnJToLJQ==",
|
||||||
|
"requires": {
|
||||||
|
"obliterator": "^1.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"move-concurrently": {
|
"move-concurrently": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||||
|
@ -6269,6 +6277,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"obliterator": {
|
||||||
|
"version": "1.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz",
|
||||||
|
"integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig=="
|
||||||
|
},
|
||||||
"obuf": {
|
"obuf": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "frankerfacez",
|
"name": "frankerfacez",
|
||||||
"author": "Dan Salvato LLC",
|
"author": "Dan Salvato LLC",
|
||||||
"version": "4.20.17",
|
"version": "4.20.18",
|
||||||
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -78,6 +78,7 @@
|
||||||
"js-cookie": "^2.2.1",
|
"js-cookie": "^2.2.1",
|
||||||
"markdown-it": "^11.0.0",
|
"markdown-it": "^11.0.0",
|
||||||
"markdown-it-link-attributes": "^3.0.0",
|
"markdown-it-link-attributes": "^3.0.0",
|
||||||
|
"mnemonist": "^0.38.0",
|
||||||
"path-to-regexp": "^3.0.0",
|
"path-to-regexp": "^3.0.0",
|
||||||
"popper.js": "^1.14.3",
|
"popper.js": "^1.14.3",
|
||||||
"raven-js": "^3.24.2",
|
"raven-js": "^3.24.2",
|
||||||
|
|
|
@ -628,6 +628,16 @@ export default class Chat extends Module {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.settings.add('chat.filtering.color-mentions', {
|
||||||
|
default: false,
|
||||||
|
ui: {
|
||||||
|
component: 'setting-check-box',
|
||||||
|
path: 'Chat > Filtering >> Appearance',
|
||||||
|
title: 'Display mentions in chat with username colors.',
|
||||||
|
description: '**Note:** Not compatible with color overrides as mentions do not include user IDs.'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.settings.add('chat.filtering.bold-mentions', {
|
this.settings.add('chat.filtering.bold-mentions', {
|
||||||
default: true,
|
default: true,
|
||||||
ui: {
|
ui: {
|
||||||
|
@ -853,6 +863,21 @@ export default class Chat extends Module {
|
||||||
for(const room of this.iterateRooms())
|
for(const room of this.iterateRooms())
|
||||||
room.buildBitsCSS();
|
room.buildBitsCSS();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.context.on('changed:chat.filtering.color-mentions', async val => {
|
||||||
|
if ( val )
|
||||||
|
await this.createColorCache();
|
||||||
|
else
|
||||||
|
this.color_cache = null;
|
||||||
|
|
||||||
|
this.emit(':update-lines');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async createColorCache() {
|
||||||
|
const LRUCache = await require(/* webpackChunkName: 'utils' */ 'mnemonist/lru-cache');
|
||||||
|
this.color_cache = new LRUCache(150);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -866,6 +891,9 @@ export default class Chat extends Module {
|
||||||
|
|
||||||
|
|
||||||
onEnable() {
|
onEnable() {
|
||||||
|
if ( this.context.get('chat.filtering.color-mentions') )
|
||||||
|
this.createColorCache().then(() => this.emit(':update-lines'));
|
||||||
|
|
||||||
for(const key in TOKENIZERS)
|
for(const key in TOKENIZERS)
|
||||||
if ( has(TOKENIZERS, key) )
|
if ( has(TOKENIZERS, key) )
|
||||||
this.addTokenizer(TOKENIZERS[key]);
|
this.addTokenizer(TOKENIZERS[key]);
|
||||||
|
@ -1143,6 +1171,9 @@ export default class Chat extends Module {
|
||||||
user.displayName = user.displayName || user.userDisplayName || user.login || ext.displayName;
|
user.displayName = user.displayName || user.userDisplayName || user.login || ext.displayName;
|
||||||
user.isIntl = user.login && user.displayName && user.displayName.trim().toLowerCase() !== user.login;
|
user.isIntl = user.login && user.displayName && user.displayName.trim().toLowerCase() !== user.login;
|
||||||
|
|
||||||
|
if ( this.color_cache && user.color )
|
||||||
|
this.color_cache.set(user.login, user.color);
|
||||||
|
|
||||||
// Standardize Message Content
|
// Standardize Message Content
|
||||||
if ( ! msg.message && msg.messageParts )
|
if ( ! msg.message && msg.messageParts )
|
||||||
this.detokenizeMessage(msg);
|
this.detokenizeMessage(msg);
|
||||||
|
|
|
@ -209,8 +209,15 @@ export const Mentions = {
|
||||||
},
|
},
|
||||||
|
|
||||||
render(token, createElement) {
|
render(token, createElement) {
|
||||||
|
let color = token.color;
|
||||||
|
if ( color ) {
|
||||||
|
const chat = this.resolve('site.chat');
|
||||||
|
color = chat ? chat.colors.process(color) : color;
|
||||||
|
}
|
||||||
|
|
||||||
return (<strong
|
return (<strong
|
||||||
class={`chat-line__message-mention${token.me ? ' ffz--mention-me' : ''}`}
|
class={`chat-line__message-mention${token.me ? ' ffz--mention-me' : ''}`}
|
||||||
|
style={{color}}
|
||||||
data-login={token.recipient}
|
data-login={token.recipient}
|
||||||
onClick={this.handleMentionClick}
|
onClick={this.handleMentionClick}
|
||||||
>
|
>
|
||||||
|
@ -270,11 +277,15 @@ export const Mentions = {
|
||||||
mentioned = mentionable;
|
mentioned = mentionable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rlower = recipient ? recipient.toLowerCase() : '',
|
||||||
|
color = this.color_cache ? this.color_cache.get(rlower) : null;
|
||||||
|
|
||||||
out.push({
|
out.push({
|
||||||
type: 'mention',
|
type: 'mention',
|
||||||
text: `${at}${recipient}`,
|
text: `${at}${recipient}`,
|
||||||
me: mentioned,
|
me: mentioned,
|
||||||
recipient: recipient ? recipient.toLowerCase() : ''
|
color,
|
||||||
|
recipient: rlower
|
||||||
});
|
});
|
||||||
|
|
||||||
if ( mentioned ) {
|
if ( mentioned ) {
|
||||||
|
|
44
src/modules/main_menu/components/performance.vue
Normal file
44
src/modules/main_menu/components/performance.vue
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<pre>{{ JSON.stringify(events, null, '\t') }}</pre>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import {deep_copy} from 'utilities/object';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ['item', 'context'],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
events: deep_copy(this.item.getEvents())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
initial_time() {
|
||||||
|
const event = this.events[0];
|
||||||
|
return event ? event.ts : 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.onEvent = this.onEvent.bind(this);
|
||||||
|
this.item.setListener(this.onEvent);
|
||||||
|
},
|
||||||
|
|
||||||
|
destroyed() {
|
||||||
|
this.onEvent = null;
|
||||||
|
this.item.setListener(null);
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onEvent(event) {
|
||||||
|
this.events.push(deep_copy(event));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
|
@ -21,6 +21,7 @@ export default class Channel extends Module {
|
||||||
|
|
||||||
this.inject('i18n');
|
this.inject('i18n');
|
||||||
this.inject('settings');
|
this.inject('settings');
|
||||||
|
this.inject('site.apollo');
|
||||||
this.inject('site.css_tweaks');
|
this.inject('site.css_tweaks');
|
||||||
this.inject('site.elemental');
|
this.inject('site.elemental');
|
||||||
this.inject('site.subpump');
|
this.inject('site.subpump');
|
||||||
|
@ -71,6 +72,18 @@ export default class Channel extends Module {
|
||||||
USER_PAGES,
|
USER_PAGES,
|
||||||
{childNodes: true, subtree: true}, 1
|
{childNodes: true, subtree: true}, 1
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const strip_host = resp => {
|
||||||
|
if ( this.settings.get('channel.hosting.enable') )
|
||||||
|
return;
|
||||||
|
|
||||||
|
const user = resp?.data?.user;
|
||||||
|
if ( user )
|
||||||
|
user.hosting = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.apollo.registerModifier('UseHosting', strip_host, false);
|
||||||
|
this.apollo.registerModifier('PlayerTrackingContextQuery', strip_host, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
onEnable() {
|
onEnable() {
|
||||||
|
@ -210,7 +223,8 @@ export default class Channel extends Module {
|
||||||
|
|
||||||
if ( ! el._ffz_links && want_links ) {
|
if ( ! el._ffz_links && want_links ) {
|
||||||
const link = el.querySelector('a .tw-line-height-heading'),
|
const link = el.querySelector('a .tw-line-height-heading'),
|
||||||
cont = link && link.closest('.tw-flex');
|
anchor = link && link.closest('a'),
|
||||||
|
cont = anchor && anchor.closest('.tw-flex');
|
||||||
|
|
||||||
if ( cont && el.contains(cont) ) {
|
if ( cont && el.contains(cont) ) {
|
||||||
el._ffz_links = <div class="ffz--links tw-mg-l-1"></div>;
|
el._ffz_links = <div class="ffz--links tw-mg-l-1"></div>;
|
||||||
|
@ -225,7 +239,7 @@ export default class Channel extends Module {
|
||||||
const login = el._ffz_link_login = props.channelLogin;
|
const login = el._ffz_link_login = props.channelLogin;
|
||||||
if ( login ) {
|
if ( login ) {
|
||||||
const make_link = (link, text) => {
|
const make_link = (link, text) => {
|
||||||
const a = <a href={link} class="tw-c-text-inherit tw-interactive tw-pd-x-1 tw-font-size-5">{text}</a>;
|
const a = <a href={link} class="tw-c-text-alt-2 tw-interactive tw-pd-x-1 tw-font-size-5">{text}</a>;
|
||||||
a.addEventListener('click', event => {
|
a.addEventListener('click', event => {
|
||||||
if ( event.ctrlKey || event.shiftKey || event.altKey )
|
if ( event.ctrlKey || event.shiftKey || event.altKey )
|
||||||
return;
|
return;
|
||||||
|
@ -240,6 +254,9 @@ export default class Channel extends Module {
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( el._ffz_links.closest('.home-header-sticky') )
|
||||||
|
el._ffz_links.innerHTML = '';
|
||||||
|
else
|
||||||
setChildren(el._ffz_links, [
|
setChildren(el._ffz_links, [
|
||||||
make_link(`/${login}/schedule`, this.i18n.t('channel.links.schedule', 'Schedule')),
|
make_link(`/${login}/schedule`, this.i18n.t('channel.links.schedule', 'Schedule')),
|
||||||
make_link(`/${login}/videos`, this.i18n.t('channel.links.videos', 'Videos')),
|
make_link(`/${login}/videos`, this.i18n.t('channel.links.videos', 'Videos')),
|
||||||
|
@ -310,6 +327,7 @@ export default class Channel extends Module {
|
||||||
login: props.channelLogin,
|
login: props.channelLogin,
|
||||||
display_name: props.displayName,
|
display_name: props.displayName,
|
||||||
live: props.isLive && ! props.videoID && ! props.clipSlug,
|
live: props.isLive && ! props.videoID && ! props.clipSlug,
|
||||||
|
video: !!(props.videoID || props.clipSlug),
|
||||||
live_since: props.liveSince
|
live_since: props.liveSince
|
||||||
},
|
},
|
||||||
props,
|
props,
|
||||||
|
@ -319,7 +337,7 @@ export default class Channel extends Module {
|
||||||
},
|
},
|
||||||
el,
|
el,
|
||||||
getViewerCount: () => {
|
getViewerCount: () => {
|
||||||
const thing = el.querySelector('p[data-a-target="animated-channel-viewers-count"]'),
|
const thing = cont.querySelector('p[data-a-target="animated-channel-viewers-count"]'),
|
||||||
r = thing && this.fine.getReactInstance(thing),
|
r = thing && this.fine.getReactInstance(thing),
|
||||||
p = r?.memoizedProps?.children?.props;
|
p = r?.memoizedProps?.children?.props;
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ 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), this);
|
||||||
|
this.on('chat:update-lines', this.updateLines, this);
|
||||||
|
|
||||||
this.chat.context.on('changed:chat.emoji.style', 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.bits.stack', this.updateLines, this);
|
||||||
|
|
|
@ -83,14 +83,14 @@ export default class HostButton extends Module {
|
||||||
},
|
},
|
||||||
|
|
||||||
label: data => {
|
label: data => {
|
||||||
if ( ! data.channel.live )
|
|
||||||
return;
|
|
||||||
|
|
||||||
const ffz_user = this.site.getUser();
|
const ffz_user = this.site.getUser();
|
||||||
|
|
||||||
if ( ! this.settings.get('metadata.host-button') || ! ffz_user || ! data.channel || data.channel.login === ffz_user.login )
|
if ( ! this.settings.get('metadata.host-button') || ! ffz_user || ! data.channel || data.channel.login === ffz_user.login )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if ( data.channel.video && ! this.isChannelHosted(data.channel.login) )
|
||||||
|
return;
|
||||||
|
|
||||||
if ( this._host_updating )
|
if ( this._host_updating )
|
||||||
return this.i18n.t('metadata.host-button.updating', 'Updating...');
|
return this.i18n.t('metadata.host-button.updating', 'Updating...');
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ffz-stat[data-key="viewers"] figure {
|
||||||
|
font-size: 1.6rem;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
.ffz-stat-text {
|
.ffz-stat-text {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
|
|
|
@ -13,6 +13,20 @@ export default class Timing extends Module {
|
||||||
super(...args);
|
super(...args);
|
||||||
|
|
||||||
this.events = [];
|
this.events = [];
|
||||||
|
|
||||||
|
this._listener = null;
|
||||||
|
|
||||||
|
this.on('settings:enabled', () => {
|
||||||
|
this.resolve('settings').addUI('timing.info', {
|
||||||
|
path: 'Debugging > Performance >> Info @{"sort": -1000}',
|
||||||
|
force_seen: true,
|
||||||
|
component: 'performance',
|
||||||
|
|
||||||
|
setListener: fn => this._listener = fn,
|
||||||
|
getEvents: () => this.events,
|
||||||
|
getTiming: () => this
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
__time() { /* no-op */ } // eslint-disable-line class-methods-use-this
|
__time() { /* no-op */ } // eslint-disable-line class-methods-use-this
|
||||||
|
@ -20,5 +34,7 @@ export default class Timing extends Module {
|
||||||
addEvent(event) {
|
addEvent(event) {
|
||||||
event.ts = performance.now();
|
event.ts = performance.now();
|
||||||
this.events.push(event);
|
this.events.push(event);
|
||||||
|
if ( this._listener )
|
||||||
|
this._listener(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue