Add the sky theme across the frontend and backend theme APIs, including starfield assets and icon-only branding.
Refresh themed grid backgrounds, admin/login/sidebar styling, and theme-specific video/listing polish.
Add Unicom cloud drive support for source-file deletion and crawler uploads.
- Implement source-file removal for Unicom cloud drive so deleting videos can also remove the original cloud-drive file when requested.
- Resolve Unicom cloud drive source identifiers across file FID, object ID, directory ID, rename, and delete flows.
- Add upload support for Spider91 crawler imports targeting Unicom cloud drive storage.
- Add Unicom cloud drive QR login backend APIs, frontend form support, and tests.
- Extend drive capability metadata, scanner behavior, proxy handling, preview handling, and migration coverage for cloud-drive source operations.
- Rename Chinese display labels from 联通沃盘 to 联通网盘 and from 123 云盘 to 123网盘 while keeping the root README aligned with origin/main.
- Add referrer-policy coverage for 302 video playback and update related frontend playback tests.
VideoPlayer:
- Long-press the video for >=400ms to enter 2x playback rate; release/pause/leave/src change restores 1x
- Block native context menu, iOS long-press callout, and download UI on the player
Shorts page (/shorts) reachable from the main nav burger menu:
- Vertical scroll-snap feed (one video per 100svh slide)
- IntersectionObserver picks the active slide; only active +/- 1 mounts a real <video>
- Default muted autoplay with mute toggle; tap toggles play/pause
- Long-press 2x carries over from the detail player
- Per-slide TikTok-style scrub bar: hidden line by default, drag from the bottom hit area to seek with live MM:SS readout
- Auto-fullscreen on first user pointer (Android Chrome/Firefox/Edge); falls back gracefully on iOS Safari which doesn't support element-level Fullscreen API
- Body overflow lock + dynamic theme-color=#000 while on the page
- Like via double-tap or the heart action button; tap again on the heart to unlike, count synced with the existing detail-page likes
- Heart-burst animation; right-rail action stack ready for future buttons
Backend:
- POST /api/shorts/next: client posts { seenIds, count }, server returns up to N videos that aren't in seenIds, picked via SQLite ORDER BY RANDOM(); roundComplete=true tells client to clear local seen list and start a new round
- DELETE /api/video/:id/like: decrement likes (clamped at 0) for unlike
- catalog.RandomVideosExcluding / CountVisibleVideos / DecrementLike with unit tests
Misc:
- index.html viewport gains viewport-fit=cover for safe-area handling
- Add a global site-wide theme that switches between two palettes:
- dark + warm orange (existing visual, default)
- cream white + sakura pink (new, soft cream bg + pink accent +
deep mauve text + soft pink shadows)
- All colors live in tokens.css under [data-theme="dark"] and
[data-theme="pink"]; component CSS is unchanged
- Backend: persist theme in SQLite settings table (key=ui.theme),
expose via Admin Settings PUT/GET and a new public read-only
endpoint GET /api/settings/theme so the login page can pick up
the right theme before the user authenticates
- Frontend: inline script in index.html applies cached theme from
localStorage before React mounts to prevent first-paint flash;
main.tsx fires syncThemeFromServer() in parallel to align with
server value; theme.ts validates input and ignores unknown values
to be robust against an old backend not returning the theme field
- Admin: new /admin/theme page with two large preview cards (mini
page mock-ups locked to each palette via data-preview), Palette
icon entry in the sidebar; clicking a card applies locally first,
then PUTs to the backend with rollback on failure
- README + plan section 14.6 updated