feat(channel): page details chaine multi-providers avec onglets et infinite scroll
CI / build-and-test (push) Successful in 13m34s

- Strategy Pattern front: ChannelProviderInterface + 6 providers (yt/dm/tw/pt/od/ru) + factory (ids longs/courts)
- ChannelContentService: cache par onglet/tri/recherche (TTL 5min), pagination nextPage
- ChannelPage: header (banniere/avatar/subs/description ...plus), tabs dynamiques par capabilities, grilles videos/shorts 9:16/playlists/live, recherche debounced, tri recent/populaire, infinite scroll IntersectionObserver, skeletons/empty/error
- Backend: GET /api/channels/:provider/:id/content (videos/shorts/playlists/live) natif par provider
This commit is contained in:
2026-09-25 10:15:12 -04:00
parent fe35340948
commit 97e5de74f5
147 changed files with 7954 additions and 77497 deletions
@@ -0,0 +1,27 @@
BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS channels (
id INTEGER PRIMARY KEY AUTOINCREMENT,
provider TEXT NOT NULL,
external_id TEXT NOT NULL,
title TEXT,
handle TEXT,
avatar_url TEXT,
url TEXT,
subs_count INTEGER,
verified INTEGER DEFAULT 0,
last_refreshed_at INTEGER,
UNIQUE(provider, external_id)
);
CREATE TABLE IF NOT EXISTS subscriptions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
channel_id INTEGER NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
created_at INTEGER NOT NULL,
UNIQUE(user_id, channel_id)
);
CREATE INDEX IF NOT EXISTS idx_subs_user ON subscriptions(user_id);
COMMIT;
@@ -0,0 +1,2 @@
-- Add multi-provider default selection (JSON array string, e.g. '["yt","dm"]').
ALTER TABLE user_preferences ADD COLUMN default_providers TEXT;
@@ -0,0 +1,28 @@
-- Persistent download queue: jobs survive API restarts, per-user scoping
BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS download_jobs (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
provider TEXT NOT NULL,
video_id TEXT NOT NULL,
title TEXT,
state TEXT NOT NULL DEFAULT 'queued', -- queued|running|merging|completed|failed|interrupted
progress REAL NOT NULL DEFAULT 0,
format_id TEXT,
audio_only INTEGER NOT NULL DEFAULT 0,
url TEXT,
file_name TEXT,
file_ext TEXT,
file_size INTEGER,
file_path TEXT,
error TEXT,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
completed_at INTEGER
);
CREATE INDEX IF NOT EXISTS idx_download_jobs_user ON download_jobs(user_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_download_jobs_state ON download_jobs(state);
COMMIT;
@@ -0,0 +1,11 @@
-- Minimal telemetry for the unified search UX (Step 13).
-- Stores anonymous, non-identifying product events.
CREATE TABLE IF NOT EXISTS telemetry_events (
id TEXT PRIMARY KEY,
user_id TEXT,
event TEXT NOT NULL,
meta_json TEXT,
created_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_telemetry_event_time ON telemetry_events(event, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_telemetry_user_time ON telemetry_events(user_id, created_at DESC);
BIN
View File
Binary file not shown.
+20 -21
View File
@@ -19,6 +19,7 @@ CREATE TABLE IF NOT EXISTS user_preferences (
user_id TEXT PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
language TEXT DEFAULT 'en',
default_provider TEXT,
default_providers TEXT,
theme TEXT DEFAULT 'system',
video_quality TEXT DEFAULT 'auto',
region TEXT,
@@ -83,32 +84,30 @@ CREATE TABLE IF NOT EXISTS watch_history (
CREATE UNIQUE INDEX IF NOT EXISTS uq_watch_history_user_video ON watch_history(user_id, provider, video_id);
CREATE INDEX IF NOT EXISTS idx_watch_history_user_time ON watch_history(user_id, watched_at DESC);
-- Subscriptions & categories -----------------------------------------------
CREATE TABLE IF NOT EXISTS categories (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name TEXT NOT NULL,
created_at TEXT NOT NULL,
UNIQUE(user_id, name)
-- Channels cache & subscriptions --------------------------------------------
CREATE TABLE IF NOT EXISTS channels (
id INTEGER PRIMARY KEY AUTOINCREMENT,
provider TEXT NOT NULL,
external_id TEXT NOT NULL,
title TEXT,
handle TEXT,
avatar_url TEXT,
url TEXT,
subs_count INTEGER,
verified INTEGER DEFAULT 0,
last_refreshed_at INTEGER,
UNIQUE(provider, external_id)
);
CREATE TABLE IF NOT EXISTS subscriptions (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
provider TEXT NOT NULL,
channel_id TEXT NOT NULL,
channel_name TEXT,
notify INTEGER NOT NULL DEFAULT 0,
subscribed_at TEXT NOT NULL,
UNIQUE(user_id, provider, channel_id)
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
channel_id INTEGER NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
created_at INTEGER NOT NULL,
UNIQUE(user_id, channel_id)
);
CREATE TABLE IF NOT EXISTS subscription_categories (
subscription_id TEXT NOT NULL REFERENCES subscriptions(id) ON DELETE CASCADE,
category_id TEXT NOT NULL REFERENCES categories(id) ON DELETE CASCADE,
PRIMARY KEY (subscription_id, category_id)
);
CREATE INDEX IF NOT EXISTS idx_subscriptions_user ON subscriptions(user_id);
CREATE INDEX IF NOT EXISTS idx_subs_user ON subscriptions(user_id);
-- Playlists -----------------------------------------------------------------
CREATE TABLE IF NOT EXISTS playlists (