Commit graph

11 commits

Author SHA1 Message Date
npeter83
2b072a10de feat(playlists): make YouTube-mirrored playlists editable + syncable
Mirrors (source='youtube') were read-only; per the original two-way design they can
now be edited locally (add/remove/reorder/rename) and pushed back. The read-sync
skips a dirty mirror so it won't clobber unpushed edits; a successful push clears
dirty and lets the mirror refresh. _mark_dirty now covers any YouTube-linked list
(exported local or mirror), and rename marks dirty too. push/delete no longer reject
mirrors. Push reconciles the title as well (cheap playlists.list compare, then
playlists.update only if changed) so a local rename doesn't revert on the next pull.
Frontend: editable = not-built-in (was also excluding mirrors); rows/reorder enabled
for all owned lists; AddToPlaylist popover lists mirrors too (with a YT marker); the
origin chip now reads 'edits sync back'. Trilingual.
2026-06-15 21:40:13 +02:00
npeter83
05c2399b94 feat(playlists): Sync to YouTube UI + delete-on-YouTube choice
Editable local playlists get an Export/Sync to YouTube button (write-scope gated):
it fetches a dry-run plan, shows a confirm with the change counts, quota estimate
and divergence warning, then pushes. An 'unsynced changes' badge and an accented
YouTube icon mark linked playlists with local edits. Deleting a linked playlist
offers 'delete on YouTube too' vs 'here only'. Trilingual strings (HU/EN/DE).
2026-06-15 21:23:13 +02:00
npeter83
f1495594af fix(notifications): use the success level for success toasts
The 'Synced N playlists' and 'View link copied' toasts used the default info level,
which renders in the accent colour and read as an error/alert. Mark them level:success
so they show the green check — clearly positive and theme-independent.
2026-06-15 19:46:37 +02:00
npeter83
12339009b5 feat(playlists): YouTube-mirrored playlists in the UI (read-only) + sync button
Show YouTube-sourced playlists with a YouTube icon; they're read-only for now (no
rename/delete/reorder/remove, excluded from the add-to-playlist popover) with a
'synced from YouTube' note — editing comes with the write-back phase. Add a 'Sync from
YouTube' button in the Playlists rail (api.syncYoutubePlaylists) with a result toast.
Trilingual strings.
2026-06-15 19:37:17 +02:00
npeter83
639d761bef feat(playlists): keep the player queue live across tabs
Track the playing item by id instead of a frozen index, deriving the index from the
live queue so the N / M counter and prev/next neighbours stay correct when the playlist
changes underneath (e.g. an item removed in another tab) without disrupting playback of
the current video. Refetch the playlist list/detail on window focus so such changes flow
in, updating the player's queue length in near-real-time.
2026-06-15 16:27:28 +02:00
npeter83
bd085fc88f feat(playlists): queue playback in the player (auto-advance + prev/next)
PlayerModal now accepts an optional queue + startIndex. The active item drives the
player; it recreates per item (reusing the single-video resume / auto-watch / progress
logic), auto-advances to the next item when one ends, and shows Previous / Next controls
with an N / M indicator. The Playlists page passes the playlist as the queue from Play all
or a clicked row. Trilingual previous/next strings.
2026-06-15 16:11:37 +02:00
npeter83
2f66196816 feat(playlists): unify Saved into a built-in Watch later playlist
The old per-video status='saved' becomes membership in a built-in, undeletable
'watch_later' playlist. Migration 0012 moves existing saved videos into each user's
Watch later list and demotes the states to 'new'. The feed/playlist serializers now
expose a 'saved' boolean (EXISTS in watch_later); the card bookmark toggles watch_later
via new /api/playlists/watch-later add/remove endpoints (create-on-demand) instead of
setting a status. Removed the 'saved' show-filter and status. Watch later shows a
localized name and hides rename/delete in the Playlists page and add-to-playlist popover.
2026-06-15 15:33:53 +02:00
npeter83
26e72d5d00 fix(playlists): correctly clear/reselect after deleting a playlist
The post-delete auto-select effect re-picked the just-deleted id from the still-stale
playlists cache, so its detail lingered. Select the next remaining playlist directly on
delete (or null), drop the deleted detail from the cache, and make the effect re-validate
the selection against the current list (clear when empty, reselect when the current id is
gone). Also fix the header title showing "Channel manager" on the Playlists page.
2026-06-15 15:15:56 +02:00
npeter83
8a82d56950 feat(ui): reusable app-styled confirm dialog, replacing window.confirm
Add a promise-based ConfirmProvider + useConfirm() hook (built on the Modal shell,
liquid-glass styling, danger variant, Esc/backdrop = cancel, Enter = confirm) so
confirmations match the app instead of the native browser dialog. Wire it in at the
app root and replace both window.confirm call sites (playlist delete, channel
unsubscribe). Trilingual common.confirm/confirmTitle strings.
2026-06-15 15:06:47 +02:00
npeter83
201ec4c3fb fix(playlists): clear the detail panel after deleting the selected playlist
The detail pane rendered from react-query's cached data, so deleting the selected
playlist emptied the rail but left its stale contents on the right. Gate the detail
view on the current selection so it falls back to the empty state when nothing (or a
just-deleted playlist) is selected.
2026-06-15 14:56:39 +02:00
npeter83
37804ee393 feat(playlists): frontend foundation — page, add-to-playlist, nav
Add the Playlists page (left rail of playlists + detail with drag&drop reorder,
inline rename, one-step delete, remove item, Play all / row-click playback via the
existing PlayerModal) and an AddToPlaylist popover (portaled, multi-toggle +
inline new-playlist) wired into the VideoCard hover overlay and the PlayerModal.
New api client methods + Playlist types, a 'playlists' page route + account-menu
entry, and trilingual strings. Local only — YouTube sync comes in later phases.
2026-06-15 14:45:18 +02:00