mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-06-27 21:05:53 +00:00
4.15.5
* Added: Changelog for Add-Ons. * Added: Option to disable the player running at a faster rate to reduce the buffer size. * Changed: Stream Latency metadata now shows you when the player is running at a faster rate. * Fixed: Formatting of tool-tips for metadata. * Fixed: Metadata tool-tips not supporting rich children when updating. * Fixed: Metadata icons not updating when changed dynamically. * Fixed: The current channel's accent color not being detected in pop-out chat. * Fixed: Styles not being applied correctly to deleted messages that are part of a channel points reward or part of a re-subscription notice. * Removed: Support for Rooms messages. * API Added: Settings now have an `onUIChanged` method that is called when a setting is changed by a UI control, allowing for immediate feedback. * API Added: Built-in settings components now accept a `buttons` component that is rendered before the reset and profile override buttons.
This commit is contained in:
parent
8ac1b2ce91
commit
347919c51a
28 changed files with 335 additions and 83 deletions
|
@ -139,7 +139,7 @@ module.exports = {
|
|||
"react/jsx-first-prop-new-line": ["error", "multiline-multiprop"],
|
||||
"react/jsx-indent": ["warn", "tab"],
|
||||
"react/jsx-indent-props": ["warn", "tab"],
|
||||
"react/jsx-key": "warn",
|
||||
//"react/jsx-key": "warn",
|
||||
"react/jsx-no-bind": "error",
|
||||
"react/jsx-no-comment-textnodes": "error",
|
||||
"react/jsx-no-duplicate-props": "error",
|
||||
|
|
|
@ -669,6 +669,12 @@
|
|||
"search": [
|
||||
"channel-points"
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "4e511190b60f329d08301eb6869c5130",
|
||||
"css": "fast-fw",
|
||||
"code": 59453,
|
||||
"src": "fontawesome"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "frankerfacez",
|
||||
"author": "Dan Salvato LLC",
|
||||
"version": "4.15.4",
|
||||
"version": "4.15.5",
|
||||
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
|
|
Binary file not shown.
|
@ -128,6 +128,8 @@
|
|||
|
||||
<glyph glyph-name="channel-points" unicode="" d="M500 550a200 200 0 0 0 200-200h-100a100 100 0 0 1-100 100z m12 200a400 400 0 0 1-412-400 400 400 0 0 1 800 0 400 400 0 0 1-388 400z m-3-100a300 300 0 0 0 291-300 300 300 0 0 0-600 0 300 300 0 0 0 309 300z" horiz-adv-x="1000" />
|
||||
|
||||
<glyph glyph-name="fast-fw" unicode="" d="M25-71q-10-11-18-8t-7 18v822q0 14 7 18t18-8l396-396q5-5 8-10v396q0 14 7 18t18-8l396-396q11-10 11-25t-11-25l-396-396q-11-11-18-8t-7 18v397q-3-6-8-11z" horiz-adv-x="928.6" />
|
||||
|
||||
<glyph glyph-name="link-ext" unicode="" d="M786 332v-178q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h393q7 0 12-5t5-13v-36q0-8-5-13t-12-5h-393q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v178q0 8 5 13t13 5h36q8 0 13-5t5-13z m214 482v-285q0-15-11-25t-25-11-25 11l-98 98-364-364q-5-6-13-6t-12 6l-64 64q-6 5-6 12t6 13l364 364-98 98q-11 11-11 25t11 25 25 11h285q15 0 25-11t11-25z" horiz-adv-x="1000" />
|
||||
|
||||
<glyph glyph-name="twitter" unicode="" d="M904 622q-37-54-90-93 0-8 0-23 0-73-21-145t-64-139-103-117-144-82-181-30q-151 0-276 81 19-2 43-2 126 0 224 77-59 1-105 36t-64 89q19-3 34-3 24 0 48 6-63 13-104 62t-41 115v2q38-21 82-23-37 25-59 64t-22 86q0 49 25 91 68-83 164-133t208-55q-5 21-5 41 0 75 53 127t127 53q79 0 132-57 61 12 115 44-21-64-80-100 52 6 104 28z" horiz-adv-x="928.6" />
|
||||
|
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 37 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,10 +1,15 @@
|
|||
<template lang="html">
|
||||
<div class="ffz--changelog tw-border-t tw-pd-t-1">
|
||||
<div class="tw-align-center">
|
||||
<h2>{{ t('home.changelog', 'Changelog') }}</h2>
|
||||
<h2 v-if="addons">
|
||||
{{ t('setting.add_ons.changelog.title', 'Add-Ons Changelog') }}
|
||||
</h2>
|
||||
<h2 v-else>
|
||||
{{ t('home.changelog', 'Changelog') }}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="tw-mg-b-1 tw-flex tw-align-items-center">
|
||||
<div v-if=" ! addons" class="tw-mg-b-1 tw-flex tw-align-items-center">
|
||||
<div class="tw-flex-grow-1" />
|
||||
<div class="tw-checkbox tw-relative tw-tooltip-wrapper">
|
||||
<input
|
||||
|
@ -28,12 +33,43 @@
|
|||
<ul>
|
||||
<li v-for="commit of display" :key="commit.sha" class="tw-mg-b-2">
|
||||
<div class="tw-flex tw-align-items-center tw-border-b tw-mg-b-05">
|
||||
<div v-if="commit.active" class="tw-pill tw-mg-r-05">
|
||||
<div v-if="! addons && commit.active" class="tw-pill tw-mg-r-05">
|
||||
{{ t('home.changelog.current', 'Current Version') }}
|
||||
</div>
|
||||
<div class="tw-font-size-4">
|
||||
<div v-if="commit.title" class="tw-font-size-4">
|
||||
{{ commit.title }}
|
||||
</div>
|
||||
<div v-if="commit.author">
|
||||
<t-list
|
||||
phrase="home.changelog.by-line"
|
||||
default="By: {user}"
|
||||
class="tw-inline-flex tw-align-items-center"
|
||||
>
|
||||
<template #user>
|
||||
<a
|
||||
v-if="commit.author.html_url"
|
||||
:href="commit.author.html_url"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="tw-inline-flex tw-align-items-center tw-link tw-link--inherit tw-mg-x-05"
|
||||
>
|
||||
<figure
|
||||
v-if="commit.author.avatar_url"
|
||||
class="tw-avatar tw-avatar--size-20 tw-mg-r-05"
|
||||
>
|
||||
<img
|
||||
:src="commit.author.avatar_url"
|
||||
class="tw-block tw-border-radius-rounded tw-image tw-image-avatar"
|
||||
>
|
||||
</figure>
|
||||
{{ commit.author.login }}
|
||||
</a>
|
||||
<strong v-else class="tw-mg-x-05">
|
||||
{{ commit.author.login || commit.author.name }}
|
||||
</strong>
|
||||
</template>
|
||||
</t-list>
|
||||
</div>
|
||||
<div
|
||||
v-if="commit.hash"
|
||||
class="tw-font-size-8 tw-c-text-alt-2"
|
||||
|
@ -81,6 +117,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
error: false,
|
||||
addons: this.item.addons,
|
||||
nonversioned: false,
|
||||
loading: false,
|
||||
more: true,
|
||||
|
@ -95,21 +132,29 @@ export default {
|
|||
|
||||
for(const commit of this.commits) {
|
||||
let message = commit.commit.message,
|
||||
author = null,
|
||||
title = old_commit;
|
||||
|
||||
const match = TITLE_MATCH.exec(message);
|
||||
if ( this.addons ) {
|
||||
title = null;
|
||||
author = commit.author;
|
||||
|
||||
if ( match ) {
|
||||
title = match[1];
|
||||
message = message.slice(match[0].length);
|
||||
} else if ( ! this.nonversioned )
|
||||
continue;
|
||||
} else {
|
||||
const match = TITLE_MATCH.exec(message);
|
||||
|
||||
if ( match ) {
|
||||
title = match[1];
|
||||
message = message.slice(match[0].length);
|
||||
} else if ( ! this.nonversioned )
|
||||
continue;
|
||||
}
|
||||
|
||||
const date = new Date(commit.commit.author.date),
|
||||
active = commit.sha === window.FrankerFaceZ.version_info.commit;
|
||||
|
||||
out.push({
|
||||
title,
|
||||
author,
|
||||
message,
|
||||
active,
|
||||
hash: commit.sha && commit.sha.slice(0,7),
|
||||
|
@ -150,7 +195,7 @@ export default {
|
|||
this.loading = true;
|
||||
|
||||
try {
|
||||
const resp = await fetch(`https://api.github.com/repos/frankerfacez/frankerfacez/commits${until ? `?until=${until}` : ''}`),
|
||||
const resp = await fetch(`https://api.github.com/repos/frankerfacez/${this.addons ? 'add-ons' : 'frankerfacez'}/commits${until ? `?until=${until}` : ''}`),
|
||||
data = resp.ok ? await resp.json() : null;
|
||||
|
||||
if ( ! data || ! Array.isArray(data) ) {
|
||||
|
@ -158,14 +203,20 @@ export default {
|
|||
return;
|
||||
}
|
||||
|
||||
let added = false;
|
||||
|
||||
for(const commit of data) {
|
||||
if ( this.commit_ids.has(commit.sha) )
|
||||
continue;
|
||||
|
||||
this.commit_ids.add(commit.sha)
|
||||
this.commits.push(commit);
|
||||
added = true;
|
||||
}
|
||||
|
||||
if ( ! added )
|
||||
this.more = false;
|
||||
|
||||
this.loading = false;
|
||||
|
||||
} catch(err) {
|
||||
|
|
|
@ -18,6 +18,14 @@
|
|||
<span v-if="unseen" class="tw-pill">{{ t('setting.new', 'New') }}</span>
|
||||
</label>
|
||||
|
||||
<component
|
||||
:is="item.buttons"
|
||||
v-if="item.buttons"
|
||||
:context="context"
|
||||
:item="item"
|
||||
:value="value"
|
||||
/>
|
||||
|
||||
<button
|
||||
v-if="source && source !== profile"
|
||||
class="tw-mg-l-05 tw-button tw-button--text"
|
||||
|
|
|
@ -18,6 +18,14 @@
|
|||
@input="onInput"
|
||||
/>
|
||||
|
||||
<component
|
||||
:is="item.buttons"
|
||||
v-if="item.buttons"
|
||||
:context="context"
|
||||
:item="item"
|
||||
:value="value"
|
||||
/>
|
||||
|
||||
<button
|
||||
v-if="source && source !== profile"
|
||||
class="tw-mg-l-05 tw-button tw-button--text"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<select
|
||||
:id="item.full_key"
|
||||
ref="control"
|
||||
class="tw-border-radius-medium tw-font-size-6 tw-select tw-pd-l-1 tw-pd-r-3 tw-pd-y-05"
|
||||
class="tw-border-top-left-radius-medium tw-border-top-right-radius-medium tw-font-size-6 tw-select tw-pd-l-1 tw-pd-r-3 tw-pd-y-05"
|
||||
@change="onChange"
|
||||
>
|
||||
<option
|
||||
|
@ -31,11 +31,19 @@
|
|||
ref="text"
|
||||
:value="value"
|
||||
:disabled="! isCustom"
|
||||
class="tw-border-radius-medium tw-font-size-6 tw-pd-x-1 tw-pd-y-05 tw-input"
|
||||
class="ffz-mg-t-1p tw-border-bottom-left-radius-medium tw-border-bottom-right-radius-medium tw-font-size-6 tw-pd-x-1 tw-pd-y-05 tw-input"
|
||||
@change="onTextChange"
|
||||
>
|
||||
</div>
|
||||
|
||||
<component
|
||||
:is="item.buttons"
|
||||
v-if="item.buttons"
|
||||
:context="context"
|
||||
:item="item"
|
||||
:value="value"
|
||||
/>
|
||||
|
||||
<button
|
||||
v-if="source && source !== profile"
|
||||
class="tw-mg-l-05 tw-mg-y-05 tw-button tw-button--text"
|
||||
|
|
|
@ -24,6 +24,14 @@
|
|||
</option>
|
||||
</select>
|
||||
|
||||
<component
|
||||
:is="item.buttons"
|
||||
v-if="item.buttons"
|
||||
:context="context"
|
||||
:item="item"
|
||||
:value="value"
|
||||
/>
|
||||
|
||||
<button
|
||||
v-if="source && source !== profile"
|
||||
class="tw-mg-l-05 tw-button tw-button--text"
|
||||
|
|
|
@ -17,6 +17,14 @@
|
|||
@change="onChange"
|
||||
>
|
||||
|
||||
<component
|
||||
:is="item.buttons"
|
||||
v-if="item.buttons"
|
||||
:context="context"
|
||||
:item="item"
|
||||
:value="value"
|
||||
/>
|
||||
|
||||
<button
|
||||
v-if="source && source !== profile"
|
||||
class="tw-mg-l-05 tw-button tw-button--text"
|
||||
|
|
|
@ -87,6 +87,13 @@ export default class MainMenu extends Module {
|
|||
component: 'changelog'
|
||||
});
|
||||
|
||||
this.settings.addUI('addon-changelog', {
|
||||
path: 'Add-Ons > Changelog @{"sort": -1000, "profile_warning": false}',
|
||||
component: 'changelog',
|
||||
force_seen: true,
|
||||
addons: true
|
||||
});
|
||||
|
||||
this.settings.addUI('legal', {
|
||||
path: 'Home > Legal @{"sort": 1000}',
|
||||
component: 'legal-page',
|
||||
|
|
|
@ -184,10 +184,16 @@ export default {
|
|||
value = this.item.process(value);
|
||||
|
||||
this.profile.set(this.item.setting, value);
|
||||
|
||||
if ( this.item.onUIChange )
|
||||
this.item.onUIChange(value);
|
||||
},
|
||||
|
||||
clear() {
|
||||
this.profile.delete(this.item.setting);
|
||||
|
||||
if ( this.item.onUIChange )
|
||||
this.item.onUIChange(this.value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
'use strict';
|
||||
'use strict';
|
||||
|
||||
// ============================================================================
|
||||
// Channel Metadata
|
||||
|
@ -114,14 +114,19 @@ export default class Metadata extends Module {
|
|||
if ( ! data.created )
|
||||
return null;
|
||||
|
||||
return `${this.i18n.t(
|
||||
'metadata.uptime.tooltip',
|
||||
'Stream Uptime'
|
||||
)}<div class="pd-t-05">${this.i18n.t(
|
||||
'metadata.uptime.since',
|
||||
'(since {since,datetime})',
|
||||
{since: data.created}
|
||||
)}</div>`;
|
||||
return [
|
||||
this.i18n.t(
|
||||
'metadata.uptime.tooltip',
|
||||
'Stream Uptime'
|
||||
),
|
||||
<div class="tw-pd-t-05">
|
||||
{this.i18n.t(
|
||||
'metadata.uptime.since',
|
||||
'(since {since,datetime})',
|
||||
{since: data.created}
|
||||
)}
|
||||
</div>
|
||||
];
|
||||
},
|
||||
|
||||
async popup(data, tip) {
|
||||
|
@ -210,6 +215,7 @@ export default class Metadata extends Module {
|
|||
hlsLatencyBroadcaster: temp.hls_latency_broadcaster / 1000,
|
||||
hlsLatencyEncoder: temp.hls_latency_encoder / 1000,
|
||||
memoryUsage: `${temp.totalMemoryNumber} MB`,
|
||||
rate: maybe_call(player.getPlaybackRate, player) || 1,
|
||||
playbackRate: temp.current_bitrate,
|
||||
skippedFrames: temp.dropped_frames,
|
||||
videoResolution: `${temp.vid_width}x${temp.vid_height}`
|
||||
|
@ -229,6 +235,7 @@ export default class Metadata extends Module {
|
|||
videoWidth,
|
||||
displayHeight,
|
||||
displayWidth,
|
||||
rate: maybe_call(player.getPlaybackRate, player),
|
||||
fps: Math.floor(maybe_call(player.getVideoFrameRate, player) || 0),
|
||||
hlsLatencyBroadcaster: player.stats?.broadcasterLatency,
|
||||
hlsLatencyEncoder: player.stats?.transcoderLatency,
|
||||
|
@ -248,13 +255,20 @@ export default class Metadata extends Module {
|
|||
return {
|
||||
stats,
|
||||
drift,
|
||||
rate: stats.rate == null ? 1 : stats.rate,
|
||||
delay: stats.hlsLatencyBroadcaster,
|
||||
old: stats.hlsLatencyBroadcaster > 180
|
||||
}
|
||||
},
|
||||
|
||||
order: 3,
|
||||
icon: 'ffz-i-gauge',
|
||||
|
||||
icon(data) {
|
||||
if ( data.rate > 1 )
|
||||
return 'ffz-i-fast-fw';
|
||||
|
||||
return 'ffz-i-gauge'
|
||||
},
|
||||
|
||||
subtitle: () => this.i18n.t('metadata.player-stats.subtitle', 'Latency'),
|
||||
|
||||
|
@ -293,16 +307,28 @@ export default class Metadata extends Module {
|
|||
},
|
||||
|
||||
tooltip(data) {
|
||||
const delayed = data.drift > 5000 ?
|
||||
`${this.i18n.t(
|
||||
const delayed = data.drift > 5000 && (<div class="tw-border-b tw-mg-b-05 tw-pd-b-05">
|
||||
{this.i18n.t(
|
||||
'metadata.player-stats.delay-warning',
|
||||
'Your local clock seems to be off by roughly {count,number} seconds, which could make this inaccurate.',
|
||||
Math.round(data.drift / 10) / 100
|
||||
)}<hr>` :
|
||||
'';
|
||||
)}
|
||||
</div>);
|
||||
|
||||
const ff = data.rate > 1 && (<div class="tw-border-b tw-mg-b-05 tw-pd-b-05">
|
||||
{this.i18n.t(
|
||||
'metadata.player-stats.rate-warning',
|
||||
'Playing at {rate,number}x speed to reduce delay.',
|
||||
{rate: data.rate.toFixed(2)}
|
||||
)}
|
||||
</div>);
|
||||
|
||||
if ( ! data.stats || ! data.delay )
|
||||
return delayed + this.i18n.t('metadata.player-stats.latency-tip', 'Stream Latency');
|
||||
return [
|
||||
delayed,
|
||||
ff,
|
||||
this.i18n.t('metadata.player-stats.latency-tip', 'Stream Latency')
|
||||
];
|
||||
|
||||
const stats = data.stats,
|
||||
video_info = this.i18n.t(
|
||||
|
@ -312,19 +338,34 @@ export default class Metadata extends Module {
|
|||
);
|
||||
|
||||
if ( data.old )
|
||||
return `${delayed}${this.i18n.t(
|
||||
'metadata.player-stats.video-tip',
|
||||
'Video Information'
|
||||
)}<div class="pd-t-05">${this.i18n.t(
|
||||
'metadata.player-stats.broadcast-ago',
|
||||
'Broadcast {count,number}s Ago',
|
||||
data.delay
|
||||
)}</div><div class="pd-t-05">${video_info}</div>`;
|
||||
return [
|
||||
delayed,
|
||||
this.i18n.t(
|
||||
'metadata.player-stats.video-tip',
|
||||
'Video Information'
|
||||
),
|
||||
<div class="tw-pd-t-05">
|
||||
{this.i18n.t(
|
||||
'metadata.player-stats.broadcast-ago',
|
||||
'Broadcast {count,number}s Ago',
|
||||
data.delay
|
||||
)}
|
||||
</div>,
|
||||
<div class="tw-pd-t-05">
|
||||
{video_info}
|
||||
</div>
|
||||
];
|
||||
|
||||
return `${delayed}${this.i18n.t(
|
||||
'metadata.player-stats.latency-tip',
|
||||
'Stream Latency'
|
||||
)}<div class="pd-t-05">${video_info}</div>`;
|
||||
return [
|
||||
delayed, ff,
|
||||
this.i18n.t(
|
||||
'metadata.player-stats.latency-tip',
|
||||
'Stream Latency'
|
||||
),
|
||||
<div class="tw-pd-t-05">
|
||||
{video_info}
|
||||
</div>
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -396,7 +437,7 @@ export default class Metadata extends Module {
|
|||
// Grab the element again in case it changed, somehow.
|
||||
el = container.querySelector(`.ffz-stat[data-key="${key}"]`);
|
||||
|
||||
let stat, old_color;
|
||||
let stat, old_color, old_icon;
|
||||
|
||||
const label = maybe_call(def.label, this, data);
|
||||
|
||||
|
@ -408,7 +449,7 @@ export default class Metadata extends Module {
|
|||
color = maybe_call(def.color, this, data) || '';
|
||||
|
||||
if ( ! el ) {
|
||||
let icon = maybe_call(def.icon, this, data);
|
||||
let icon = old_icon = maybe_call(def.icon, this, data);
|
||||
let button = false;
|
||||
|
||||
if ( def.button !== false && (def.popup || def.click) ) {
|
||||
|
@ -608,6 +649,7 @@ export default class Metadata extends Module {
|
|||
if ( ! stat )
|
||||
return destroy();
|
||||
|
||||
old_icon = el.dataset.icon || '';
|
||||
old_color = el.dataset.color || '';
|
||||
|
||||
if ( el._ffz_order !== order )
|
||||
|
@ -616,7 +658,17 @@ export default class Metadata extends Module {
|
|||
if ( el.tip_content !== tooltip ) {
|
||||
el.tip_content = tooltip;
|
||||
if ( el.tip )
|
||||
el.tip.element.innerHTML = tooltip;
|
||||
setChildren(el.tip.element, tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
if ( typeof def.icon === 'function' ) {
|
||||
const icon = maybe_call(def.icon, this, data);
|
||||
if ( typeof icon === 'string' && icon !== old_icon ) {
|
||||
el.dataset.icon = icon;
|
||||
const figure = el.querySelector('figure');
|
||||
if ( figure )
|
||||
figure.className = icon;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,12 @@ export default class Channel extends Module {
|
|||
Twilight.CHAT_ROUTES
|
||||
);
|
||||
|
||||
this.ChannelContext = this.fine.define(
|
||||
'channel-context',
|
||||
n => n.resetPrivateVariables && n.fetchChannel && n.clearBroadcastSettingsUpdateInterval,
|
||||
['popout', 'embed-chat']
|
||||
);
|
||||
|
||||
/*this.SquadController = this.fine.define(
|
||||
'squad-controller',
|
||||
n => n.onSquadPage && n.isValidSquad && n.handleLeaveSquad,
|
||||
|
@ -74,7 +80,10 @@ export default class Channel extends Module {
|
|||
|
||||
|
||||
updateChannelColor(color) {
|
||||
const parsed = color && Color.RGBA.fromHex(color);
|
||||
let parsed = color && Color.RGBA.fromHex(color);
|
||||
if ( ! parsed )
|
||||
parsed = Color.RGBA.fromHex('9147FF');
|
||||
|
||||
if ( parsed ) {
|
||||
this.css_tweaks.setVariable('channel-color', parsed.toCSS());
|
||||
this.css_tweaks.setVariable('channel-color-20', parsed._a(0.2).toCSS());
|
||||
|
@ -95,6 +104,14 @@ export default class Channel extends Module {
|
|||
//this.SquadController.on('mount', this.noAutoSquads, this);
|
||||
//this.SquadController.on('update', this.noAutoSquads, this);
|
||||
|
||||
this.ChannelContext.on('mount', this.onChannelContext, this);
|
||||
this.ChannelContext.on('update', this.onChannelContext, this);
|
||||
this.ChannelContext.on('unmount', this.offChannelContext, this);
|
||||
this.ChannelContext.ready((cls, instances) => {
|
||||
for(const inst of instances)
|
||||
this.onChannelContext(inst);
|
||||
});
|
||||
|
||||
this.RaidController.ready((cls, instances) => {
|
||||
for(const inst of instances)
|
||||
this.wrapRaidController(inst);
|
||||
|
@ -148,6 +165,41 @@ export default class Channel extends Module {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
onChannelContext(inst) {
|
||||
if ( ! inst.state || inst.state.loading )
|
||||
return;
|
||||
|
||||
const channel = inst.state.channel,
|
||||
clip = inst.state.clip,
|
||||
video = inst.state.video,
|
||||
|
||||
category = video?.game || clip?.game || channel?.stream?.game || channel?.broadcastSettings?.game;
|
||||
|
||||
const color = inst.state?.primaryColorHex;
|
||||
this.updateChannelColor(color);
|
||||
|
||||
this.settings.updateContext({
|
||||
channel: inst.state.channel?.login,
|
||||
channelID: inst.state.channel?.id,
|
||||
channelColor: color,
|
||||
category: category?.name,
|
||||
categoryID: category?.id
|
||||
});
|
||||
}
|
||||
|
||||
offChannelContext() {
|
||||
this.updateChannelColor(null);
|
||||
this.settings.updateContext({
|
||||
channel: null,
|
||||
channelID: null,
|
||||
category: null,
|
||||
categoryID: null,
|
||||
channelColor: null
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
onChannelMounted(inst) {
|
||||
this.wrapChannelPage(inst);
|
||||
|
||||
|
|
|
@ -47,11 +47,11 @@ export default class ChatLine extends Module {
|
|||
Twilight.CHAT_ROUTES
|
||||
);
|
||||
|
||||
this.ChatRoomLine = this.fine.define(
|
||||
/*this.ChatRoomLine = this.fine.define(
|
||||
'chat-room-line',
|
||||
n => n.renderMessageBody && n.props && ! n.onExtensionNameClick && has(n.props, 'hasModPermissions'),
|
||||
Twilight.CHAT_ROUTES
|
||||
);
|
||||
);*/
|
||||
|
||||
/*this.ChatRoomContainer = this.fine.define(
|
||||
'chat-room-container',
|
||||
|
@ -100,7 +100,7 @@ export default class ChatLine extends Module {
|
|||
FFZRichContent = this.rich_content && this.rich_content.RichContent;
|
||||
|
||||
|
||||
this.ChatRoomLine.ready(cls => {
|
||||
/*this.ChatRoomLine.ready(cls => {
|
||||
const old_render = cls.prototype.render;
|
||||
|
||||
cls.prototype.render = function() { try {
|
||||
|
@ -212,7 +212,7 @@ export default class ChatLine extends Module {
|
|||
// Do this after a short delay to hopefully reduce the chance of React
|
||||
// freaking out on us.
|
||||
setTimeout(() => this.ChatRoomLine.forceUpdate());
|
||||
});
|
||||
});*/
|
||||
|
||||
|
||||
this.WhisperLine.ready(cls => {
|
||||
|
@ -527,7 +527,7 @@ other {# messages were deleted by a moderator.}
|
|||
}, the_list);
|
||||
}
|
||||
|
||||
cls = 'user-notice-line tw-pd-y-05 ffz--subscribe-line';
|
||||
cls = `user-notice-line tw-pd-y-05 ffz--subscribe-line${show_class ? ' ffz--deleted-message' : ''}`;
|
||||
out = [
|
||||
e('div', {
|
||||
className: 'tw-flex tw-c-text-alt-2',
|
||||
|
@ -590,7 +590,7 @@ other {# messages were deleted by a moderator.}
|
|||
count: msg.sub_total
|
||||
}));
|
||||
|
||||
cls = 'user-notice-line tw-pd-y-05 tw-pd-r-2 ffz--subscribe-line';
|
||||
cls = `user-notice-line tw-pd-y-05 tw-pd-r-2 ffz--subscribe-line${show_class ? ' ffz--deleted-message' : ''}`;
|
||||
out = [
|
||||
e('div', {className: 'tw-flex tw-c-text-alt-2'}, [
|
||||
t.chat.context.get('chat.subs.compact') ? null :
|
||||
|
@ -652,7 +652,7 @@ other {# messages were deleted by a moderator.}
|
|||
));
|
||||
}
|
||||
|
||||
cls = 'user-notice-line tw-pd-y-05 tw-pd-r-2 ffz--subscribe-line';
|
||||
cls = `user-notice-line tw-pd-y-05 tw-pd-r-2 ffz--subscribe-line${show_class ? ' ffz--deleted-message' : ''}`;
|
||||
out = [
|
||||
e('div', {className: 'tw-flex tw-c-text-alt-2'}, [
|
||||
t.chat.context.get('chat.subs.compact') ? null :
|
||||
|
@ -690,7 +690,7 @@ other {# messages were deleted by a moderator.}
|
|||
]);
|
||||
|
||||
if ( system_msg ) {
|
||||
cls = 'user-notice-line tw-pd-y-05 tw-pd-r-2 ffz--ritual-line';
|
||||
cls = `user-notice-line tw-pd-y-05 tw-pd-r-2 ffz--ritual-line${show_class ? ' ffz--deleted-message' : ''}`;
|
||||
out = [
|
||||
system_msg,
|
||||
out && e('div', {
|
||||
|
@ -710,7 +710,7 @@ other {# messages were deleted by a moderator.}
|
|||
t.i18n.formatNumber(getRewardCost(msg.ffz_reward))
|
||||
]);
|
||||
|
||||
cls = `ffz--points-line tw-pd-l-1 tw-pd-y-05 tw-pd-r-2${isHighlightedReward(msg.ffz_reward) ? ' ffz--points-highlight' : ''}`;
|
||||
cls = `ffz--points-line tw-pd-l-1 tw-pd-y-05 tw-pd-r-2${isHighlightedReward(msg.ffz_reward) ? ' ffz--points-highlight' : ''}${show_class ? ' ffz--deleted-message' : ''}`;
|
||||
out = [
|
||||
e('div', {className: 'tw-c-text-alt-2'}, [
|
||||
out ? null : t.actions.renderInline(msg, this.props.showModerationIcons, u, r, e),
|
||||
|
@ -872,13 +872,13 @@ other {# messages were deleted by a moderator.}
|
|||
}
|
||||
}
|
||||
|
||||
for(const inst of this.ChatRoomLine.instances) {
|
||||
/*for(const inst of this.ChatRoomLine.instances) {
|
||||
const msg = inst.props.message;
|
||||
if ( msg ) {
|
||||
msg.ffz_tokens = null;
|
||||
msg.mentioned = msg.mention_color = null;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
for(const inst of this.WhisperLine.instances) {
|
||||
const msg = inst.props.message;
|
||||
|
@ -888,7 +888,7 @@ other {# messages were deleted by a moderator.}
|
|||
|
||||
this.ChatLine.forceUpdate();
|
||||
this.ExtensionLine.forceUpdate();
|
||||
this.ChatRoomLine.forceUpdate();
|
||||
//this.ChatRoomLine.forceUpdate();
|
||||
this.WhisperLine.forceUpdate();
|
||||
|
||||
this.emit('chat:updated-lines');
|
||||
|
|
|
@ -20,10 +20,10 @@ export default class Layout extends Module {
|
|||
this.inject('site.fine');
|
||||
this.inject('site.css_tweaks');
|
||||
|
||||
this.TopNav = this.fine.define(
|
||||
/*this.TopNav = this.fine.define(
|
||||
'top-nav',
|
||||
n => n.computeStyles && n.navigationLinkSize
|
||||
);
|
||||
);*/
|
||||
|
||||
/*this.RightColumn = this.fine.define(
|
||||
'tw-rightcolumn',
|
||||
|
@ -239,10 +239,7 @@ export default class Layout extends Module {
|
|||
}
|
||||
|
||||
updateNavLinks() {
|
||||
for(const inst of this.TopNav.instances)
|
||||
try {
|
||||
inst.computeStyles();
|
||||
} catch(err) { /* no-op */ }
|
||||
|
||||
}
|
||||
|
||||
updatePortraitMode() {
|
||||
|
|
|
@ -73,6 +73,21 @@ export default class Player extends Module {
|
|||
|
||||
// Settings
|
||||
|
||||
this.settings.add('player.allow-catchup', {
|
||||
default: true,
|
||||
ui: {
|
||||
path: 'Player > General >> General',
|
||||
title: 'Allow the player to speed up to reduce delay.',
|
||||
description: 'Twitch, by default, will apply a minor speed up to live video when you have a large delay to the broadcaster in order to catch back up with the live broadcast. This may result in audio distortion. Disable this to prevent the automatic speed changes.',
|
||||
component: 'setting-check-box'
|
||||
},
|
||||
|
||||
changed: val => {
|
||||
for(const inst of this.Player.instances)
|
||||
this.updateAutoPlaybackRate(inst, val);
|
||||
}
|
||||
});
|
||||
|
||||
this.settings.add('player.volume-scroll', {
|
||||
default: false,
|
||||
ui: {
|
||||
|
@ -80,11 +95,6 @@ export default class Player extends Module {
|
|||
title: 'Adjust volume by scrolling with the mouse wheel.',
|
||||
description: '*This setting will not work properly on streams with visible extensions when mouse interaction with extensions is allowed.*',
|
||||
component: 'setting-check-box'
|
||||
},
|
||||
|
||||
changed: val => {
|
||||
for(const inst of this.Player.instances)
|
||||
this.updateVolumeScroll(inst, val);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -647,6 +657,19 @@ export default class Player extends Module {
|
|||
}
|
||||
|
||||
|
||||
updateAutoPlaybackRate(inst, val) {
|
||||
const player = inst.props?.mediaPlayerInstance;
|
||||
if ( ! player )
|
||||
return;
|
||||
|
||||
if ( val == null )
|
||||
val = this.settings.get('player.allow-catchup');
|
||||
|
||||
if ( player.setLiveSpeedUpRate )
|
||||
player.setLiveSpeedUpRate(val ? 1.05 : 1);
|
||||
}
|
||||
|
||||
|
||||
updateHideExtensions(val) {
|
||||
if ( val === undefined )
|
||||
val = this.settings.get('player.ext-hide');
|
||||
|
@ -762,6 +785,12 @@ export default class Player extends Module {
|
|||
updateGUI(inst) {
|
||||
this.addPiPButton(inst);
|
||||
this.addResetButton(inst);
|
||||
|
||||
const player = inst?.props?.mediaPlayerInstance;
|
||||
if ( player && ! this.settings.get('player.allow-catchup') ) {
|
||||
if ( player.setLiveSpeedUpRate )
|
||||
player.setLiveSpeedUpRate(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -90,5 +90,6 @@ export default [
|
|||
"t-reset",
|
||||
"whispers",
|
||||
"cake",
|
||||
"channel-points"
|
||||
"channel-points",
|
||||
"fast-fw"
|
||||
];
|
|
@ -60,6 +60,7 @@
|
|||
.ffz-i-t-reset:before { content: '\e83a'; } /* '' */
|
||||
.ffz-i-whispers:before { content: '\e83b'; } /* '' */
|
||||
.ffz-i-channel-points:before { content: '\e83c'; } /* '' */
|
||||
.ffz-i-fast-fw:before { content: '\e83d'; } /* '' */
|
||||
.ffz-i-link-ext:before { content: '\f08e'; } /* '' */
|
||||
.ffz-i-twitter:before { content: '\f099'; } /* '' */
|
||||
.ffz-i-github:before { content: '\f09b'; } /* '' */
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -60,6 +60,7 @@
|
|||
.ffz-i-t-reset { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.ffz-i-whispers { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.ffz-i-channel-points { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.ffz-i-fast-fw { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.ffz-i-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.ffz-i-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.ffz-i-github { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
.ffz-i-t-reset { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.ffz-i-whispers { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.ffz-i-channel-points { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.ffz-i-fast-fw { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.ffz-i-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.ffz-i-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.ffz-i-github { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
@font-face {
|
||||
font-family: 'ffz-fontello';
|
||||
src: url('../font/ffz-fontello.eot?90039340');
|
||||
src: url('../font/ffz-fontello.eot?90039340#iefix') format('embedded-opentype'),
|
||||
url('../font/ffz-fontello.woff2?90039340') format('woff2'),
|
||||
url('../font/ffz-fontello.woff?90039340') format('woff'),
|
||||
url('../font/ffz-fontello.ttf?90039340') format('truetype'),
|
||||
url('../font/ffz-fontello.svg?90039340#ffz-fontello') format('svg');
|
||||
src: url('../font/ffz-fontello.eot?37997143');
|
||||
src: url('../font/ffz-fontello.eot?37997143#iefix') format('embedded-opentype'),
|
||||
url('../font/ffz-fontello.woff2?37997143') format('woff2'),
|
||||
url('../font/ffz-fontello.woff?37997143') format('woff'),
|
||||
url('../font/ffz-fontello.ttf?37997143') format('truetype'),
|
||||
url('../font/ffz-fontello.svg?37997143#ffz-fontello') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
|||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
@font-face {
|
||||
font-family: 'ffz-fontello';
|
||||
src: url('../font/ffz-fontello.svg?90039340#ffz-fontello') format('svg');
|
||||
src: url('../font/ffz-fontello.svg?37997143#ffz-fontello') format('svg');
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
@ -116,6 +116,7 @@
|
|||
.ffz-i-t-reset:before { content: '\e83a'; } /* '' */
|
||||
.ffz-i-whispers:before { content: '\e83b'; } /* '' */
|
||||
.ffz-i-channel-points:before { content: '\e83c'; } /* '' */
|
||||
.ffz-i-fast-fw:before { content: '\e83d'; } /* '' */
|
||||
.ffz-i-link-ext:before { content: '\f08e'; } /* '' */
|
||||
.ffz-i-twitter:before { content: '\f099'; } /* '' */
|
||||
.ffz-i-github:before { content: '\f09b'; } /* '' */
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
margin-right: -0.5rem !important;
|
||||
}
|
||||
|
||||
.ffz-mg-t-1p {
|
||||
margin-top: 1px !important;
|
||||
}
|
||||
|
||||
.ffz-mg-l--05 {
|
||||
margin-left: -0.5rem !important;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue