Files
jellytau/src/lib/stores/sleepTimer.ts
T
dtourolle 75014ee00f
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 4m1s
Traceability Validation / Check Requirement Traces (push) Successful in 23s
Build & Release / Run Tests (push) Successful in 4m7s
🏗️ Build and Test JellyTau / Build Android APK (push) Successful in 19m5s
Build & Release / Build Linux (push) Successful in 16m20s
Build & Release / Build Android (push) Successful in 19m12s
Build & Release / Create Release (push) Successful in 8s
Fix sleep bug, fix menu return
2026-07-01 23:49:51 +02:00

85 lines
2.4 KiB
TypeScript

/**
* Sleep Timer Store (Backend-First Architecture)
*
* This store reflects sleep timer state from the backend.
* All logic is in the Rust backend (PlayerController).
*
* The backend emits SleepTimerChanged events to update this store.
* Components call store methods which invoke the backend API.
*
* TRACES: UR-026 | DR-029
*/
import { writable, derived } from "svelte/store";
import { commands } from "$lib/api/bindings";
export type SleepTimerMode =
| { kind: "off" }
| { kind: "time"; endTime: number }
| { kind: "endOfTrack" }
| { kind: "episodes"; remaining: number };
interface SleepTimerState {
mode: SleepTimerMode;
remainingSeconds: number;
}
function createSleepTimerStore() {
const initialState: SleepTimerState = {
mode: { kind: "off" },
remainingSeconds: 0,
};
const { subscribe, set } = writable<SleepTimerState>(initialState);
return {
subscribe,
set, // Updated by playerEvents.ts when backend emits SleepTimerChanged event
// Methods that invoke the backend API
async setTimeTimer(minutes: number): Promise<void> {
const endTime = Date.now() + minutes * 60 * 1000;
await commands.playerSetSleepTimer({ kind: "time", endTime });
},
async setEndOfTrackTimer(): Promise<void> {
await commands.playerSetSleepTimer({ kind: "endOfTrack" });
},
async setEpisodesTimer(count: number): Promise<void> {
await commands.playerSetSleepTimer({ kind: "episodes", remaining: count });
},
async cancel(): Promise<void> {
await commands.playerCancelSleepTimer();
},
};
}
export const sleepTimer = createSleepTimerStore();
/**
* Incremented each time the backend reports the time-based sleep timer
* expired. The backend stops its own (MPV/ExoPlayer) playback itself, but
* HTML5 video on Linux plays in the webview outside the backend's control —
* VideoPlayer watches this signal and pauses the <video> element.
*/
export const sleepTimerExpiredSignal = writable(0);
// Derived stores for convenient access
export const sleepTimerMode = derived(sleepTimer, ($s) => $s.mode);
export const sleepTimerActive = derived(
sleepTimer,
($s) => $s.mode.kind !== "off"
);
export const sleepTimerRemainingSeconds = derived(
sleepTimer,
($s) => $s.remainingSeconds
);
export const sleepTimerRemainingEpisodes = derived(sleepTimer, ($s) =>
$s.mode.kind === "episodes" ? $s.mode.remaining : 0
);