Skip to content

Commit bf59ba5

Browse files
committed
fix(player): time updates stop when page is hidden
closes #1332
1 parent cebfe8f commit bf59ba5

4 files changed

Lines changed: 25 additions & 13 deletions

File tree

packages/vidstack/src/foundation/fullscreen/controller.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,27 @@ export class FullscreenController
2929

3030
protected override onConnect() {
3131
// @ts-expect-error
32-
listenEvent(fscreen as any, 'fullscreenchange', this._onFullscreenChange.bind(this) as any);
32+
listenEvent(fscreen, 'fullscreenchange', this._onChange.bind(this));
33+
3334
// @ts-expect-error
34-
listenEvent(fscreen as any, 'fullscreenerror', this._onFullscreenError.bind(this) as any);
35+
listenEvent(fscreen, 'fullscreenerror', this._onError.bind(this));
36+
3537
onDispose(this._onDisconnect.bind(this));
3638
}
3739

38-
protected async _onDisconnect() {
40+
private async _onDisconnect() {
3941
if (CAN_FULLSCREEN) await this.exit();
4042
}
4143

42-
protected _onFullscreenChange(event: Event) {
44+
private _onChange(event: Event) {
4345
const active = isFullscreen(this.el);
4446
if (active === this._active) return;
4547
if (!active) this._listening = false;
4648
this._active = active;
4749
this.dispatch('fullscreen-change', { detail: active, trigger: event });
4850
}
4951

50-
protected _onFullscreenError(event: Event) {
52+
private _onError(event: Event) {
5153
if (!this._listening) return;
5254
this.dispatch('fullscreen-error', { detail: null, trigger: event });
5355
this._listening = false;

packages/vidstack/src/foundation/observers/intersection-observer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ export class IntersectionObserverController extends ViewController {
1414

1515
this._observer.observe(el);
1616

17-
onDispose(this._disconnect.bind(this));
17+
onDispose(this._onDisconnect.bind(this));
1818
}
1919

2020
/**
2121
* Disconnect any active intersection observers.
2222
*/
23-
_disconnect(): void {
23+
protected _onDisconnect(): void {
2424
this._observer?.disconnect();
2525
this._observer = undefined;
2626
}

packages/vidstack/src/foundation/observers/page-visibility.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { signal, ViewController } from 'maverick.js';
1+
import { signal } from 'maverick.js';
22
import { listenEvent } from 'maverick.js/std';
33

44
import { IS_SAFARI } from '../../utils/support';
@@ -14,7 +14,7 @@ declare global {
1414
}
1515
}
1616

17-
export class PageVisibilityController extends ViewController {
17+
export class PageVisibility {
1818
private _state = signal<PageState>(determinePageState());
1919

2020
private _visibility = signal<DocumentVisibility>(
@@ -23,7 +23,7 @@ export class PageVisibilityController extends ViewController {
2323

2424
private _safariBeforeUnloadTimeout: any;
2525

26-
protected override onConnect() {
26+
connect() {
2727
for (const eventType of PAGE_EVENTS) {
2828
listenEvent(window, eventType, this._handlePageEvent.bind(this));
2929
}
@@ -61,7 +61,7 @@ export class PageVisibilityController extends ViewController {
6161
*
6262
* @see https://developers.google.com/web/updates/2018/07/page-lifecycle-api#states
6363
*/
64-
$pageState(): PageState {
64+
get pageState(): PageState {
6565
return this._state();
6666
}
6767

@@ -76,7 +76,7 @@ export class PageVisibilityController extends ViewController {
7676
*
7777
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilityState
7878
*/
79-
$visibility(): DocumentVisibility {
79+
get visibility(): DocumentVisibility {
8080
return this._visibility();
8181
}
8282

packages/vidstack/src/providers/html/html–media-events.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { DOMEvent, isNil, listenEvent, useDisposalBin } from 'maverick.js/std';
44
import type { MediaContext } from '../../core/api/media-context';
55
import type { MediaCanPlayDetail } from '../../core/api/media-events';
66
import type { MediaErrorCode } from '../../core/api/types';
7+
import { PageVisibility } from '../../foundation/observers/page-visibility';
78
import { RAFLoop } from '../../foundation/observers/raf-loop';
89
import { isHLSSrc } from '../../utils/mime';
910
import { getNumberOfDecimalPlaces } from '../../utils/number';
@@ -16,6 +17,7 @@ export class HTMLMediaEvents {
1617
private _attachedLoadStart = false;
1718
private _attachedCanPlay = false;
1819
private _timeRAF = new RAFLoop(this._onAnimationFrame.bind(this));
20+
private _pageVisibility = new PageVisibility();
1921

2022
private get _media() {
2123
return this._provider.media;
@@ -30,7 +32,10 @@ export class HTMLMediaEvents {
3032
private _ctx: MediaContext,
3133
) {
3234
this._attachInitialListeners();
35+
36+
this._pageVisibility.connect();
3337
effect(this._attachTimeUpdate.bind(this));
38+
3439
onDispose(this._onDispose.bind(this));
3540
}
3641

@@ -253,12 +258,17 @@ export class HTMLMediaEvents {
253258
}
254259

255260
protected _attachTimeUpdate() {
256-
if (this._ctx.$state.paused()) {
261+
const isPaused = this._ctx.$state.paused(),
262+
isPageHidden = this._pageVisibility.visibility === 'hidden',
263+
shouldListenToTimeUpdates = isPaused || isPageHidden;
264+
265+
if (shouldListenToTimeUpdates) {
257266
listenEvent(this._media, 'timeupdate', this._onTimeUpdate.bind(this));
258267
}
259268
}
260269

261270
protected _onTimeUpdate(event: Event) {
271+
console.log(this._media.currentTime);
262272
this._updateCurrentTime(this._media.currentTime, event);
263273
}
264274

0 commit comments

Comments
 (0)