1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-06-27 12:55:55 +00:00
* Fixed: The video player appearing as the incorrect size when a custom chat width is set, portrait mode is enabled, or swap sidebars is enabled.
* Fixed: Channel page tweaks being removed when Twitch refreshes the channel page for whatever reason they're doing that.
* API Fixed: Elemental not correctly detecting new elements in some situations.
This commit is contained in:
SirStendec 2025-05-21 13:02:09 -04:00
parent 872b0ff731
commit b250075813
6 changed files with 53 additions and 11 deletions

View file

@ -1,7 +1,7 @@
{
"name": "frankerfacez",
"author": "Dan Salvato LLC",
"version": "4.77.3",
"version": "4.77.4",
"description": "FrankerFaceZ is a Twitch enhancement suite.",
"private": true,
"license": "Apache-2.0",

View file

@ -0,0 +1,6 @@
.channel-root__info--with-chat .channel-info-content,
.channel-root__player--with-chat,
.persistent-player:has(+.channel-root--hold-chat),
.persistent-player:has(+.channel-root--watch-chat) {
width: 100% !important;
}

View file

@ -138,6 +138,13 @@ export default class Layout extends Module {
//changed: val => this.css_tweaks.toggle('portrait', val)
});
this.settings.add('layout.fix-player-size', {
requires: ['layout.inject-portrait', 'chat.use-width', 'layout.swap-sidebars'],
process(ctx) {
return ctx.get('layout.inject-portrait') || ctx.get('chat.use-width') || ctx.get('layout.swap-sidebars');
}
});
this.settings.add('layout.use-portrait-swapped', {
requires: ['layout.inject-portrait', 'layout.swap-sidebars'],
process(ctx) {
@ -245,6 +252,7 @@ export default class Layout extends Module {
this.settings.getChanges('layout.portrait-extra-width', val => this.css_tweaks.setVariable('portrait-extra-width', `${val}rem`));
this.settings.getChanges('layout.portrait-extra-height', val => this.css_tweaks.setVariable('portrait-extra-height', `${val}rem`));
this.settings.getChanges('layout.fix-player-size', val => this.css_tweaks.toggle('player-size', val));
/*this.css_tweaks.toggle('portrait-chat', this.settings.get('layout.portrait-min-chat'));
this.css_tweaks.toggle('portrait', this.settings.get('layout.inject-portrait'));

View file

@ -102,6 +102,7 @@ export default class Loadable extends Module {
proto = cls.prototype as ErrorBoundaryNode,
old_render = proto.render;
(proto as any)._ffz_wrapped_render = old_render;
proto.render = function() {
try {
const type = this.props.name;
@ -181,14 +182,16 @@ export default class Loadable extends Module {
update(cmp: string) {
for(const inst of this.LoadableComponent.instances) {
const type = inst.props?.component;
if ( type && type === cmp )
if ( type && type === cmp ) {
inst.forceUpdate();
}
}
for(const inst of this.ErrorBoundaryComponent.instances) {
const name = inst.props?.name;
if ( name && name === cmp )
if ( name && name === cmp ) {
inst.forceUpdate();
}
}
}

View file

@ -24,6 +24,7 @@ export default class Elemental extends Module<'site.elemental'> {
private _timer?: number | null;
private _timeout?: ReturnType<typeof setTimeout> | null;
private _clean_timeout?: ReturnType<typeof setTimeout> | null;
private _clean_all?: ReturnType<typeof requestAnimationFrame> | null;
constructor(name?: string, parent?: GenericModule) {
@ -36,6 +37,8 @@ export default class Elemental extends Module<'site.elemental'> {
this._observer = null;
this._watching = new Set;
this._live_watching = null;
this.scheduleCleaning();
}
/** @internal */
@ -74,6 +77,16 @@ export default class Elemental extends Module<'site.elemental'> {
this.cleanAll();
}
scheduleCleaning() {
if ( this._clean_timeout )
clearTimeout(this._clean_timeout);
this._clean_timeout = setTimeout(() => {
this._clean_timeout = null;
this.cleanAll();
this.scheduleCleaning();
}, 1000);
}
cleanAll() {
if ( this._clean_all )
@ -182,7 +195,7 @@ export default class Elemental extends Module<'site.elemental'> {
listen(inst: ElementalWrapper<any>, ensure_live = true) {
if ( this._watching.has(inst) )
if ( this._watching.has(inst) || ! ensure_live )
return;
if ( ensure_live )
@ -284,9 +297,18 @@ export class ElementalWrapper<
clean() {
const instances = Array.from(this.instances);
let removed = false;
for(const el of instances) {
if ( ! document.contains(el) )
this.remove(el);
if ( ! document.contains(el) ) {
this.remove(el, false);
removed = true;
}
}
if ( removed ) {
if ( this.limit === 0 || this.count < this.limit )
this.check();
this.schedule();
}
}
@ -378,7 +400,7 @@ export class ElementalWrapper<
this.emit('mount', element);
}
remove(element: TElement) {
remove(element: TElement, do_schedule = true) {
const observer = element[this.param];
if ( observer ) {
observer.disconnect();
@ -397,7 +419,8 @@ export class ElementalWrapper<
this.instances.delete(element);
this.count--;
this.schedule();
if ( do_schedule )
this.schedule();
this.emit('unmount', element);
}
}

View file

@ -955,9 +955,11 @@ export function pick_random(obj: any) {
/**
* Escape a string for inclusion in a regular expression.
*/
export const escape_regex = ((RegExp as any).escape as (input: string) => string) || function escape_regex(str: string) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
export const escape_regex: (str: string) => string = /*(RegExp as any).escape
? (str: string) => ((RegExp as any).escape(` ${str}`) as string).slice(1)
:*/ function escape_regex(str: string) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
};
export function addWordSeparators(str: string) {