jellytau/src/lib/stores/nextEpisode.ts

107 lines
2.7 KiB
TypeScript

/**
* Next Episode Store (Display Only - Backend-First Architecture)
*
* This store reflects next episode popup state from the backend.
* The backend handles all countdown logic and decisions.
*
* The backend emits ShowNextEpisodePopup and CountdownTick events to update this store.
*/
import { writable, derived } from "svelte/store";
import type { MediaItem } from "$lib/api/types";
export interface NextEpisodeState {
// Popup visibility
isVisible: boolean;
// Episode data
nextEpisode: MediaItem | null;
currentEpisode: MediaItem | null;
// Countdown state (managed by backend)
countdownSeconds: number;
initialCountdownSeconds: number;
// Settings
autoPlayEnabled: boolean;
}
function createNextEpisodeStore() {
const initialState: NextEpisodeState = {
isVisible: false,
nextEpisode: null,
currentEpisode: null,
countdownSeconds: 10,
initialCountdownSeconds: 10,
autoPlayEnabled: true,
};
const { subscribe, set, update } = writable<NextEpisodeState>(initialState);
/**
* Show the next episode popup (called by playerEvents when backend emits event)
*/
function showPopup(
currentEpisode: MediaItem,
nextEpisode: MediaItem,
countdownSeconds: number,
autoPlayEnabled: boolean
): void {
update((s) => ({
...s,
isVisible: true,
currentEpisode,
nextEpisode,
countdownSeconds,
initialCountdownSeconds: countdownSeconds,
autoPlayEnabled,
}));
}
/**
* Update countdown value (called by playerEvents on CountdownTick event)
*/
function updateCountdown(remainingSeconds: number): void {
update((s) => ({
...s,
countdownSeconds: remainingSeconds,
}));
}
/**
* Hide the popup
*/
function hidePopup(): void {
update((s) => ({
...s,
isVisible: false,
}));
}
/**
* Reset store to initial state
*/
function reset(): void {
set(initialState);
}
return {
subscribe,
showPopup,
updateCountdown,
hidePopup,
reset,
};
}
export const nextEpisode = createNextEpisodeStore();
// Derived stores for convenient access
export const isNextEpisodePopupVisible = derived(nextEpisode, ($ne) => $ne.isVisible);
export const nextEpisodeItem = derived(nextEpisode, ($ne) => $ne.nextEpisode);
export const currentEpisodeItem = derived(nextEpisode, ($ne) => $ne.currentEpisode);
export const countdownSeconds = derived(nextEpisode, ($ne) => $ne.countdownSeconds);
export const initialCountdownSeconds = derived(nextEpisode, ($ne) => $ne.initialCountdownSeconds);
export const isAutoPlayEnabled = derived(nextEpisode, ($ne) => $ne.autoPlayEnabled);
export const isCountdownActive = derived(nextEpisode, ($ne) => $ne.isVisible && $ne.countdownSeconds > 0);