1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-06-30 08:08:32 +00:00
**Note**: This update does not fix all issues with features not working on Twitch's new channel page layout. Due to changes Twitch has been making to their coding practices, it is significantly harder to support their newer pages. We are still trying to determine the best way to support things going forward.

* Added: Chat Actions can be copied as JSON and imported from JSON. (Closes #782)
* Fixed: The player stuttering when attempting to play a clip when the Audio Compressor is set to be enabled by default.
* Fixed: Custom chat widths, swapping sidebars, and portrait mode not working correctly with the new channel page layout. (Closes #799, Affects #794)
* Fixed: Square Avatars not working correctly on the new channel page layout.
* Fixed: Searching settings would not properly search for items in Experiments.
* Fixed: Emotes ending in punctuation (specifically: `.`, `,`, and `!`) were not being displayed correctly.
* Fixed: The order of actions reversing after an inheritance point. (Closes #791)
* Changed: Rename `Chat > Bits and Cheering > Display Top Cheerers` to `Chat > Appearance > Display Leaderboard` to bring it in line with the current state of the feature.
* Removed: Option to hide offline channels from sidebar. This is no longer trivial to implement due to Twitch changes. (Closes #801)
This commit is contained in:
SirStendec 2020-05-27 15:44:37 -04:00
parent b3266a2ef3
commit 261c461481
14 changed files with 255 additions and 25 deletions

View file

@ -1,7 +1,7 @@
{ {
"name": "frankerfacez", "name": "frankerfacez",
"author": "Dan Salvato LLC", "author": "Dan Salvato LLC",
"version": "4.19.11", "version": "4.19.12",
"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

@ -38,6 +38,27 @@ export default class ExperimentManager extends Module {
this.settings.addUI('experiments', { this.settings.addUI('experiments', {
path: 'Debugging > Experiments', path: 'Debugging > Experiments',
component: 'experiments', component: 'experiments',
no_filter: true,
getExtraTerms: () => {
const values = [];
for(const [key,val] of Object.entries(this.experiments)) {
values.push(key);
if ( val.name )
values.push(val.name);
if ( val.description )
values.push(val.description);
}
for(const [key, val] of Object.entries(this.getTwitchExperiments())) {
values.push(key);
if ( val.name )
values.push(val.name);
}
return values;
},
unique_id: () => this.unique_id, unique_id: () => this.unique_id,
@ -103,6 +124,7 @@ export default class ExperimentManager extends Module {
} }
this.log.info(`Loaded information on ${Object.keys(data).length} experiments.${changed > 0 ? ` ${changed} values updated.` : ''}`); this.log.info(`Loaded information on ${Object.keys(data).length} experiments.${changed > 0 ? ` ${changed} values updated.` : ''}`);
//this.emit(':loaded');
} }

View file

@ -24,6 +24,7 @@ import Actions from './actions';
export const SEPARATORS = '[\\s`~<>!-#%-\\x2A,-/:;\\x3F@\\x5B-\\x5D_\\x7B}\\u00A1\\u00A7\\u00AB\\u00B6\\u00B7\\u00BB\\u00BF\\u037E\\u0387\\u055A-\\u055F\\u0589\\u058A\\u05BE\\u05C0\\u05C3\\u05C6\\u05F3\\u05F4\\u0609\\u060A\\u060C\\u060D\\u061B\\u061E\\u061F\\u066A-\\u066D\\u06D4\\u0700-\\u070D\\u07F7-\\u07F9\\u0830-\\u083E\\u085E\\u0964\\u0965\\u0970\\u0AF0\\u0DF4\\u0E4F\\u0E5A\\u0E5B\\u0F04-\\u0F12\\u0F14\\u0F3A-\\u0F3D\\u0F85\\u0FD0-\\u0FD4\\u0FD9\\u0FDA\\u104A-\\u104F\\u10FB\\u1360-\\u1368\\u1400\\u166D\\u166E\\u169B\\u169C\\u16EB-\\u16ED\\u1735\\u1736\\u17D4-\\u17D6\\u17D8-\\u17DA\\u1800-\\u180A\\u1944\\u1945\\u1A1E\\u1A1F\\u1AA0-\\u1AA6\\u1AA8-\\u1AAD\\u1B5A-\\u1B60\\u1BFC-\\u1BFF\\u1C3B-\\u1C3F\\u1C7E\\u1C7F\\u1CC0-\\u1CC7\\u1CD3\\u2010-\\u2027\\u2030-\\u2043\\u2045-\\u2051\\u2053-\\u205E\\u207D\\u207E\\u208D\\u208E\\u2329\\u232A\\u2768-\\u2775\\u27C5\\u27C6\\u27E6-\\u27EF\\u2983-\\u2998\\u29D8-\\u29DB\\u29FC\\u29FD\\u2CF9-\\u2CFC\\u2CFE\\u2CFF\\u2D70\\u2E00-\\u2E2E\\u2E30-\\u2E3B\\u3001-\\u3003\\u3008-\\u3011\\u3014-\\u301F\\u3030\\u303D\\u30A0\\u30FB\\uA4FE\\uA4FF\\uA60D-\\uA60F\\uA673\\uA67E\\uA6F2-\\uA6F7\\uA874-\\uA877\\uA8CE\\uA8CF\\uA8F8-\\uA8FA\\uA92E\\uA92F\\uA95F\\uA9C1-\\uA9CD\\uA9DE\\uA9DF\\uAA5C-\\uAA5F\\uAADE\\uAADF\\uAAF0\\uAAF1\\uABEB\\uFD3E\\uFD3F\\uFE10-\\uFE19\\uFE30-\\uFE52\\uFE54-\\uFE61\\uFE63\\uFE68\\uFE6A\\uFE6B\\uFF01-\\uFF03\\uFF05-\\uFF0A\\uFF0C-\\uFF0F\\uFF1A\\uFF1B\\uFF1F\\uFF20\\uFF3B-\\uFF3D\\uFF3F\\uFF5B\\uFF5D\\uFF5F-\\uFF65]'; export const SEPARATORS = '[\\s`~<>!-#%-\\x2A,-/:;\\x3F@\\x5B-\\x5D_\\x7B}\\u00A1\\u00A7\\u00AB\\u00B6\\u00B7\\u00BB\\u00BF\\u037E\\u0387\\u055A-\\u055F\\u0589\\u058A\\u05BE\\u05C0\\u05C3\\u05C6\\u05F3\\u05F4\\u0609\\u060A\\u060C\\u060D\\u061B\\u061E\\u061F\\u066A-\\u066D\\u06D4\\u0700-\\u070D\\u07F7-\\u07F9\\u0830-\\u083E\\u085E\\u0964\\u0965\\u0970\\u0AF0\\u0DF4\\u0E4F\\u0E5A\\u0E5B\\u0F04-\\u0F12\\u0F14\\u0F3A-\\u0F3D\\u0F85\\u0FD0-\\u0FD4\\u0FD9\\u0FDA\\u104A-\\u104F\\u10FB\\u1360-\\u1368\\u1400\\u166D\\u166E\\u169B\\u169C\\u16EB-\\u16ED\\u1735\\u1736\\u17D4-\\u17D6\\u17D8-\\u17DA\\u1800-\\u180A\\u1944\\u1945\\u1A1E\\u1A1F\\u1AA0-\\u1AA6\\u1AA8-\\u1AAD\\u1B5A-\\u1B60\\u1BFC-\\u1BFF\\u1C3B-\\u1C3F\\u1C7E\\u1C7F\\u1CC0-\\u1CC7\\u1CD3\\u2010-\\u2027\\u2030-\\u2043\\u2045-\\u2051\\u2053-\\u205E\\u207D\\u207E\\u208D\\u208E\\u2329\\u232A\\u2768-\\u2775\\u27C5\\u27C6\\u27E6-\\u27EF\\u2983-\\u2998\\u29D8-\\u29DB\\u29FC\\u29FD\\u2CF9-\\u2CFC\\u2CFE\\u2CFF\\u2D70\\u2E00-\\u2E2E\\u2E30-\\u2E3B\\u3001-\\u3003\\u3008-\\u3011\\u3014-\\u301F\\u3030\\u303D\\u30A0\\u30FB\\uA4FE\\uA4FF\\uA60D-\\uA60F\\uA673\\uA67E\\uA6F2-\\uA6F7\\uA874-\\uA877\\uA8CE\\uA8CF\\uA8F8-\\uA8FA\\uA92E\\uA92F\\uA95F\\uA9C1-\\uA9CD\\uA9DE\\uA9DF\\uAA5C-\\uAA5F\\uAADE\\uAADF\\uAAF0\\uAAF1\\uABEB\\uFD3E\\uFD3F\\uFE10-\\uFE19\\uFE30-\\uFE52\\uFE54-\\uFE61\\uFE63\\uFE68\\uFE6A\\uFE6B\\uFF01-\\uFF03\\uFF05-\\uFF0A\\uFF0C-\\uFF0F\\uFF1A\\uFF1B\\uFF1F\\uFF20\\uFF3B-\\uFF3D\\uFF3F\\uFF5B\\uFF5D\\uFF5F-\\uFF65]';
const EMOTE_CHARS = /[ .+!]/;
export default class Chat extends Module { export default class Chat extends Module {
constructor(...args) { constructor(...args) {
@ -1184,12 +1185,18 @@ export default class Chat extends Module {
if ( Array.isArray(raw_emote) ) if ( Array.isArray(raw_emote) )
return msg.ffz_emotes = msg.emotes; return msg.ffz_emotes = msg.emotes;
const em = emotes[raw_emote.id] = emotes[raw_emote.id] || [], const em = emotes[raw_emote.id] = emotes[raw_emote.id] || [];
idx = chars.indexOf(' ', raw_emote.startIndex); let idx = raw_emote.startIndex + 1;
while(idx < chars.length) {
if ( EMOTE_CHARS.test(chars[idx]) )
break;
idx++;
}
em.push({ em.push({
startIndex: raw_emote.startIndex, startIndex: raw_emote.startIndex,
endIndex: (idx === -1 ? chars.length : idx) - 1 endIndex: idx - 1
}); });
} }

View file

@ -14,6 +14,15 @@
{{ t('setting.actions.visible', 'visible: {list}', {list: visibility}) }} {{ t('setting.actions.visible', 'visible: {list}', {list: visibility}) }}
</div> </div>
</template> </template>
<template v-else-if="copying">
<textarea
ref="json"
v-model="json"
readonly
class="tw-full-width tw-full-height tw-border-radius-medium tw-font-size-6 tw-pd-x-1 tw-pd-y-05 tw-input"
@focus="$event.target.select()"
/>
</template>
<template v-else> <template v-else>
<section> <section>
<h5>{{ t('setting.actions.appearance', 'Appearance') }}</h5> <h5>{{ t('setting.actions.appearance', 'Appearance') }}</h5>
@ -369,7 +378,14 @@
</div> </div>
<div class="tw-mg-l-1 tw-border-l tw-pd-l-1 tw-flex tw-flex-wrap tw-flex-column tw-justify-content-start tw-align-items-start"> <div class="tw-mg-l-1 tw-border-l tw-pd-l-1 tw-flex tw-flex-wrap tw-flex-column tw-justify-content-start tw-align-items-start">
<template v-if="editing"> <template v-if="copying">
<button class="tw-button tw-button--text" @click="copying = false">
<span class="tw-button__text ffz-i-cancel">
{{ t('setting.cancel', 'Cancel') }}
</span>
</button>
</template>
<template v-if="editing && ! copying">
<button class="tw-button tw-button--text" @click="save"> <button class="tw-button tw-button--text" @click="save">
<span class="tw-button__text ffz-i-floppy"> <span class="tw-button__text ffz-i-floppy">
{{ t('setting.save', 'Save') }} {{ t('setting.save', 'Save') }}
@ -380,8 +396,13 @@
{{ t('setting.cancel', 'Cancel') }} {{ t('setting.cancel', 'Cancel') }}
</span> </span>
</button> </button>
<button class="tw-button tw-button--text" @click="prepareCopy">
<span class="tw-button__text ffz-i-docs">
{{ t('setting.copy-json', 'Copy') }}
</span>
</button>
</template> </template>
<template v-else-if="deleting"> <template v-else-if="deleting && ! copying">
<button class="tw-button tw-button--text" @click="$emit('remove', action)"> <button class="tw-button tw-button--text" @click="$emit('remove', action)">
<span class="tw-button__text ffz-i-trash"> <span class="tw-button__text ffz-i-trash">
{{ t('setting.delete', 'Delete') }} {{ t('setting.delete', 'Delete') }}
@ -393,7 +414,7 @@
</span> </span>
</button> </button>
</template> </template>
<template v-else> <template v-else-if="! copying">
<button <button
v-if="canEdit" v-if="canEdit"
class="tw-button tw-button--text" class="tw-button tw-button--text"
@ -425,6 +446,7 @@ export default {
data() { data() {
return { return {
id: id++, id: id++,
copying: false,
deleting: false, deleting: false,
editing: false, editing: false,
edit_data: null edit_data: null
@ -432,6 +454,10 @@ export default {
}, },
computed: { computed: {
json() {
return JSON.stringify(this.display)
},
display() { display() {
if ( this.editing ) if ( this.editing )
return this.edit_data; return this.edit_data;
@ -692,7 +718,15 @@ export default {
this.cancel(); this.cancel();
}, },
prepareCopy() {
this.copying = true;
requestAnimationFrame(() => {
this.$refs.json.focus();
});
},
cancel() { cancel() {
this.copying = false;
this.editing = false; this.editing = false;
this.edit_data = null; this.edit_data = null;
}, },

View file

@ -222,10 +222,38 @@
v-if="add_open" v-if="add_open"
color="background-alt-2" color="background-alt-2"
dir="down-right" dir="down-right"
size="sm" :size="add_pasting ? 'md' : 'sm'"
> >
<simplebar classes="ffz-mh-30"> <simplebar classes="ffz-mh-30">
<div class="tw-pd-y-1"> <div v-if="add_pasting" class="tw-pd-1">
<div class="tw-flex tw-align-items-center">
<input
ref="paste"
:placeholder="t('setting.paste-json.json', '[json]')"
class="tw-flex-grow-1 tw-border-radius-medium tw-font-size-6 tw-pd-x-1 tw-pd-y-05 tw-input"
@keydown.enter="addFromJSON"
>
<button
class="tw-mg-l-05 tw-button"
@click="addFromJSON"
>
<span class="tw-button__text ffz-i-plus">
{{ t('setting.add', 'Add') }}
</span>
</button>
</div>
</div>
<div v-else class="tw-pd-y-1">
<button
class="tw-interactable tw-interactable--hover-enabled tw-interactable--inverted tw-interactive tw-full-width"
@click="add_pasting = true"
>
<div class="tw-flex tw-align-items-center tw-pd-y-05 tw-pd-x-1">
<div class="tw-flex-grow-1 tw-mg-r-1">
{{ t('setting.paste-json', 'Paste JSON') }}
</div>
</div>
</button>
<template v-for="(preset, idx) in presets"> <template v-for="(preset, idx) in presets">
<div <div
v-if="preset.divider" v-if="preset.divider"
@ -348,6 +376,7 @@ export default {
maybe_clear: false, maybe_clear: false,
add_open: false, add_open: false,
add_pasting: false
} }
}, },
@ -548,10 +577,46 @@ export default {
closeAdd() { closeAdd() {
this.add_open = false; this.add_open = false;
this.add_pasting = false;
}, },
toggleAdd() { toggleAdd() {
this.add_open = ! this.add_open; this.add_open = ! this.add_open;
this.add_pasting = false;
},
addFromJSON() {
let value = this.$refs.paste.value;
this.closeAdd();
if ( value ) {
try {
value = JSON.parse(value);
} catch(err) {
alert(err); // eslint-disable-line no-alert
return;
}
if ( ! value.appearance )
value.appearance = {};
if ( ! value.appearance.type )
value.appearance.type = 'text';
if ( value.appearance.type === 'text' && ! value.appearance.text )
value.appearance.text = 'C';
if ( value.appearance.type === 'icon' && ! value.appearance.icon )
value.appearance.icon = 'ffz-i-ok';
if ( ! value.display )
value.display = {};
if ( ! value.action )
value.action = 'chat';
this.add({v: value});
}
}, },
populate() { populate() {

View file

@ -28,7 +28,7 @@
<div class="ffz--experiment-list"> <div class="ffz--experiment-list">
<section <section
v-for="({key, exp}) of sorted(ffz_data)" v-for="({key, exp}) of visible_ffz"
:key="key" :key="key"
:data-key="key" :data-key="key"
> >
@ -72,6 +72,9 @@
<div v-if="! Object.keys(ffz_data).length"> <div v-if="! Object.keys(ffz_data).length">
{{ t('setting.experiments.none', 'There are no current experiments.') }} {{ t('setting.experiments.none', 'There are no current experiments.') }}
</div> </div>
<div v-else-if="! visible_ffz.length">
{{ t('setting.experiments.none-filter', 'There are no matching experiments.') }}
</div>
</div> </div>
<h3 class="tw-mg-t-5 tw-mg-b-1"> <h3 class="tw-mg-t-5 tw-mg-b-1">
@ -80,7 +83,7 @@
<div class="ffz--experiment-list"> <div class="ffz--experiment-list">
<section <section
v-for="({key, exp}) of sorted(twitch_data)" v-for="({key, exp}) of visible_twitch"
:key="key" :key="key"
:data-key="key" :data-key="key"
> >
@ -146,6 +149,9 @@
<div v-if="! Object.keys(twitch_data).length"> <div v-if="! Object.keys(twitch_data).length">
{{ t('setting.experiments.none', 'There are no current experiments.') }} {{ t('setting.experiments.none', 'There are no current experiments.') }}
</div> </div>
<div v-else-if="! visible_twitch.length">
{{ t('setting.experiments.none-filter', 'There are no matching experiments.') }}
</div>
</div> </div>
</div> </div>
</template> </template>
@ -154,8 +160,16 @@
import {has} from 'utilities/object'; import {has} from 'utilities/object';
function matches(exp, filter) {
return (exp.key && exp.key.toLowerCase().includes(filter)) ||
(exp.exp && (
(exp.exp.name && exp.exp.name.toLowerCase().includes(filter)) ||
(exp.exp.description && exp.exp.description.toLowerCase().includes(filter))
));
}
export default { export default {
props: ['item'], props: ['item', 'filter'],
data() { data() {
return { return {
@ -166,6 +180,34 @@ export default {
} }
}, },
computed: {
sorted_ffz() {
return this.sorted(this.ffz_data);
},
visible_ffz() {
const items = this.sorted_ffz,
f = this.filter && this.filter.toLowerCase();
if ( ! f )
return items;
return items.filter(x => matches(x, f));
},
sorted_twitch() {
return this.sorted(this.twitch_data);
},
visible_twitch() {
const items = this.sorted_twitch,
f = this.filter && this.filter.toLowerCase();
if ( ! f )
return items;
return items.filter(x => matches(x, f));
}
},
created() { created() {
for(const key in this.ffz_data) for(const key in this.ffz_data)
if ( has(this.ffz_data, key) ) { if ( has(this.ffz_data, key) ) {

View file

@ -160,6 +160,7 @@ export default class MainMenu extends Module {
await this.site.awaitElement(Dialog.EXCLUSIVE); await this.site.awaitElement(Dialog.EXCLUSIVE);
this.on('addons:added', this.scheduleUpdate, this); this.on('addons:added', this.scheduleUpdate, this);
this.on('experiments:enabled', this.scheduleUpdate, this);
this.on('i18n:update', this.scheduleUpdate, this); this.on('i18n:update', this.scheduleUpdate, this);
this.dialog.on('show', () => { this.dialog.on('show', () => {

View file

@ -54,14 +54,15 @@ export const array_merge = {
get(key, profiles, definition, log) { get(key, profiles, definition, log) {
const values = [], const values = [],
trailing = [],
sources = []; sources = [];
let trailing = [];
let had_value = false; let had_value = false;
for(const profile of profiles) for(const profile of profiles)
if ( profile.has(key) ) { if ( profile.has(key) ) {
const value = profile.get(key); const value = profile.get(key),
trail = [];
if ( ! Array.isArray(value) ) { if ( ! Array.isArray(value) ) {
log.warn(`Profile #${profile.id} has an invalid value for "${key}" of type ${typeof value}. Skipping.`); log.warn(`Profile #${profile.id} has an invalid value for "${key}" of type ${typeof value}. Skipping.`);
continue; continue;
@ -74,11 +75,13 @@ export const array_merge = {
if ( val.t === 'inherit' ) if ( val.t === 'inherit' )
is_trailing = true; is_trailing = true;
else if ( is_trailing ) else if ( is_trailing )
trailing.unshift(val.v); trail.push(val.v);
else else
values.push(val.v); values.push(val.v);
} }
trailing = trail.concat(trailing);
// If we didn't run into an inherit, don't inherit. // If we didn't run into an inherit, don't inherit.
if ( ! is_trailing && ! definition.always_inherit ) if ( ! is_trailing && ! definition.always_inherit )
break; break;

View file

@ -375,9 +375,9 @@ export default class ChatHook extends Module {
}, },
ui: { ui: {
path: 'Chat > Bits and Cheering >> Appearance', path: 'Chat > Appearance >> Community',
title: 'Display Top Cheerers', title: 'Display Leaderboard',
description: 'By default, this inherits its value from Display Bits.', description: 'The leaderboard shows the top cheerers and sub gifters in a channel.\n\nBy default due to a previous implementation, this inherits its value from Chat > Bits and Cheering > Display Bits.',
component: 'setting-check-box' component: 'setting-check-box'
} }
}); });
@ -550,6 +550,7 @@ export default class ChatHook extends Module {
this.css_tweaks.setVariable('chat-line-height', `${lh/10}rem`); this.css_tweaks.setVariable('chat-line-height', `${lh/10}rem`);
this.css_tweaks.setVariable('chat-font-family', font); this.css_tweaks.setVariable('chat-font-family', font);
this.css_tweaks.setVariable('chat-width', `${width/10}rem`); this.css_tweaks.setVariable('chat-width', `${width/10}rem`);
this.css_tweaks.setVariable('negative-chat-width', `${-width/10}rem`);
this.css_tweaks.toggle('chat-font', size !== 12 || font); this.css_tweaks.toggle('chat-font', size !== 12 || font);
this.css_tweaks.toggle('chat-width', this.settings.get('chat.use-width')); this.css_tweaks.toggle('chat-width', this.settings.get('chat.use-width'));
@ -558,6 +559,7 @@ export default class ChatHook extends Module {
this.css_tweaks.toggle('emote-alignment-baseline', emote_alignment === 2); this.css_tweaks.toggle('emote-alignment-baseline', emote_alignment === 2);
this.emit(':update-chat-css'); this.emit(':update-chat-css');
this.emit('site.player:fix-player');
} }
updateLineBorders() { updateLineBorders() {

View file

@ -18,7 +18,7 @@ const CLASSES = {
'side-friends': '.side-nav .online-friends', 'side-friends': '.side-nav .online-friends',
'side-closed-friends': '.side-nav--collapsed .online-friends', 'side-closed-friends': '.side-nav--collapsed .online-friends',
'side-closed-rec-channels': '.side-nav--collapsed .recommended-channels', 'side-closed-rec-channels': '.side-nav--collapsed .recommended-channels',
'side-offline-channels': '.side-nav-card__link[href*="/videos/"],.side-nav-card[href*="/videos/"]', //'side-offline-channels': '.side-nav-card__link[href*="/videos/"],.side-nav-card[href*="/videos/"]',
'side-rerun-channels': '.side-nav .ffz--side-nav-card-rerun', 'side-rerun-channels': '.side-nav .ffz--side-nav-card-rerun',
'community-highlights': '.community-highlight-stack__card', 'community-highlights': '.community-highlight-stack__card',
@ -59,6 +59,17 @@ export default class CSSTweaks extends Module {
// Layout // Layout
this.settings.add('layout.use-chat-fix', {
requires: ['layout.swap-sidebars', 'layout.use-portrait', 'chat.use-width'],
process(ctx) {
return ctx.get('layout.swap-sidebars') || ctx.get('layout.use-portrait') || ctx.get('chat.use-width')
},
changed: val => {
this.toggle('chat-fix', val);
this.emit('site.player:fix-player');
}
});
this.settings.add('layout.side-nav.show', { this.settings.add('layout.side-nav.show', {
default: true, default: true,
ui: { ui: {
@ -127,7 +138,7 @@ export default class CSSTweaks extends Module {
changed: val => this.toggleHide('side-rec-friends', !val) changed: val => this.toggleHide('side-rec-friends', !val)
}); });
this.settings.add('layout.side-nav.hide-offline', { /*this.settings.add('layout.side-nav.hide-offline', {
default: false, default: false,
ui: { ui: {
path: 'Appearance > Layout >> Side Navigation', path: 'Appearance > Layout >> Side Navigation',
@ -135,7 +146,7 @@ export default class CSSTweaks extends Module {
component: 'setting-check-box' component: 'setting-check-box'
}, },
changed: val => this.toggleHide('side-offline-channels', val) changed: val => this.toggleHide('side-offline-channels', val)
}); });*/
this.settings.add('layout.side-nav.rerun-style', { this.settings.add('layout.side-nav.rerun-style', {
default: 1, default: 1,
@ -307,6 +318,7 @@ export default class CSSTweaks extends Module {
} }
onEnable() { onEnable() {
this.toggle('chat-fix', this.settings.get('layout.use-chat-fix'));
this.toggle('swap-sidebars', this.settings.get('layout.swap-sidebars')); this.toggle('swap-sidebars', this.settings.get('layout.swap-sidebars'));
this.toggle('minimal-navigation', this.settings.get('layout.minimal-navigation')); this.toggle('minimal-navigation', this.settings.get('layout.minimal-navigation'));
this.toggle('theatre-nav', this.settings.get('layout.theatre-navigation')); this.toggle('theatre-nav', this.settings.get('layout.theatre-navigation'));
@ -314,7 +326,7 @@ export default class CSSTweaks extends Module {
this.toggle('hide-side-nav-avatars', ! this.settings.get('layout.side-nav.show-avatars')); this.toggle('hide-side-nav-avatars', ! this.settings.get('layout.side-nav.show-avatars'));
this.toggle('hide-side-nav', !this.settings.get('layout.side-nav.show')); this.toggle('hide-side-nav', !this.settings.get('layout.side-nav.show'));
this.toggleHide('side-rec-friends', !this.settings.get('layout.side-nav.show-rec-friends')); this.toggleHide('side-rec-friends', !this.settings.get('layout.side-nav.show-rec-friends'));
this.toggleHide('side-offline-channels', this.settings.get('layout.side-nav.hide-offline')); //this.toggleHide('side-offline-channels', this.settings.get('layout.side-nav.hide-offline'));
this.toggleHide('prime-offers', !this.settings.get('layout.prime-offers')); this.toggleHide('prime-offers', !this.settings.get('layout.prime-offers'));
this.toggleHide('top-discover', !this.settings.get('layout.discover')); this.toggleHide('top-discover', !this.settings.get('layout.discover'));
@ -339,6 +351,8 @@ export default class CSSTweaks extends Module {
this.updateFont(); this.updateFont();
this.updateTopNav(); this.updateTopNav();
this.emit('site.player:fix-player');
} }
updateTopNav() { updateTopNav() {

View file

@ -0,0 +1,25 @@
body .video-watch-page__right-column,
body .clips-watch-page__right-column,
body .channel-page__right-column,
body .right-column:not(.right-column--collapsed),
body .channel-videos__right-column,
body .channel-clips__sidebar,
body .channel-events__sidebar,
body .channel-follow-listing__right-column,
body .channel-follow-listing__right-column,
body .channel-root__right-column {
width: 34rem;
}
.channel-root__right-column--expanded {
position: initial;
transform: none !important;
}
.toggle-visibility__right-column--expanded {
transform: none !important;
}
.channel-root--hold-chat+.persistent-player, .channel-root--watch-chat+.persistent-player, .channel-root__info--with-chat .channel-info-content, .channel-root__player--with-chat {
width: 100% !important;
}

View file

@ -50,6 +50,10 @@
right: 0 !important; right: 0 !important;
} }
.channel-root__right-column--expanded {
min-height: unset !important;
}
.right-column { .right-column {
display: unset !important; display: unset !important;
position: fixed !important; position: fixed !important;

View file

@ -1,3 +1,4 @@
.user-avatar-animated,
.search-result-card, .search-result-card,
.tw-avatar { .tw-avatar {
--border-radius-rounded: 0 !important; --border-radius-rounded: 0 !important;
@ -10,3 +11,7 @@
.bits-leaderboard-medal .tw-avatar { .bits-leaderboard-medal .tw-avatar {
--border-radius-rounded: 9000px !important; --border-radius-rounded: 9000px !important;
} }
.user-avatar-animated .user-avatar-animated__halo {
visibility: hidden;
}

View file

@ -59,6 +59,11 @@ export default class Player extends Module {
PLAYER_ROUTES PLAYER_ROUTES
); );
this.PersistentPlayer = this.fine.define(
'persistent-player',
n => n.state && n.state.playerStyles
);
this.Player = this.fine.define( this.Player = this.fine.define(
'highwind-player', 'highwind-player',
n => n.setPlayerActive && n.props?.playerEvents && n.props?.mediaPlayerInstance, n => n.setPlayerActive && n.props?.playerEvents && n.props?.mediaPlayerInstance,
@ -522,10 +527,10 @@ export default class Player extends Module {
this.installVisibilityHook(); this.installVisibilityHook();
this.on(':reset', this.resetAllPlayers, this); this.on(':reset', this.resetAllPlayers, this);
this.on(':fix-player', () => this.PersistentPlayer.forceUpdate(), this);
const t = this; const t = this;
this.SquadStreamBar.ready(cls => { this.SquadStreamBar.ready(cls => {
const old_should_render = cls.prototype.shouldRenderSquadBanner; const old_should_render = cls.prototype.shouldRenderSquadBanner;
@ -1097,7 +1102,8 @@ export default class Player extends Module {
const url = new URL(video.src); const url = new URL(video.src);
if ( url.protocol !== 'blob:' ) if ( url.protocol !== 'blob:' )
return false; return false;
} } else
return false;
/*this.PlayerSource.check(); /*this.PlayerSource.check();
for(const si of this.PlayerSource.instances) { for(const si of this.PlayerSource.instances) {