Immersive fullscreen player, touch-device perf, and edge caching - #17
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
harusharu
force-pushed
the
feat/immersive-player-and-edge-caching
branch
from
August 20, 2026 06:19
1c037cf to
7f5ba79
Compare
The featured endpoint is the hottest route in the app — every home-screen
load hits it, and each hit previously re-fanned-out to every live provider
upstream. Two cache layers now absorb the load:
- An in-process single-flight TTL cache (60s) via cachedFetch so a burst
of users can't stampede the upstream provider sites; in-flight requests
share one upstream fetch.
- A CDN-friendly Cache-Control on the response
('public, max-age=30, s-maxage=60, stale-while-revalidate=300') so
Vercel's edge serves the same feed to most users without invoking the
function at all, and refreshes it in the background after expiry.
The artwork proxy route gains the same treatment with longer windows:
browsers keep the optimized bytes for a day while the CDN holds them for
a week (s-maxage=86400, stale-while-revalidate=604800), keeping
repeated loads entirely off the proxy since artwork rarely changes.
Scroll-linked transforms on a full-width, gradient-heavy layer are the #1 Android scroll-jank source, and backdrop-filter + infinite blur animations are nearly as bad on low-end phones. A new useIsFinePointer hook (matchMedia '(pointer: fine)') now gates the expensive effects: - Hero: the parallax wrapper (and its useScroll listener) is only mounted on fine pointers; touch devices render a static backdrop layer. Ambient orb drift, the Ken Burns settle, and the text shimmer are switched off via pointer-coarse:animate-none. - Backdrop blur chips/pills fall back to solid backgrounds (pointer-coarse:bg-background/80, no backdrop-blur) on touch. - Cards: the cursor spotlight, hover gradient scrim, and play chip skip pointer tracking entirely — a touch-drag no longer runs getBoundingClientRect + spring updates per move event. SSR assumes a fine pointer and the effect corrects before first scroll, so no hydration mismatch or flash.
Shrinks the dock's vertical stack so it sits lower on screen and reads more like a slim dash: icon circles go from 36px to 32px with proportionally smaller icons (size-4.5), button padding tightens (pt-1.5 pb-0.5, gap-0.5), the container padding and divider height follow, and the GitHub label is always visible instead of hidden on mobile. Touch targets stay well above the 44px floor thanks to the touch-target utility.
…y, and subtitles Redesigns playback as a pure immersive surface — the video fills the viewport on black with every control inside the stage, and the player best-effort enters fullscreen and locks landscape on open (silently falling back to the tab-fill layout where the browser disallows it). The old modal chrome (header, title row, side episode list) is gone; EpisodeList is deleted and the episode switcher now lives in the player as a searchable overlay panel. New in-video capabilities: - Settings panel with Quality / Speed / Audio / Subtitles tabs. Quality and Audio lead with hub-based entries derived from the movie's linkList — one entry per advertised resolution (480p/720p/1080p) or per audio language (multi-language WEB-DLs) — and fall back to manifest levels/tracks when the stream is a plain HLS rendition. Switching re-resolves the stream from that hub with failure memory, so a dead link is skipped on retry; the winning hub is matched against the original stream to preselect the active option. Original language is tagged and leads the Audio menu. - External caption registration: providers attach subtitle tracks (vtt/srt/ass/json) to stream sources; subtitleTracksFrom normalizes the wildly varying provider shapes and registers them as Vidstack text tracks, with a dedicated Subtitles shortcut button and no-stacking track switching. - Transport-cluster prev/next episode buttons (disabled at list boundaries) plus Shift+P / Shift+N keyboard shortcuts. - Safe-area aware top/bottom bars (env(safe-area-inset-*)) and a portrait rotate hint that auto-dismisses. Wiring and state: - App resolves and carries audioLanguages/hubQualities through the player/loading -> playing -> error cycle so menus stay populated while a switch is in flight, and re-derives them when a fallback hub takes over after sources are exhausted. - Reducer player states carry the new optional audio/quality fields. - DetailModal drops its old quality/season picker (superseded by the in-player settings) and gains dialog semantics: role=dialog, aria-modal, labelled by title, focus moved inside on open, Escape to close.
harusharu
force-pushed
the
feat/immersive-player-and-edge-caching
branch
from
August 20, 2026 06:24
7f5ba79 to
e3dafbe
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This branch carries the next wave of the streaming UI upgrade: playback becomes a true immersive surface, the home screen gets faster on touch devices, and the API's hottest endpoints stop hammering upstream providers.
What's included
1. Immersive fullscreen player (
feat(player))EpisodeListis deleted and episode switching lives in the player as an overlay panel.subtitleTracksFromand registered as Vidstack text tracks, with a dedicated Subtitles shortcut and no-stacking track switching.Shift+P/Shift+Nshortcuts.role="dialog", focus moved inside on open, Escape to close.2. Touch-device performance (
perf(ui))useIsFinePointerhook gates scroll-linked parallax, backdrop-filter, and infinite blur animations to fine pointers — the main Android scroll-jank sources are simply not mounted on touch.getBoundingClientRect+ spring updates per pointer-move during touch drags; spotlight/gradient/play-chip hover effects are hidden on coarse pointers.3. API edge caching (
perf(api))Cache-Control: public, max-age=30, s-maxage=60, stale-while-revalidate=300, so bursts of users share one upstream fetch and Vercel's edge serves most loads without invoking the function.s-maxage=86400, stale-while-revalidate=604800— browsers keep bytes for a day, the CDN for a week, keeping repeat loads off the proxy entirely.4. Slimmer dock (
ui(menu))Commits (grouped by concern)
perf(api)cache featured feed in-process and tune CDN cache headersperf(ui)drop parallax, blurs, and infinite animations on touch devicesui(menu)compact the horizontal dockfeat(player)immersive fullscreen player with in-video audio, quality, and subtitlesVerification
pnpm lint(biome) — cleanpnpm typecheck(tsc --noEmit) — clean