Commit graph

384 commits

Author SHA1 Message Date
KhooLy
1e8f37633d Fix recent search selection 2026-07-11 14:56:02 +03:00
KhooLy
ceb991ebc1 Open imported Nuvio collection sources 2026-07-11 14:51:24 +03:00
KhooLy
d47e30fed6 Add anime-skip.com as a third skip-segment provider
Adds an opt-in provider alongside AniSkip and IntroDB, gated by a
user-supplied anime-skip.com Client ID (settings mirror the existing
IntroDB API key flow). Matches shows via AniList ID, fetches episode
timestamps over the anime-skip.com GraphQL API, and merges results
with the other providers through the existing dedup path.
2026-07-11 14:36:17 +03:00
KhooLy
13ead49812 Stop episode synopsis from expanding to full text on hover 2026-07-11 13:26:30 +03:00
KhooLy
e6565f8a5f Fix calendar date handling and expand calendar screen
readCalendarMonth was truncating nextEpisodeAirDate before using it as
the item's dateIso, losing the time component; now the full string is
kept for dateIso and only truncated for the id key.
2026-07-11 13:26:03 +03:00
KhooLy
45647bf4df Retry torrent playback on peer stall instead of failing after one 60s wait
Torrent playback used to give up after a single 60s wait for ready
peers. Now it retries up to 2 more times (15s first attempt, then the
remaining budget split across retries), showing a "retry N/M" status
so a slow initial peer connect doesn't sink the whole playback attempt.

Also preloads the content logo mid-playback when it wasn't already
available, tightens the first-frame-ready check to not fire while
pausedForCache, and drops a redundant buffering-percent line from the
loading overlay.
2026-07-11 13:25:54 +03:00
KhooLy
a271a2b78d Add optional trailer autoplay on the detail screen hero banner
Adds a settings toggle (with a configurable delay: 2/4/6/10s) to
autoplay the trailer over the hero background, with mute, progress,
fullscreen, and subtitle overlay controls. The subtitle cue parsing
(WebVTT/YouTube timedtext) and language selection previously private
to HeroSection.tsx move into a shared src/core/trailerSubtitles.ts so
the detail screen's hero can reuse the same logic.
2026-07-11 13:25:47 +03:00
KhooLy
da7f9ed34f Remember window size and position across restarts
Adds the tauri-plugin-window-state plugin so the app reopens at the
same size/position instead of always resetting to defaults.
2026-07-11 13:25:38 +03:00
KhooLy
8622fc9085 Make the offline banner app-wide instead of Nuvio-specific
No internet affects the whole app, not just Nuvio sync, and Nuvio
already has its own "servers unreachable" banner for real backend
outages. Split connectivity detection into a standalone
useOnlineStatus hook and OfflineBanner component, shown in place of
the Nuvio banner whenever the OS reports no network at all.
2026-07-11 13:23:44 +03:00
KhooLy
e7a4fb08cf Add a retry button for failed addon stream fetches to the Sources panel
Wires detail.failedAddons through to both the movie and episode source
panels with a manual retry action, so a permanently failed addon isn't
just invisible — the user can see it happened and try again without
reopening the whole detail screen.
2026-07-11 13:21:14 +03:00
KhooLy
7eb5bf16f6 Show trailing skeleton tiles instead of a pill while loading more folder items 2026-07-11 13:21:02 +03:00
KhooLy
adabdb2c9b Distinguish no-internet from Nuvio-down in the connectivity banner
The health check treated any failed request as "Nuvio unreachable",
even when the user's own internet was down. Track navigator.onLine
via online/offline events and show a separate neutral banner instead
of blaming Nuvio when there's no internet at all.
2026-07-11 13:20:15 +03:00
KhooLy
ba18dda017 Retry on HTTP errors and malformed JSON too, and surface addon failures to the UI
Retries previously only fired when the network request itself threw
(timeout/DNS/connection failure); an addon responding with a 5xx/429
status or a truncated/malformed body counted as "got a response" and
was never retried. Now those cases retry as well (up to 3 attempts for
stream requests, with a shorter timeout on the retries).

Addon failures that survive every retry are no longer silently
indistinguishable from "this addon genuinely has no streams" — they're
tracked per addon and exposed as detail.failedAddons so the UI can
show a distinct notice instead of just omitting the addon.
2026-07-11 13:19:09 +03:00
KhooLy
15cdbae110 Add pagination to the collection folder grid so Movies/Series tabs can load more than the first page 2026-07-11 13:17:32 +03:00
KhooLy
a9a4549306 Enlarge collection-load error text and icon to fill the empty grid space 2026-07-11 13:08:36 +03:00
KhooLy
42d3b2b479 Improve contrast on collection-load error text 2026-07-11 13:07:42 +03:00
KhooLy
66cf3be7b4 Show an error state instead of silently closing empty/failed collection folders 2026-07-11 13:06:42 +03:00
KhooLy
59985b1418 Stop player next-episode preload from writing into detail-screen state
loadStreams reused fetchDetailStreams' progressive-dispatch callback,
which sends detailStreamsAppended with no generation tag and bypasses
the staleness guard, merging into the same detail.streams/
availableAddons the Detail screen reads. loadStreams only ever
consumes the final aggregated array, so the progressive dispatch was
unused for it and just risked mixing another episode's addon results
into whatever the user is currently viewing.
2026-07-11 13:01:05 +03:00
KhooLy
fad9acb803 Add setting to control whether search suggestions open detail screen
Defaults off: clicking a suggestion now runs a full search across addons
like a normal search, unless the new toggle is enabled.
2026-07-11 12:56:14 +03:00
KhooLy
025733a3e9 Retry addon stream fetches once and lengthen timeouts to reduce dropped addons
Torrentio and similar addons were sometimes missing from stream results
because a single transient network blip or slow response past the
timeout permanently dropped that addon's results with no retry.
2026-07-11 12:52:16 +03:00
KhooLy
0dbf5ab7e0 Wire onDispatch through search results so poster context menu works
MovieCard's right-click context menu only renders when onDispatch is
passed; SearchScreen never forwarded it to SearchCategoryRow/MovieCard.
2026-07-11 04:25:54 +03:00
KhooLy
2ca4f5cf72 Tag detail-stream fetches with a generation to discard stale results
Pairs with fluxa-core ae2a662: passes the effect's generation into
fetchDetailStreams so its partial-result callback can tell the core
which episode selection it belongs to, letting the core drop appends
from an abandoned episode's still-in-flight addon queries.
2026-07-11 04:20:53 +03:00
KhooLy
4f0858ebdd Pass the target episode id through to next-episode stream selection
Threads the requested episode's id into coreSelectNextEpisodeStream so
the core can verify a candidate stream's title/filename actually
matches before selecting it, instead of trusting bingeGroup/list-order
alone (fluxa-core 403b413).
2026-07-11 04:20:45 +03:00
KhooLy
82f4848f13 Fix resume seek freezing video while audio keeps playing
Applying the resume position via loadfile's start= option seeked
before mpv had indexed the stream's keyframes, landing the video
decoder in a bad spot while audio (no keyframe dependency) kept
advancing. Load at 0 and issue a real runtime seek once playback
actually restarts instead, same as a manual seekbar click. Also
expose a "resuming" status flag so the loading overlay stays up
through the whole seek instead of dismissing at the wrong restart
event and exposing the mid-seek frame directly to the user.
2026-07-11 04:19:07 +03:00
KhooLy
0a648979a4 Fix next-episode transitions getting stuck behind the loading overlay
firstFrameFiredRef never reset between episodes, so the loading
overlay's dismiss path was permanently disabled after the first
episode played. Also await mpv's stop command before tearing down
the previous episode's torrent session, and keep meta.videos in
sync with the background-fetched episode list so the next-episode
and episode-panel fallbacks don't read a stale/empty list.
2026-07-11 04:18:52 +03:00
KhooLy
55b7562fae Fix Continue Watching rows blanking out name/episode name on partial refresh
Progress saves land in two steps: an immediate save with just lastVideoId
and season/episode, then a follow-up save once episode title/show name
metadata resolves. If a Continue Watching refresh landed between those two
saves, mergeContinueWatching would replace the row wholesale with the
name-less version and it stayed that way until another refresh happened to
fire. Backfill name/lastEpisodeName from the previous item when the
incoming one is missing them.
2026-07-11 04:16:14 +03:00
KhooLy
f0e780508b Fix calendar never showing upcoming episodes for local watchlist/continue-watching items
readCalendarMonth built localItems by calling coreCalendarItemsFromMeta on
each raw watchlist/continueWatching item, but that Rust function only
produces entries from a meta.videos array embedded in the item -- nothing
in the codebase ever stores a videos array on a library item. The actual
upcoming-episode data lives in item.nextEpisodeAirDate, populated by
refreshWatchlistAirDates, but readCalendarMonth never read that field.
This meant localItems was silently empty for every user regardless of
where the item came from (local, Trakt, Simkl, Stremio, Nuvio, etc.),
even once air dates were correctly fetched.

Build localItems directly from nextEpisodeAirDate instead.
2026-07-11 03:49:09 +03:00
KhooLy
af2c6dad7a Add Simkl and AniList calendar support alongside Trakt
Simkl exposes the same calendar/shows + calendar/movies personal
endpoints Trakt does; AniList's existing MediaListCollection query now
also asks for nextAiringEpisode. refreshExternalCalendarItems merges
whichever of the three the user has connected into
lib.externalCalendarItems.

Stremio and Nuvio don't have a calendar concept of their own — both
already merge their continue-watching/watchlist into lib.watchlist and
lib.continueWatching directly, so those items already flow through the
existing local addon-based air-date path without extra wiring.
2026-07-11 03:11:03 +03:00
KhooLy
98720bec1d Populate calendar with Trakt upcoming episodes and movie releases
Calendar's externalItems slot existed in the data model and UI but was
never fed by anything — Trakt sync only mirrored watchlist/watched/
progress, never queried Trakt's calendars/my/shows and calendars/my/movies
endpoints. Fetch those on calendar load and store into
lib.externalCalendarItems, which the screen already renders.
2026-07-11 02:51:16 +03:00
KhooLy
18c99a66e2 Fix Discover catalog dropdown going empty on Movie/Series switch
discover.catalogs held whatever type the last fetch returned, so
switching content type raced the async refetch: the auto-select
effect could latch onto a stale catalog key from the previous type,
which then matched nothing once the real catalogs arrived. Filter
catalogs by the current contentType at the source so a mismatched
entry can never be selected.

Adds a Vitest + RTL harness (none existed) to drive the real
DiscoverScreen through the exact race condition.
2026-07-11 02:44:16 +03:00
KhooLy
353f82de26 Fix season dropdown reverting selection after change
Changing season cleared selectedEpisode, which caused the episode-plan
refetch to fall back to lastVideoId (last-watched episode) and silently
reset selectedSeason to that episode's season once the async plan
resolved.
2026-07-11 02:37:23 +03:00
KhooLy
3c23a6ca3c Fix invisible toggle thumb when accent color is white
The collection editor's Toggle used a fixed white thumb, which
disappeared against the on-state track when using the default
white accent color.
2026-07-11 02:27:05 +03:00
KhooLy
ec708d6e04 Default movie detail screen to Details tab instead of Similar Titles
The modern tabbed detail layout initialized activeTab to 'related' for
non-series items, so opening a movie's detail screen landed on Similar
Titles instead of the overview/details content.
2026-07-11 02:23:04 +03:00
KhooLy
9b7127c2d8 Guard search suggestion ranking against addons missing item name
Fixes JAVASCRIPT-REACT-C
2026-07-11 02:21:07 +03:00
KhooLy
0a229970c2 Fix Windows display refresh build 2026-07-11 01:11:29 +03:00
KhooLy
d6d2329213 Fix Windows vcpkg cache 2026-07-11 00:42:27 +03:00
KhooLy
726877bd82 Bump version to 0.1.26 2026-07-11 00:38:23 +03:00
KhooLy
c85172b7db Optimize home screen refresh 2026-07-10 23:56:57 +03:00
KhooLy
51ddec8495 Add Anime4K mode shortcuts 2026-07-10 23:48:12 +03:00
KhooLy
1a3554a39a Fix continue watching refresh consistency 2026-07-10 23:48:05 +03:00
KhooLy
ff99430262 Add in-player subtitle styling and auto sync 2026-07-10 23:23:51 +03:00
KhooLy
47d5173f29 Fix Anime4K chain portability and restore upscaler WHEN gates
Restore the //!WHEN OUTPUT > 1.2x gates in Upscale_CNN_x2_S/M/L: with
full restore/upscale/thin chains the native-resolution effect comes
from Restore/Thin, and the gates let the upscale stages self-disable
at 1:1 instead of force-upscaling and downscaling back.

Join chain paths with ';' on Windows (mpv's path list separator there;
':' would also split drive letters). Replace cscale=ewa_lanczossoft
with ewa_lanczos — gpu-next has no libplacebo analog for lanczossoft
and was silently falling back.

Verified all three chains against the bundled libmpv: no shader or
scaler mapping errors; visible pixel diffs at 2x upscale and, via
Restore/Thin only, at 1:1 native resolution.
2026-07-10 22:47:36 +03:00
KhooLy
b214cad9fd Replace single Anime4K shader with full restore/upscale/thin chains
The bare Upscale_CNN shader only did anything when the output was
larger than the input, so toggling Anime4K at native resolution
looked like a no-op. Each quality tier now runs Clamp_Highlights ->
Restore -> Upscale -> AutoDownscalePre -> Upscale -> Thin, matching
the standard Anime4K mode presets, so restore/thin stages are visible
even at 1:1 while the downscale/second-upscale stages self-disable
via their WHEN gates when there's no resolution headroom.
2026-07-10 22:42:24 +03:00
KhooLy
884e5844ae Fix Anime4K toggling and frame interpolation
Frame interpolation could never engage: vo_libmpv answers no
VOCTRL_GET_DISPLAY_FPS and vsync estimation only accumulates once
display-sync is already active, so with the render API
video-sync=display-resample silently reverts unless the client sets
display-fps-override. Set a 60 FPS baseline at renderer init and
override it with the real monitor refresh rate (GDK monitor on Linux,
GetDeviceCaps VREFRESH on Windows); mpv refines it further from
report_swap timing. Turning interpolation off now also resets
video-sync back to audio.

Anime4K: drop the //!WHEN OUTPUT > 1.2x gates from the bundled shaders
(they made the shader a no-op whenever the window wasn't upscaling by
more than 1.2x) and deliver glsl-shaders changes via change-list
commands. Verified against the bundled libmpv fork with a headless
EGL harness: shader set/clr visibly changes rendered pixels and
display-sync-active flips to yes once an fps override exists.

player_init now creates the mpv renderer even when a native surface is
used, so the first session's player_apply_preferences no longer lands
on a missing renderer and gets dropped. Async mpv command failures are
logged from MPV_EVENT_COMMAND_REPLY instead of vanishing.
2026-07-10 22:21:50 +03:00
KhooLy
48e1cb56e5 Delete torrent-cache when a stream stops and on startup
Downloaded torrent pieces/files were written to the app data dir and
never removed, so every torrent ever streamed accumulated on disk
forever (users reported multi-GB AppData folders). torrent-cache is a
transient streaming scratch buffer with no other consumer, so wipe it
whenever no stream is active and sweep it again at app launch to catch
anything left behind by a crash or force-quit.
2026-07-10 21:50:56 +03:00
KhooLy
de136e06e0 Fix Windows window restoration 2026-07-10 20:33:08 +03:00
KhooLy
f9675693ef Preserve continue watching artwork on refresh 2026-07-10 20:25:31 +03:00
KhooLy
4ddcc96cdf Fix stream provider filter rendering 2026-07-10 20:22:32 +03:00
KhooLy
15b1a59e85 Fix search history and stream source loading 2026-07-10 19:57:06 +03:00
KhooLy
78bf699371 Fix torrent buffering playback 2026-07-10 19:41:19 +03:00