diff --git a/package.json b/package.json index f5a8e834..3febb587 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "frankerfacez", "author": "Dan Salvato LLC", - "version": "4.14.7", + "version": "4.14.8", "description": "FrankerFaceZ is a Twitch enhancement suite.", "license": "Apache-2.0", "scripts": { diff --git a/src/sites/twitch-twilight/modules/player.jsx b/src/sites/twitch-twilight/modules/player.jsx index ded349d5..cd55ea74 100644 --- a/src/sites/twitch-twilight/modules/player.jsx +++ b/src/sites/twitch-twilight/modules/player.jsx @@ -11,6 +11,21 @@ export const PLAYER_ROUTES = ['front-page', 'user', 'video', 'user-video', 'user const STYLE_VALIDATOR = createElement('span'); +function rotateButton(event) { + const target = event.currentTarget, + icon = target && target.querySelector('figure'); + if ( ! icon || icon.classList.contains('ffz-i-t-reset-clicked') ) + return; + + icon.classList.toggle('ffz-i-t-reset', false); + icon.classList.toggle('ffz-i-t-reset-clicked', true); + + setTimeout(() => { + icon.classList.toggle('ffz-i-t-reset', true); + icon.classList.toggle('ffz-i-t-reset-clicked', false); + }, 500); +} + export default class Player extends Module { constructor(...args) { super(...args); @@ -395,6 +410,9 @@ export default class Player extends Module { if ( ! this._ffzErrorReset ) this._ffzErrorReset = t.addErrorResetButton.bind(t, this); + if ( ! this._ffzReady ) + this._ffzReady = this.ffzReady.bind(this); + const inst = this, old_active = this.setPlayerActive, old_inactive = this.setPlayerInactive; @@ -427,6 +445,7 @@ export default class Player extends Module { on(events, 'PlayerError', this._ffzErrorReset); on(events, 'Ended', this._ffzUpdateState); on(events, 'Ended', this.ffzOnEnded); + on(events, 'Ready', this._ffzReady); on(events, 'Idle', this._ffzUpdateState); } @@ -444,6 +463,7 @@ export default class Player extends Module { off(events, 'PlayerError', this._ffzErrorReset); off(events, 'Ended', this._ffzUpdateState); off(events, 'Ended', this.ffzOnEnded); + off(events, 'Ready', this._ffzReady); off(events, 'Idle', this._ffzUpdateState); } @@ -452,9 +472,26 @@ export default class Player extends Module { this._ffz_state_raf = null; this._ffzUpdateState = null; this._ffzErrorReset = null; + this._ffzReady = null; this.ffzOnEnded = null; } + cls.prototype.ffzReady = function() { + const cont = this.props.containerRef; + if ( ! cont ) + return; + + requestAnimationFrame(() => { + const icons = cont.querySelectorAll('.ffz--player-reset figure'); + for(const icon of icons) { + if ( icon._ffz_unspin ) + clearTimeout(icon._ffz_unspin); + + icon.classList.toggle('loading', false); + } + }); + } + cls.prototype.ffzStopAutoplay = function() { if ( t.settings.get('player.no-autoplay') || (! t.settings.get('player.home.autoplay') && t.router.current.name === 'front-page') ) { const player = this.props.mediaPlayerInstance, @@ -758,7 +795,7 @@ export default class Player extends Module { >
- {icon = (
)} + {icon = (
)}
)} @@ -777,20 +814,27 @@ export default class Player extends Module { tip = cont.querySelector('.tw-tooltip'); } - const pip_active = !!document.pictureInPictureElement + const pip_active = !!document.pictureInPictureElement, + label = pip_active ? + this.i18n.t('player.pip_button.off', 'Exit Picture-in-Picture') : + this.i18n.t('player.pip_button', 'Picture-in-Picture'); icon.classList.toggle('ffz-i-t-pip-inactive', ! pip_active); icon.classList.toggle('ffz-i-t-pip-active', pip_active); - btn.setAttribute('aria-label', tip.textContent = this.i18n.t('player.pip_button', 'Picture-in-Picture')); + btn.setAttribute('aria-label', label); + tip.textContent = label; } - pipPlayer(inst) { + pipPlayer(inst, e) { const video = inst.props.mediaPlayerInstance?.mediaSinkManager?.video; if ( ! video || ! document.pictureInPictureEnabled ) return; + if ( e ) + e.preventDefault(); + if ( ! video._ffz_pip_enter ) { video.addEventListener('enterpictureinpicture', video._ffz_pip_enter = () => { this.addPiPButton(inst); @@ -836,11 +880,12 @@ export default class Player extends Module { class="tw-align-items-center tw-align-middle tw-border-bottom-left-radius-medium tw-border-bottom-right-radius-medium tw-border-top-left-radius-medium tw-border-top-right-radius-medium tw-button-icon tw-button-icon--overlay tw-core-button tw-core-button--border tw-core-button--overlay tw-inline-flex tw-interactive tw-justify-content-center tw-overflow-hidden tw-relative" type="button" data-a-target="ffz-player-reset-button" + onClick={rotateButton} onDblClick={this.resetPlayer.bind(this, inst)} // eslint-disable-line react/jsx-no-bind >
-
+
)} @@ -903,11 +948,12 @@ export default class Player extends Module { class="tw-align-items-center tw-align-middle tw-border-bottom-left-radius-medium tw-border-bottom-right-radius-medium tw-border-top-left-radius-medium tw-border-top-right-radius-medium tw-button-icon tw-button-icon--overlay tw-core-button tw-core-button--border tw-core-button--overlay tw-inline-flex tw-interactive tw-justify-content-center tw-overflow-hidden tw-relative" type="button" data-a-target="ffz-player-reset-button" + onClick={rotateButton} onDblClick={this.resetPlayer.bind(this, inst)} // eslint-disable-line react/jsx-no-bind >
-
+
)} @@ -929,9 +975,29 @@ export default class Player extends Module { } - resetPlayer(inst) { + resetPlayer(inst, e) { const player = inst ? (inst.mediaSinkManager ? inst : inst?.props?.mediaPlayerInstance) : null; + if ( e ) { + e.preventDefault(); + const target = e.currentTarget, + icon = target && target.querySelector('figure'); + + if ( icon ) { + if ( icon.classList.contains('loading') ) + return; + + icon.classList.toggle('ffz-i-t-reset', true); + icon.classList.toggle('ffz-i-t-reset-clicked', false); + + icon.classList.toggle('loading', true); + icon._ffz_unspin = setTimeout(() => { + icon._ffz_unspin = null; + icon.classList.toggle('loading', false); + }, 10000); + } + } + this.PlayerSource.check(); for(const inst of this.PlayerSource.instances) { if ( ! player || player === inst.props?.mediaPlayerInstance ) diff --git a/styles/icons.scss b/styles/icons.scss index 1afce8e9..90816d62 100644 --- a/styles/icons.scss +++ b/styles/icons.scss @@ -44,6 +44,12 @@ } +.ffz-player-icon { + font-size: 2rem !important; + margin: -.5rem -.4rem !important; +} + + .tw-button-icon__icon { [class^="ffz-i-"], [class*=" ffz-i-"] { font-size: 1.6rem diff --git a/styles/main.scss b/styles/main.scss index 594bb5b8..0d0d856e 100644 --- a/styles/main.scss +++ b/styles/main.scss @@ -13,6 +13,8 @@ } +.ffz-i-t-reset.loading, +.ffz-i-t-reset-clicked.loading, .ffz-i-zreknarf.loading { animation: ffz-rotateplane 1.2s infinite linear; }