mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +09:00
fix(app): keep timers running while the window is visible but unfocused (#1682)
This commit is contained in:
1 parent
438f11adda
commit
30a1271774
2 files changed
+69
-4
No files matched your search
@@ -0,0 +1,65 @@
|
||||
// @vitest-environment happy-dom
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {autorun} from 'mobx';
|
||||
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
|
||||
|
||||
async function loadTick() {
|
||||
vi.resetModules();
|
||||
const {default: Window} = await import('@app/features/window/state/Window');
|
||||
const {default: Tick} = await import('@app/features/ui/state/Tick');
|
||||
return {Tick, Window};
|
||||
}
|
||||
|
||||
describe('Tick', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('keeps counting while the window is visible but not focused', async () => {
|
||||
const {Tick, Window} = await loadTick();
|
||||
const dispose = autorun(() => Tick.nowSecond);
|
||||
const started = Tick.nowSecond;
|
||||
Window.setFocused(false);
|
||||
vi.advanceTimersByTime(3000);
|
||||
expect(Window.visible).toBe(true);
|
||||
expect(Tick.nowSecond).toBe(started + 3);
|
||||
dispose();
|
||||
});
|
||||
|
||||
it('stops counting while the window is hidden', async () => {
|
||||
const {Tick, Window} = await loadTick();
|
||||
const dispose = autorun(() => Tick.nowSecond);
|
||||
Window.setVisible(false);
|
||||
const stopped = Tick.nowSecond;
|
||||
vi.advanceTimersByTime(5000);
|
||||
expect(Tick.nowSecond).toBe(stopped);
|
||||
dispose();
|
||||
});
|
||||
|
||||
it('resynchronises to wall clock as soon as the window becomes visible again', async () => {
|
||||
const {Tick, Window} = await loadTick();
|
||||
const dispose = autorun(() => Tick.nowSecond);
|
||||
Window.setVisible(false);
|
||||
const stopped = Tick.nowSecond;
|
||||
vi.advanceTimersByTime(60_000);
|
||||
expect(Tick.nowSecond).toBe(stopped);
|
||||
Window.setVisible(true);
|
||||
expect(Tick.nowSecond).toBe(stopped + 60);
|
||||
dispose();
|
||||
});
|
||||
|
||||
it('does not run an interval while nothing observes the clock', async () => {
|
||||
const {Tick} = await loadTick();
|
||||
const idle = Tick.nowSecond;
|
||||
vi.advanceTimersByTime(5000);
|
||||
expect(Tick.nowSecond).toBe(idle);
|
||||
const dispose = autorun(() => Tick.nowSecond);
|
||||
expect(Tick.nowSecond).toBe(idle + 5);
|
||||
dispose();
|
||||
});
|
||||
});
|
||||
@@ -20,9 +20,9 @@ class TickRegistryImpl {
|
||||
this.stop();
|
||||
});
|
||||
reaction(
|
||||
() => Window.focused,
|
||||
(focused) => {
|
||||
if (focused) this.start();
|
||||
() => Window.visible,
|
||||
(visible) => {
|
||||
if (visible) this.start();
|
||||
else this.stop();
|
||||
},
|
||||
{fireImmediately: true},
|
||||
@@ -30,7 +30,7 @@ class TickRegistryImpl {
|
||||
}
|
||||
|
||||
private start(): void {
|
||||
if (!this.observed || !Window.focused || this.intervalId !== null) return;
|
||||
if (!this.observed || !Window.visible || this.intervalId !== null) return;
|
||||
this.tick();
|
||||
this.intervalId = window.setInterval(() => this.tick(), 1000);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user