diff options
Diffstat (limited to 'src/lib/stores')
| -rw-r--r-- | src/lib/stores/playlists.ts | 123 | ||||
| -rw-r--r-- | src/lib/stores/subscriptions.ts | 65 |
2 files changed, 188 insertions, 0 deletions
diff --git a/src/lib/stores/playlists.ts b/src/lib/stores/playlists.ts new file mode 100644 index 0000000..ee516dc --- /dev/null +++ b/src/lib/stores/playlists.ts @@ -0,0 +1,123 @@ +import { writable } from 'svelte/store'; +import { get, set } from 'idb-keyval'; + +export interface PlaylistVideo { + videoId: string; + title: string; + author: string; + authorId: string; + thumbnail: string; + lengthSeconds: number; +} + +export interface Playlist { + id: string; + name: string; + videos: PlaylistVideo[]; + createdAt: number; + updatedAt: number; +} + +const STORAGE_KEY = 'actualyt-playlists'; + +function generateId(): string { + return Date.now().toString(36) + Math.random().toString(36).substring(2); +} + +function createPlaylistStore() { + const { subscribe, set: setStore, update } = writable<Playlist[]>([]); + let initialized = false; + + async function init() { + if (initialized) return; + try { + const stored = await get<Playlist[]>(STORAGE_KEY); + if (stored) { + setStore(stored); + } + initialized = true; + } catch (e) { + console.error('Failed to load playlists:', e); + } + } + + async function persist(playlists: Playlist[]) { + try { + await set(STORAGE_KEY, playlists); + } catch (e) { + console.error('Failed to save playlists:', e); + } + } + + return { + subscribe, + init, + create: async (name: string): Promise<string> => { + const id = generateId(); + const now = Date.now(); + const newPlaylist: Playlist = { + id, + name, + videos: [], + createdAt: now, + updatedAt: now + }; + update(playlists => { + const newPlaylists = [...playlists, newPlaylist]; + persist(newPlaylists); + return newPlaylists; + }); + return id; + }, + delete: async (id: string) => { + update(playlists => { + const newPlaylists = playlists.filter(p => p.id !== id); + persist(newPlaylists); + return newPlaylists; + }); + }, + rename: async (id: string, name: string) => { + update(playlists => { + const newPlaylists = playlists.map(p => + p.id === id ? { ...p, name, updatedAt: Date.now() } : p + ); + persist(newPlaylists); + return newPlaylists; + }); + }, + addVideo: async (playlistId: string, video: PlaylistVideo) => { + update(playlists => { + const newPlaylists = playlists.map(p => { + if (p.id !== playlistId) return p; + if (p.videos.some(v => v.videoId === video.videoId)) return p; + return { + ...p, + videos: [...p.videos, video], + updatedAt: Date.now() + }; + }); + persist(newPlaylists); + return newPlaylists; + }); + }, + removeVideo: async (playlistId: string, videoId: string) => { + update(playlists => { + const newPlaylists = playlists.map(p => { + if (p.id !== playlistId) return p; + return { + ...p, + videos: p.videos.filter(v => v.videoId !== videoId), + updatedAt: Date.now() + }; + }); + persist(newPlaylists); + return newPlaylists; + }); + }, + getById: (playlists: Playlist[], id: string): Playlist | undefined => { + return playlists.find(p => p.id === id); + } + }; +} + +export const playlists = createPlaylistStore(); diff --git a/src/lib/stores/subscriptions.ts b/src/lib/stores/subscriptions.ts new file mode 100644 index 0000000..91f3d36 --- /dev/null +++ b/src/lib/stores/subscriptions.ts @@ -0,0 +1,65 @@ +import { writable } from 'svelte/store'; +import { get, set } from 'idb-keyval'; +import type { VideoThumbnail } from '$lib/api/youtube'; + +export interface Subscription { + channelId: string; + channelName: string; + thumbnail: string; +} + +const STORAGE_KEY = 'actualyt-subscriptions'; + +function createSubscriptionStore() { + const { subscribe, set: setStore, update } = writable<Subscription[]>([]); + let initialized = false; + + async function init() { + if (initialized) return; + try { + const stored = await get<Subscription[]>(STORAGE_KEY); + if (stored) { + setStore(stored); + } + initialized = true; + } catch (e) { + console.error('Failed to load subscriptions:', e); + } + } + + async function persist(subs: Subscription[]) { + try { + await set(STORAGE_KEY, subs); + } catch (e) { + console.error('Failed to save subscriptions:', e); + } + } + + return { + subscribe, + init, + add: async (channelId: string, channelName: string, thumbnails: VideoThumbnail[]) => { + update(subs => { + if (subs.some(s => s.channelId === channelId)) { + return subs; + } + const thumbnail = thumbnails[0]?.url || ''; + const newSubs = [...subs, { channelId, channelName, thumbnail }]; + persist(newSubs); + return newSubs; + }); + }, + remove: async (channelId: string) => { + update(subs => { + const newSubs = subs.filter(s => s.channelId !== channelId); + persist(newSubs); + return newSubs; + }); + }, + isSubscribed: (subs: Subscription[], channelId: string): boolean => { + return subs.some(s => s.channelId === channelId); + } + }; +} + +export const subscriptions = createSubscriptionStore(); |
