mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-07-05 18:48:31 +00:00
4.0.0-rc12.2
* Fixed: Take a few more variables into account when sizing the player for Portrait Mode. * Changed: Fade in the Host button, not responding to user interaction while it's fading to give users a chance to react to the UI change.
This commit is contained in:
parent
7e4223ccdd
commit
d091a35079
11 changed files with 134 additions and 32 deletions
|
@ -196,6 +196,24 @@ export default class ExperimentManager extends Module {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTwitchKeyFromName(name) {
|
||||||
|
const experiments = this.getTwitchExperiments();
|
||||||
|
if ( ! experiments )
|
||||||
|
return undefined;
|
||||||
|
|
||||||
|
name = name.toLowerCase();
|
||||||
|
for(const key in experiments)
|
||||||
|
if ( has(experiments, key) ) {
|
||||||
|
const data = experiments[key];
|
||||||
|
if ( data && data.name && data.name.toLowerCase() === name )
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getTwitchAssignmentByName(name) {
|
||||||
|
return this.getTwitchAssignment(this.getTwitchKeyFromName(name));
|
||||||
|
}
|
||||||
|
|
||||||
_rebuildTwitchKey(key, is_set, new_val) {
|
_rebuildTwitchKey(key, is_set, new_val) {
|
||||||
const core = this.resolve('site').getCore(),
|
const core = this.resolve('site').getCore(),
|
||||||
exps = core.experiments,
|
exps = core.experiments,
|
||||||
|
|
|
@ -100,7 +100,7 @@ class FrankerFaceZ extends Module {
|
||||||
FrankerFaceZ.Logger = Logger;
|
FrankerFaceZ.Logger = Logger;
|
||||||
|
|
||||||
const VER = FrankerFaceZ.version_info = {
|
const VER = FrankerFaceZ.version_info = {
|
||||||
major: 4, minor: 0, revision: 0, extra: '-rc12.1',
|
major: 4, minor: 0, revision: 0, extra: '-rc12.2',
|
||||||
commit: __git_commit__,
|
commit: __git_commit__,
|
||||||
build: __webpack_hash__,
|
build: __webpack_hash__,
|
||||||
toString: () =>
|
toString: () =>
|
||||||
|
|
|
@ -266,17 +266,36 @@ export default class Metadata extends Module {
|
||||||
data = await def.setup.call(this, data);
|
data = await def.setup.call(this, data);
|
||||||
|
|
||||||
// Let's get refresh logic out of the way now.
|
// Let's get refresh logic out of the way now.
|
||||||
const refresh = maybe_call(def.refresh, this, data);
|
let refresh = maybe_call(def.refresh, this, data);
|
||||||
|
let fade_in = maybe_call(def.fade_in, this, data);
|
||||||
|
|
||||||
|
// Grab the element again in case it changed, somehow.
|
||||||
|
el = container.querySelector(`.ffz-sidebar-stat[data-key="${key}"]`);
|
||||||
|
|
||||||
|
if ( refresh && typeof refresh !== 'number' )
|
||||||
|
refresh = 1000;
|
||||||
|
|
||||||
|
if ( fade_in && typeof fade_in !== 'number' )
|
||||||
|
fade_in = 1500;
|
||||||
|
|
||||||
|
if ( fade_in && el && el._ffz_fading ) {
|
||||||
|
// If we have a fade-in and we're still fading in, make sure to
|
||||||
|
// update the metadata when that completes, if not sooner.
|
||||||
|
const remaining = fade_in - (Date.now() - el._ffz_created);
|
||||||
|
if ( remaining <= 0 ) {
|
||||||
|
el._ffz_fading = false;
|
||||||
|
el.classList.remove('ffz--fade-in');
|
||||||
|
|
||||||
|
} else if ( ! refresh || remaining <= refresh )
|
||||||
|
refresh = remaining;
|
||||||
|
}
|
||||||
|
|
||||||
if ( refresh )
|
if ( refresh )
|
||||||
timers[key] = setTimeout(
|
timers[key] = setTimeout(
|
||||||
() => refresh_fn(key),
|
() => refresh_fn(key),
|
||||||
typeof refresh === 'number' ? refresh : 1000
|
typeof refresh === 'number' ? refresh : 1000
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Grab the element again in case it changed, somehow.
|
|
||||||
el = container.querySelector(`.ffz-sidebar-stat[data-key="${key}"]`);
|
|
||||||
|
|
||||||
let stat, old_color, sub_el;
|
let stat, old_color, sub_el;
|
||||||
|
|
||||||
const label = maybe_call(def.label, this, data);
|
const label = maybe_call(def.label, this, data);
|
||||||
|
@ -335,7 +354,7 @@ export default class Metadata extends Module {
|
||||||
|
|
||||||
if ( def.click )
|
if ( def.click )
|
||||||
btn.addEventListener('click', e => {
|
btn.addEventListener('click', e => {
|
||||||
if ( btn.disabled || btn.classList.contains('disabled') || el.disabled || el.classList.contains('disabled') )
|
if ( el._ffz_fading || btn.disabled || btn.classList.contains('disabled') || el.disabled || el.classList.contains('disabled') )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
def.click.call(this, el._ffz_data, e, () => refresh_fn(key));
|
def.click.call(this, el._ffz_data, e, () => refresh_fn(key));
|
||||||
|
@ -343,7 +362,7 @@ export default class Metadata extends Module {
|
||||||
|
|
||||||
if ( def.popup )
|
if ( def.popup )
|
||||||
popup.addEventListener('click', () => {
|
popup.addEventListener('click', () => {
|
||||||
if ( popup.disabled || popup.classList.contains('disabled') || el.disabled || el.classList.contains('disabled') )
|
if ( el._ffz_fading || popup.disabled || popup.classList.contains('disabled') || el.disabled || el.classList.contains('disabled') )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( el._ffz_popup )
|
if ( el._ffz_popup )
|
||||||
|
@ -428,6 +447,14 @@ export default class Metadata extends Module {
|
||||||
if ( order != null )
|
if ( order != null )
|
||||||
el.style.order = order;
|
el.style.order = order;
|
||||||
|
|
||||||
|
el._ffz_created = Date.now();
|
||||||
|
|
||||||
|
if ( fade_in ) {
|
||||||
|
el._ffz_fading = true;
|
||||||
|
el.classList.add('ffz--fade-in');
|
||||||
|
el.style.setProperty('--ffz-fade-duration', `${fade_in/1000}s`);
|
||||||
|
}
|
||||||
|
|
||||||
subcontainer.appendChild(el);
|
subcontainer.appendChild(el);
|
||||||
|
|
||||||
if ( def.tooltip ) {
|
if ( def.tooltip ) {
|
||||||
|
|
|
@ -151,6 +151,8 @@ export default class Channel extends Module {
|
||||||
state.videoPlayerSource = expected;
|
state.videoPlayerSource = expected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.settings.updateContext({hosting: !!state.hostMode});
|
||||||
|
|
||||||
} else if ( has(state, 'videoPlayerSource') ) {
|
} else if ( has(state, 'videoPlayerSource') ) {
|
||||||
if ( state.videoPlayerSource !== expected && ! t.settings.get('channel.hosting.enable') )
|
if ( state.videoPlayerSource !== expected && ! t.settings.get('channel.hosting.enable') )
|
||||||
state.videoPlayerSource = expected;
|
state.videoPlayerSource = expected;
|
||||||
|
@ -164,6 +166,9 @@ export default class Channel extends Module {
|
||||||
if ( has(state, 'videoPlayerSource') )
|
if ( has(state, 'videoPlayerSource') )
|
||||||
state.videoPlayerSource = inst.ffzGetChannel();
|
state.videoPlayerSource = inst.ffzGetChannel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( has(state, 'isHosting') )
|
||||||
|
t.settings.updateContext({hosting: state.isHosting});
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
|
@ -177,6 +182,8 @@ export default class Channel extends Module {
|
||||||
|
|
||||||
if ( new_style ) {
|
if ( new_style ) {
|
||||||
const hosted = inst.ffzExpectedHost = inst.state.hostMode;
|
const hosted = inst.ffzExpectedHost = inst.state.hostMode;
|
||||||
|
this.settings.updateContext({hosting: this.settings.get('channel.hosting.enable') && !!inst.state.hostMode});
|
||||||
|
|
||||||
if ( hosted && ! this.settings.get('channel.hosting.enable') ) {
|
if ( hosted && ! this.settings.get('channel.hosting.enable') ) {
|
||||||
inst.ffzOldSetState({
|
inst.ffzOldSetState({
|
||||||
hostMode: null,
|
hostMode: null,
|
||||||
|
@ -185,7 +192,7 @@ export default class Channel extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
inst.ffzOldGetHostedLogin = inst.getHostedChannelLogin;
|
inst.ffzOldGetHostedLogin = () => get('props.data.user.hosting.login', inst) || null;
|
||||||
inst.getHostedChannelLogin = function() {
|
inst.getHostedChannelLogin = function() {
|
||||||
return t.settings.get('channel.hosting.enable') ?
|
return t.settings.get('channel.hosting.enable') ?
|
||||||
inst.ffzOldGetHostedLogin() : null;
|
inst.ffzOldGetHostedLogin() : null;
|
||||||
|
@ -200,15 +207,15 @@ export default class Channel extends Module {
|
||||||
|
|
||||||
// Store the current state and disable the current host if needed.
|
// Store the current state and disable the current host if needed.
|
||||||
inst.ffzExpectedHost = inst.state.isHosting ? inst.state.videoPlayerSource : null;
|
inst.ffzExpectedHost = inst.state.isHosting ? inst.state.videoPlayerSource : null;
|
||||||
if ( ! this.settings.get('channel.hosting.enable') )
|
this.settings.updateContext({hosting: this.settings.get('channel.hosting.enable') && inst.state.isHosting});
|
||||||
|
if ( ! this.settings.get('channel.hosting.enable') ) {
|
||||||
inst.ffzOldHostHandler(null);
|
inst.ffzOldHostHandler(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, we force an update so that any child components
|
// Finally, we force an update so that any child components
|
||||||
// receive our updated handler.
|
// receive our updated handler.
|
||||||
inst.forceUpdate();
|
inst.forceUpdate();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -216,7 +223,12 @@ export default class Channel extends Module {
|
||||||
if ( val === undefined )
|
if ( val === undefined )
|
||||||
val = this.settings.get('channel.hosting.enable');
|
val = this.settings.get('channel.hosting.enable');
|
||||||
|
|
||||||
|
let hosting = val;
|
||||||
|
|
||||||
for(const inst of this.ChannelPage.instances) {
|
for(const inst of this.ChannelPage.instances) {
|
||||||
|
if ( ! inst.ffzExpectedHost )
|
||||||
|
hosting = false;
|
||||||
|
|
||||||
if ( has(inst.state, 'hostMode') ) {
|
if ( has(inst.state, 'hostMode') ) {
|
||||||
const host = val ? inst.ffzExpectedHost : null,
|
const host = val ? inst.ffzExpectedHost : null,
|
||||||
target = host && host.hostedChannel && host.hostedChannel.login || inst.ffzGetChannel();
|
target = host && host.hostedChannel && host.hostedChannel.login || inst.ffzGetChannel();
|
||||||
|
@ -229,5 +241,7 @@ export default class Channel extends Module {
|
||||||
} else
|
} else
|
||||||
inst.ffzOldHostHandler(val ? inst.ffzExpectedHost : null);
|
inst.ffzOldHostHandler(val ? inst.ffzExpectedHost : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.settings.updateContext({hosting});
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,7 +5,6 @@
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
import {deep_copy} from 'utilities/object';
|
|
||||||
|
|
||||||
import CHANNEL_QUERY from './channel_bar_query.gql';
|
import CHANNEL_QUERY from './channel_bar_query.gql';
|
||||||
|
|
||||||
|
@ -15,6 +14,7 @@ export default class ChannelBar extends Module {
|
||||||
|
|
||||||
this.should_enable = true;
|
this.should_enable = true;
|
||||||
|
|
||||||
|
this.inject('settings');
|
||||||
this.inject('site.fine');
|
this.inject('site.fine');
|
||||||
this.inject('site.apollo');
|
this.inject('site.apollo');
|
||||||
this.inject('metadata');
|
this.inject('metadata');
|
||||||
|
@ -42,6 +42,8 @@ export default class ChannelBar extends Module {
|
||||||
this.ChannelBar.on('update', this.updateChannelBar, this);
|
this.ChannelBar.on('update', this.updateChannelBar, this);
|
||||||
|
|
||||||
this.ChannelBar.ready((cls, instances) => {
|
this.ChannelBar.ready((cls, instances) => {
|
||||||
|
this.settings.updateContext({new_channel: true});
|
||||||
|
|
||||||
for(const inst of instances)
|
for(const inst of instances)
|
||||||
this.updateChannelBar(inst);
|
this.updateChannelBar(inst);
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
import {ColorAdjuster} from 'utilities/color';
|
import {ColorAdjuster} from 'utilities/color';
|
||||||
import {setChildren} from 'utilities/dom';
|
import {setChildren} from 'utilities/dom';
|
||||||
import {has, split_chars, shallow_object_equals, deep_copy} from 'utilities/object';
|
import {has, split_chars, shallow_object_equals} from 'utilities/object';
|
||||||
import {FFZEvent} from 'utilities/events';
|
import {FFZEvent} from 'utilities/events';
|
||||||
|
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
|
@ -100,6 +100,7 @@ const CHAT_TYPES = ((e = {}) => {
|
||||||
e[e.BitsCharity = 29] = 'BitsCharity';
|
e[e.BitsCharity = 29] = 'BitsCharity';
|
||||||
e[e.CrateGift = 30] = 'CrateGift';
|
e[e.CrateGift = 30] = 'CrateGift';
|
||||||
e[e.RewardGift = 31] = 'RewardGift';
|
e[e.RewardGift = 31] = 'RewardGift';
|
||||||
|
e[e.SubMysteryGift = 32] = 'SubMysteryGift';
|
||||||
return e;
|
return e;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
|
@ -92,16 +92,44 @@ export default class CSSTweaks extends Module {
|
||||||
changed: val => this.toggle('portrait', val)
|
changed: val => this.toggle('portrait', val)
|
||||||
});
|
});
|
||||||
|
|
||||||
this.settings.add('layout.sidenav-width', {
|
this.settings.add('layout.portrait-extra-height', {
|
||||||
require: ['context.ui.theatreModeEnabled', 'context.ui.sideNavExpanded'],
|
requires: ['context.new_channel', 'context.hosting', 'context.ui.theatreModeEnabled', 'player.theatre.no-whispers', 'whispers.show', 'layout.minimal-navigation'],
|
||||||
process(ctx) {
|
process(ctx) {
|
||||||
if ( ctx.get('context.ui.theatreModeEnabled') )
|
let height = 0;
|
||||||
return '0';
|
if ( ctx.get('context.ui.theatreModeEnabled') ) {
|
||||||
|
if ( ctx.get('layout.minimal-navigation') )
|
||||||
|
height += 1;
|
||||||
|
|
||||||
|
if ( ctx.get('whispers.show') && ! ctx.get('player.theatre.no-whispers') )
|
||||||
|
height += 4;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
height = ctx.get('layout.minimal-navigation') ? 1 : 5;
|
||||||
|
if ( ctx.get('whispers.show') )
|
||||||
|
height += 4;
|
||||||
|
|
||||||
|
height += ctx.get('context.new_channel') ? 1 : 5;
|
||||||
|
|
||||||
|
if ( ctx.get('context.hosting') )
|
||||||
|
height += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${height}rem`;
|
||||||
|
},
|
||||||
|
|
||||||
|
changed: val => this.setVariable('portrait-extra-height', val)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.settings.add('layout.portrait-extra-width', {
|
||||||
|
require: ['layout.side-nav.show', 'context.ui.theatreModeEnabled', 'context.ui.sideNavExpanded'],
|
||||||
|
process(ctx) {
|
||||||
|
if ( ! ctx.get('layout.side-nav.show') || ctx.get('context.ui.theatreModeEnabled') )
|
||||||
|
return '0px';
|
||||||
|
|
||||||
return ctx.get('context.ui.sideNavExpanded') ? '24rem' : '5rem'
|
return ctx.get('context.ui.sideNavExpanded') ? '24rem' : '5rem'
|
||||||
},
|
},
|
||||||
|
|
||||||
changed: val => this.setVariable('sidenav-width', val)
|
changed: val => this.setVariable('portrait-extra-width', val)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -273,7 +301,8 @@ export default class CSSTweaks extends Module {
|
||||||
|
|
||||||
this.toggleHide('whispers', !this.settings.get('whispers.show'));
|
this.toggleHide('whispers', !this.settings.get('whispers.show'));
|
||||||
|
|
||||||
this.setVariable('sidenav-width', this.settings.get('layout.sidenav-width'))
|
this.setVariable('portrait-extra-width', this.settings.get('layout.portrait-extra-width'))
|
||||||
|
this.setVariable('portrait-extra-height', this.settings.get('layout.portrait-extra-height'))
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleHide(key, val) {
|
toggleHide(key, val) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
.twilight-root {
|
.twilight-root {
|
||||||
--ffz-player-width: calc(100vw - var(--ffz-sidenav-width));
|
--ffz-player-width: calc(100vw - var(--ffz-portrait-extra-width));
|
||||||
--ffz-player-height: calc(calc(var(--ffz-player-width) * 0.5625) + 10rem);
|
--ffz-player-height: calc(calc(calc(var(--ffz-player-width) * 0.5625) + var(--ffz-portrait-extra-height)));
|
||||||
--ffz-theater-height: calc(100vw * 0.5625);
|
--ffz-theater-height: calc(calc(100vw * 0.5625) + var(--ffz-portrait-extra-height));
|
||||||
|
|
||||||
& > .tw-full-height {
|
& > .tw-full-height {
|
||||||
height: var(--ffz-player-height) !important;
|
height: var(--ffz-player-height) !important;
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.persistent-player--theatre {
|
.persistent-player.persistent-player--theatre {
|
||||||
top: 0 !important;
|
top: 0 !important;
|
||||||
left: 0 !important;
|
left: 0 !important;
|
||||||
right: 0 !important;
|
right: 0 !important;
|
||||||
|
@ -25,6 +25,11 @@
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.whispers--theatre-mode {
|
||||||
|
bottom: 5rem !important;
|
||||||
|
right: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.right-column {
|
.right-column {
|
||||||
display: unset !important;
|
display: unset !important;
|
||||||
position: fixed !important;
|
position: fixed !important;
|
||||||
|
|
|
@ -55,6 +55,7 @@ export default class HostButton extends Module {
|
||||||
this.metadata.definitions.host = {
|
this.metadata.definitions.host = {
|
||||||
order: 150,
|
order: 150,
|
||||||
button: true,
|
button: true,
|
||||||
|
fade_in: true,
|
||||||
|
|
||||||
disabled: () => this._host_updating || this._host_error,
|
disabled: () => this._host_updating || this._host_error,
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
// Video Chat Hooks
|
// Video Chat Hooks
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
import {has, get} from 'utilities/object';
|
import {get} from 'utilities/object';
|
||||||
import {print_duration} from 'utilities/time';
|
import {print_duration} from 'utilities/time';
|
||||||
import {ClickOutside} from 'utilities/dom';
|
//import {ClickOutside} from 'utilities/dom';
|
||||||
import {formatBitsConfig} from '../chat';
|
import {formatBitsConfig} from '../chat';
|
||||||
|
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
|
@ -242,7 +242,7 @@ export default class VideoChatHook extends Module {
|
||||||
</button>
|
</button>
|
||||||
</div>)}
|
</div>)}
|
||||||
<ul>{
|
<ul>{
|
||||||
context.replies.map(reply => (<li class="tw-mg-l-05">
|
context.replies.map(reply => (<li key={reply.comment && reply.comment.id} class="tw-mg-l-05">
|
||||||
{ this.ffzRenderMessage(t.standardizeMessage(reply.comment, reply.author)) }
|
{ this.ffzRenderMessage(t.standardizeMessage(reply.comment, reply.author)) }
|
||||||
{ this.props.isExpandedLayout && this.ffzRenderExpanded(msg) }
|
{ this.props.isExpandedLayout && this.ffzRenderExpanded(msg) }
|
||||||
</li>))
|
</li>))
|
||||||
|
@ -418,9 +418,4 @@ export default class VideoChatHook extends Module {
|
||||||
|
|
||||||
room.updateBitsConfig(formatBitsConfig(config));
|
room.updateBitsConfig(formatBitsConfig(config));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function formatDuration(seconds) {
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -36,6 +36,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ffz--fade-in {
|
||||||
|
pointer-events: none;
|
||||||
|
animation: ffz-fade-in var(--ffz-fade-duration) 1;
|
||||||
|
}
|
||||||
|
|
||||||
.ffz-sidebar-stats {
|
.ffz-sidebar-stats {
|
||||||
margin-top: .5rem;
|
margin-top: .5rem;
|
||||||
margin-right: -1rem;
|
margin-right: -1rem;
|
||||||
|
@ -69,4 +74,9 @@
|
||||||
max-width: 3.2rem;
|
max-width: 3.2rem;
|
||||||
max-height: 3.2rem;
|
max-height: 3.2rem;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes ffz-fade-in {
|
||||||
|
from {opacity: 0}
|
||||||
|
to {opacity: 1}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue