Files
oki-podcast-reader/src/lib/user-preferences.ts
T
sucupira 67c701f85a feat: réparation audio, mobile et PWA + charte OKI légère
- Volume propagé en direct sur l'élément audio (le slider ne faisait
  que persister) ; volume 0 respecté (?? 1) ; slider masqué sur iOS
  (can_set_volume) ; mute synchronisé store/élément, persistant entre pistes
- Race condition loadedmetadata, USER_PROGRESS borné à 200 entrées,
  erreurs radio affichées avec bouton Réessayer
- Mobile : barre de progression avec zone tactile 44 px (tap + scrub au doigt),
  boutons 48 px, contrôles wrap, listes paginées 50×50 + content-visibility
- PWA : manifest + icônes 192/512 (any+maskable), service worker manuel
  (shell + pochettes, streams exclus), Media Session API (metadata + 4 handlers)
- SEO : Seo.svelte (canonical, OG, Twitter), footer fédéré OKI + flag-bar
- Mesuré puppeteer 390x844 : seek tactile OK, scrollWidth OK, SW actif
2026-07-21 18:57:26 -04:00

72 lines
1.6 KiB
TypeScript

import clamp from 'just-clamp';
import { persisted } from 'svelte-local-storage-store';
export interface UserPreferences {
playback_rate: number;
volume: number;
muted: boolean;
}
/**
* The default user preferences
*/
const DEFAULT_USER_PREFERENCES: UserPreferences = {
playback_rate: 1,
volume: 1,
muted: false,
};
/**
* The user preferences store
*/
export const USER_PREFERENCES_STORE = persisted<UserPreferences>(
'USER_PREFERENCE',
DEFAULT_USER_PREFERENCES,
);
/**
* Sets the playback rate for the user
* @param value - The playback rate value
*/
const set_playback_rate = (value: number) => {
const playback_rate = clamp(value, 0.5, 5);
return USER_PREFERENCES_STORE.update((prefs) => ({
...prefs,
playback_rate,
}));
};
/**
* Sets the volume for the user
* @param value - The volume value
*/
const set_volume = (value: number) => {
const volume = clamp(value, 0, 1);
return USER_PREFERENCES_STORE.update((prefs) => ({ ...prefs, volume }));
};
/**
* Sets the muted state for the user. This is the single source of truth
* for mute: the audio element is kept in sync with it.
* @param value - The muted value
*/
const set_muted = (value: boolean) => {
return USER_PREFERENCES_STORE.update((prefs) => ({ ...prefs, muted: value }));
};
/**
* Clears user preferences store
*/
const clear_store = () => USER_PREFERENCES_STORE.set(DEFAULT_USER_PREFERENCES);
/**
* The user preferences object
*/
export const user_preferences = {
subscribe: USER_PREFERENCES_STORE.subscribe,
set_playback_rate,
set_volume,
set_muted,
clear: clear_store,
};