Commit Graph

14 Commits

Author SHA1 Message Date
Simon
d7086ead27 Play favorites from freshly resolved formats, not the page URL
Streaming a page URL makes /api/stream re-run yt-dlp on every request --
slow, and a 500 on some sites -- so the player and the reels feed now
wait for App.videos.ensureFormats() when an item has no formats
(favorites, or a card clicked before its hover-resolve landed) and play a
real media URL with the extractor's headers, the same path a hovered card
takes. Favorites' download does the same. The page URL survives only as a
last resort when resolution yields nothing.

Two things in the proxy kept this site broken either way:

heavyfetish serves media from paths with a trailing slash
(/get_file/.../11097_720p.mp4/), which missed every extension test in
stream_video and sent even a resolved media URL down the yt-dlp branch --
a full extraction per request, including every seek.

Its CDN (st17.heavyfetish.com) also serves a certificate that expired
2026-02-16, so the upstream fetch failed verification and returned 500.
A browser can't play such a host at all, which is much of why this proxy
exists, so impersonate_get() now retries once without verification, logs
it, and remembers the host so the doomed handshake isn't repeated for
every range request. STREAM_TLS_VERIFY_ONLY=1 restores the hard failure.

Verified in headless Chrome against the real site: a favorite holding
only the page URL now resolves, streams (206, video/mp4, duration
3167.8s, readyState 4, no error) and shows "720p mp4 | 480p mp4" in the
quality menu.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QBDkEXP4htyXTCZUwMLphd
2026-09-05 14:26:15 +00:00
Simon
25dad88ed9 Fix expiring favorites, empty quality menus, rotation scroll jumps
Favorites persisted the *resolved* stream metadata (resolveAndProbe
mutates video.meta with yt-dlp's CDN format URLs), so a favorite opened
the next day replayed a dead link. They now store only the page URL and
identifying fields, and ignore any stale meta left in localStorage --
playback, download and info re-resolve through the backend, which
resolves a page URL live in /api/stream.

That left the quality switcher empty for anything not yet resolved
(favorites, cards clicked before their hover-resolve landed, feed
slides), so App.videos.ensureFormats now resolves formats once per
session -- cached by video id rather than per object, so any object
describing the same video gets them -- and both the player and the reels
feed rebuild their format menu when they arrive. Playback isn't blocked:
it already starts from the page URL via the proxy.

Rotating a phone also jumped the grid to a completely different place:
the anchor was read inside the resize handler (by which point the
browser has already moved the scroll) and asserted once, and every
re-pack discarded known card heights for the 16:9 placeholder estimate.
The virtualizer now tracks the anchor on every scroll pass, re-asserts
it across a short settling window (ending early on a real gesture), and
remembers each thumbnail's true aspect ratio so a re-pack places cards
at their real heights. Verified in headless Chrome across a
portrait/landscape/portrait cycle: visible videos 37-39 -> 36-40 ->
36-38, against 37-39 -> 34-37 -> 29-30 before.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QBDkEXP4htyXTCZUwMLphd
2026-09-05 14:07:56 +00:00
Simon
b6b17b1f52 "Open in new tab" 2026-07-06 15:32:31 +00:00
Simon
7207e36510 Replace video player with a fully custom fake-fullscreen HUD
Single fullscreen player state everywhere (desktop/Android/iOS/feed) instead
of the old modal-vs-native-fullscreen split, with custom controls: draggable
timeline with buffered range, dynamically-escalating skip buttons (double-tap
zones too), per-video format switching, favorites, PiP with auto-PiP on
backgrounding, volume swipe, TikTok-style HUD auto-hide, and swipe-down/
back-button/close-button dismissal. Reels feed reuses the same skip/format/
PiP logic via the new customPlayer.js shared module.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 19:08:21 +00:00
Simon
138c3224de Add modern UI enhancements over the classic redesign
Layered progressive polish on the warm classic + brass theme:
- Card entrance animation on first mount (virtualizer-aware)
- Cursor-tracking brass spotlight border on cards
- Thumbnail skeleton shimmer until the poster paints
- Hover video preview after a short dwell (only when formats resolved)
- View Transition + blurred-poster ambient backdrop on player open
- Favorite heart pop + expanding ring on add
- ⌘K command palette (search, theme, density, reels, source/channel)
- Scroll-progress bar + back-to-top FAB
- Grid density toggle (comfortable/compact)
- Reels HUD: serif title, brass scrubber, muted-state pulse

All new motion respects prefers-reduced-motion; no JS/HTML structure
changes to the core grid/feed. New glue lives in frontend/js/enhance.js.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 08:25:37 +00:00
Simon
9fe7511b4d header bugfix 2026-06-24 20:08:08 +00:00
Simon
785b991d01 probe videos in background 2026-06-23 07:54:35 +00:00
Simon
a251b274db fallback of formats 2026-06-23 06:59:40 +00:00
Simon
b5b3e13dd0 live stream support 2026-06-22 12:34:47 +00:00
Simon
988e11b159 fix missing headers in video get requests 2026-06-18 11:55:08 +00:00
Simon
7ba8896405 fix player bug with apple mpegurl 2026-02-12 08:23:27 +00:00
Simon
1f5910a996 added loading indicator 2026-02-11 07:04:59 +00:00
Simon
d2e1e3adea honoring formats and http headers 2026-02-09 19:16:44 +00:00
Simon
ee1cb511df broke up monolithic structure 2026-02-09 13:27:08 +00:00