mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-12 20:16:15 -08:00
ce18f41219b04e2e867bb04202f3bf07cd072fc2
59
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
626c6142f3 | fix(downloads): align episode identity contract | ||
|
|
907e5f5a28 | feat(downloads): define episode queue identity | ||
|
|
760099358b |
feat(downloads): redesign download manager (#1313)
* docs(downloads): specify manager MVP redesign * docs(downloads): plan manager MVP implementation * docs(downloads): tighten manager validation plan * fix(downloads): keep renderer download state global * fix(downloads): make active count accessible * feat(downloads): derive queue and library view model * test(downloads): close view model coverage gaps * fix(downloads): stabilize malformed view model data * refactor(downloads): isolate library navigation * fix(downloads): report library navigation failures * feat(downloads): add ready-to-watch library * feat(downloads): add active download queue * feat(downloads): finish manager MVP * docs(downloads): clarify detail-first offline behavior * docs(downloads): plan detail navigation follow-up * fix(downloads): open completed movies in details * test(downloads): cover pending series navigation * fix(downloads): honor the global cover size * fix(downloads): prefer local playback in shared details * fix(downloads): preserve external launch priority * fix(downloads): prefer local playback in Xtream details * test(downloads): cover offline detail journey * docs(downloads): document offline detail behavior * docs(downloads): format detail navigation plan * fix(downloads): open Stalker items in provider details * docs(downloads): clarify Stalker navigation fallback * fix(xtream): isolate reused detail identities * fix(xtream): ignore stale VOD positions * fix(downloads): keep offline Xtream playback available * docs(downloads): clarify provider playback availability * docs(downloads): design missing-file recovery * docs(downloads): plan missing-file recovery * feat(downloads): derive completed file availability * feat(downloads): recover missing completed files * feat(downloads): refresh missing local files * feat(downloads): separate missing files from ready media * feat(downloads): surface missing files for recovery * refactor(downloads): simplify ready cards * test(downloads): cover missing-file and series journeys * feat(downloads): finish missing-file recovery * docs(downloads): design offline detail views * docs(downloads): plan offline detail views * feat(downloads): persist offline metadata snapshots * fix(downloads): complete metadata snapshot bridge contract * feat(downloads): manage offline metadata snapshots * fix(downloads): harden metadata snapshot updates * fix(downloads): restrict snapshot artwork * fix(downloads): guard restart artwork URL * fix(downloads): refine artwork URL checks * feat(downloads): expose offline metadata updates * fix(downloads): keep metadata service change focused * fix(downloads): preserve metadata error conventions * feat(downloads): derive offline detail content * fix(downloads): preserve unknown episode coordinates * feat(downloads): add focused offline detail routes * fix(downloads): ignore fragments in shell route state * fix(downloads): normalize fragments before queries * feat(downloads): open ready cards in offline details * fix(downloads): use native disabled card styles * feat(downloads): enrich offline detail metadata * fix(downloads): harden offline metadata resolution * fix(downloads): preserve stalker provider titles * fix(downloads): distinguish stalker metadata seeds * fix(downloads): stabilize offline metadata refresh * fix(downloads): throttle sparse metadata refreshes * fix(downloads): type metadata language settings * feat(downloads): render offline movie and series details * fix(downloads): harden offline detail interactions * fix(downloads): close offline detail edge cases * feat(downloads): hand off to provider-only details * fix(downloads): preserve stalker provider handoff * feat(downloads): capture metadata at download time * fix(downloads): preserve snapshot source semantics * fix(downloads): preserve episode snapshot identity * docs(downloads): document offline details flow * docs(downloads): clarify stalker provider fallback * test(downloads): cover offline detail journeys * test(downloads): stabilize offline detail selectors * style(downloads): format changed files * docs(downloads): clean design spec formatting * fix(downloads): preserve offline library ownership * test(downloads): fix Windows workspace navigation * test(database): preserve Electron tsconfig resolution * perf(downloads): avoid blocking file availability probes |
||
|
|
46c7713841 |
fix(ui): preserve EPG in narrow channel rows (#1312)
Preserve current-program context and enabled actions in narrow channel rows while aligning loaded rows, skeletons, and virtual-scroll geometry across M3U, Xtream, Stalker, Favorites, and Recent views. |
||
|
|
2ac0de752f |
fix(skills): align repository guidance with implementation (#1315)
* docs(skills): design implementation synchronization * docs(skills): plan implementation synchronization * fix(release): filter internal notes from public body * docs(release): synchronize release workflow guidance * fix(stalker): normalize catalog series flags * fix(stalker): preserve progress with scoped episode IDs * fix(playback): expose strict position persistence * docs(stalker): record series position compatibility * test(skills): validate repository skill contracts * fix(database): keep SQL trace values private * docs(skills): refresh Nx and SQLite ownership * docs(skills): align provider and UI guidance * docs(skills): tighten validated guidance * docs(release): require exact release pushes * style(electron): remove trailing blank line * fix(ci): classify repository skills coverage |
||
|
|
063662028a |
feat(portals): find the same movie in your other playlists (#1286)
* feat(portals): find the same movie in your other playlists A movie that exists in several imported Xtream playlists now shows a "Sources N" chip on its detail page and in the player. Switching playlist mid-film keeps the timecode, a preferred source can be pinned per movie, and a failed stream offers the alternatives instead of a dead end. The governing rule is that a guess is never presented as a fact. Every metadata value carries where it came from — `api` (the provider said so), `parsed` (inferred from the title) or `probe` (we contacted the stream). Facts render as plain tags, guesses are prefixed `~` in a warning colour, and an unknown value renders no tag at all plus a "check" affordance. Ranking and failover read through `factualOnly()`, so a filename claiming 4K is structurally unable to outrank a source that was actually reached. A probe that could not complete reports "unknown", never "unavailable". Scope is deliberately narrow: Xtream to Xtream, movies only, Electron only. Stalker never reaches the `content` table and M3U is a JSON blob whose search forces live content; both are additive later, since the candidate type already carries all three portal kinds. In the PWA every entry point is gated off and the chip renders nothing. Auto-failover is opt-in and off by default. Each source is tried at most once per session, so it terminates structurally, and the switch is never silent — the toast names the new playlist, offers an undo, and warns that the dub may differ only when both sides state an audio track as fact. Notable details: - Playlist names are routinely the pasted URL, credentials included. They are never rendered raw; a short host-only label is derived instead. - Quality is derived from pixel width, not height: a 2.39:1 1080p master is 1920x800, and bucketing that by height would publish "720p" as a fact. - Switching is a single `inlinePlayback.set()` so the player and engine survive and re-seek; the carried position is read before the 15s persistence throttle so it does not rewind. - Sources from one playlist collapse into a group, since the same film often appears there several times under different stream ids. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(portals): stop stale source resolutions from committing Addresses three defects Greptile found in the multi-source review. **Concurrent switches committed out of order.** Selecting a second source before the first resolution returned let the slower request overwrite the newer selection and repoint Undo at itself. `switchTo` now takes a sequence number and drops its result if a newer switch already committed. **Stale switches crossed movie sessions.** Navigating to another film while a resolution was in flight let the continuation activate the old film's source inside the new controller — and restart it from that session's zero resume position. The controller is now snapshotted per operation and the movie session is revalidated after every await. `check()` had the same hazard across its two awaits and is guarded the same way. **Short titles skipped discovery entirely.** The trigram tokenizer cannot index tokens under three characters, so "Up", "It" or "Us" produced an empty MATCH expression and the query was discarded before SQLite was consulted — the chip could never appear for those films. Discovery now falls back to a bounded scan when FTS structurally cannot serve the title; the existing two-tier normalized confirmation still rejects loose hits like "Upgrade". Each fix carries a regression test; all three were mutation-checked by removing the guard and confirming exactly those tests fail. The previous test asserting that short titles return nothing encoded the bug and has been replaced. The host spec passed 400 lines, so its fixtures moved to a shared module and the race suite into its own file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(portals): make the pin decide playback and keep failover going Second round of Greptile review findings. **A pin had no behavioural effect.** Loading a stored pin only decorated the row: Play still started the route's playlist and failover ranking ignored `isPinned`, so "make this the main source" survived a restart as an icon and nothing else. The primary action now starts from the pinned source when one is set, and the pin outranks everything else in failover ranking. **Failover stopped at the first unresolvable candidate.** An expired account or a failing `get_vod_info` on the top-ranked source ended the attempt, and since production calls `failover()` only once — on the original playback failure — a healthy lower-ranked source was never reached. It now continues through untried candidates. `switchTo` reports why it stopped so the loop can tell "could not resolve, try the next one" from "something newer owns the screen"; without that distinction a superseded switch would have spun forever, because only the former marks the candidate tried. **Identity ignored enrichment.** The key was `playlistId:contentId:title`, so when `get_vod_info` added a TMDB id and release year to an unchanged title the host saw no change, never reloaded, and kept yearless discovery and title-only pin keys — a `tmdb:`-keyed pin could never be found. The key now covers every field that affects matching. **A server refusing HEAD read as unavailable.** Some stream hosts answer 405 or 501 to HEAD yet serve the media over GET. The probe now retries once with the ranged GET the main process already supported, instead of caching a working source as failed and penalising it during failover. Greptile also flagged a missing token check after the resolve await in `switchTo`; that guard landed in |
||
|
|
80af9257a0 |
refactor(portals): share external-button and position-writer logic (#1298)
The Xtream and Stalker VOD detail views each carried a private copy of two behaviours: deriving the Play/Stop button state from the active external (MPV/VLC) session, and throttled persistence of the inline player position. A Play button or a resume point that behaves differently per portal is the kind of divergence users notice, so both now read from one implementation. Extracts `createExternalPlaybackButtonState` and `createInlinePlaybackPositionWriter` into portal/shared/util, and lifts the Stalker VOD download errand into its own helper. Behaviour is unchanged; the shared helpers are deliberately identical to the copies they replace. This also brings both hosts back under the 400-line ESLint limit, neither of which was baselined: vod-details.component.ts 389 -> 333 stalker-catalog-detail.component 394 -> 325 vod-details-playback.service.ts 345 -> 275 Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
9885178f32 |
fix(stalker): refresh stale embedded-series snapshots from favorites and dashboard (#1253)
Favorites and recently-viewed rows store Stalker items as full JSON snapshots, so a vclub-style embedded series[] episode list froze at the moment the row was written: a series favorited when only episode 1 was out kept showing one episode forever when opened from favorites, recents, Continue Watching, or any dashboard rail. New withStalkerSnapshotRefresh() store feature renders the stored snapshot immediately and re-fetches the item from the portal in the background via a title search (get_ordered_list&type=vod&search=..., matched by id, paginated up to 5 pages, wildcard-category retry), patching fresh episodes and cmd into the active selection. The patch is guarded on both the item id and the active playlist id, since Stalker ids are only unique per portal. Only the in-memory selection is patched — the stored snapshot row is deliberately left alone, because every entry path into the detail view runs this refresh and writing it back would add an uncontrolled background writer to the whole-playlist read-modify-write that every favorite/recent mutation performs. Also fixes the stalker-mock-server embedded-series scenario, which generated series[] as objects the app's vclub adapters filter out instead of the episode-number arrays real portals send. Regular type=series and Ministra is_series items are unaffected; Xtream is unaffected (get_series_info is never cached). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
5cae310430 |
fix(logging): redact sensitive portal and Electron diagnostics (#1182)
* fix: redact sensitive log data * fix(ci): keep logging preload self-contained * fix(logging): preserve shared diagnostics * fix(logging): close trace redaction gaps * fix(logging): redact Xtream path credentials * fix(logging): close credential redaction gaps * fix(logging): suppress external player arguments * fix(logging): harden URL and date redaction * fix(logging): redact map keys and URL fragments * fix(logging): redact sensitive map values * fix(logging): redact credentials in diagnostic text * fix(logging): close remaining credential leaks |
||
|
|
2f8aee72df |
feat(xtream): add catch-up playback to favorites and recent tabs (#1166)
Enables Xtream catch-up/timeshift from the Favorites and Recent surfaces (per-playlist and global), not just Live TV, and adds start-over replay of the currently-airing programme. Carries tv_archive/tv_archive_duration through the favorites and recently-viewed DB projections and maps them onto UnifiedCollectionItem; tv_archive_duration is interpreted as days, matching live-stream-layout.controlledArchiveDays. Closes #1138. Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
643dee1be3 |
feat(xtream): resume the latest series episode (#1187)
Dashboard Continue Watching now carries the exact saved season/episode into Xtream series details and starts it at the persisted offset. Successful external MPV/VLC launches persist the launched episode and retarget the series CTA to "Play episode N". Recent-history rows keyed by an episode id resolve their parent series before navigation. Includes maintainer follow-ups: no zero-offset resume on failed position loads, seriesXtreamId-gated resume targets for legacy rows, and patch coverage raised from 76.7% to 93.9%. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ffc07146fe |
feat(xtream): sort and filter the VOD/series catalog by IMDb rating
Adds IMDb rating sort and minimum-rating filtering for Xtream VOD/series catalogs, consolidates refinement controls, and guards rating controls away from Live TV. |
||
|
|
676e8bb5da | refactor(runtime): gate downloads navigation by capability | ||
|
|
45ee1ac3e4 | refactor(portal-ui): use runtime capabilities | ||
|
|
4ab8915483 | chore(web): enable strict TypeScript mode | ||
|
|
67d512d44c |
Merge pull request #961 from 4gray/agent/pwa-provider-target-flow
fix(docker): exclude agent worktrees from build context |
||
|
|
b2909a1186 |
feat(workspace): add keyboard shortcuts help (#957)
* feat(workspace): add keyboard shortcuts help * style(workspace): polish keyboard shortcuts dialog * fix(workspace): address shortcuts review feedback * docs(workspace): clarify desktop shortcut availability * refactor(workspace): split keyboard shortcut definitions |
||
|
|
6829c667bd | fix(pwa): restore xtream rail and vod navigation | ||
|
|
20e7322353 | refactor(portal): split collection data access (#953) | ||
|
|
118d4fce32 |
fix(playback): improve inline stream diagnostics (#952)
* fix(playback): improve inline stream diagnostics * fix(playback): preserve headers in diagnostics wrapper * fix(portal): align unified live player imports |
||
|
|
d24c77a143 | chore(nx): enforce scoped workspace boundaries (#942) | ||
|
|
8232a86a1e |
feat(portal): add category sorting controls (#940)
* feat(portal): add category sort modes * fix(portal): address category sort review feedback |
||
|
|
9ae984ad7f |
feat(portal): add series quick start CTA (#925)
* feat(portal): add series quick start CTA Entire-Checkpoint: f957cd9849e0 * fix(portal): address series quick start review Entire-Checkpoint: f957cd9849e0 * docs: use repo-relative quick start path Entire-Checkpoint: f957cd9849e0 |
||
|
|
a33d506266 |
fix(stalker): play radio collections with audio layout (#930)
* fix(stalker): play radio collections with audio layout * fix(stalker): address radio review feedback |
||
|
|
6ae1251ad1 |
fix(playback): use inline player for collection VOD (#928)
* feat(portal): add series quick start CTA Entire-Checkpoint: f957cd9849e0 * fix(playback): use inline player for collection vod * fix(playback): address inline collection review feedback * fix(playback): ignore stale vod position loads |
||
|
|
6305dcf00e |
Add browser playback diagnostics and MPV/VLC fallback (#921)
* feat(playback): add codec diagnostics fallback Entire-Checkpoint: f957cd9849e0 * fix(playback): address diagnostics review feedback Entire-Checkpoint: f957cd9849e0 * fix(playback): ignore recoverable hls diagnostics Entire-Checkpoint: f957cd9849e0 * fix(playback): polish diagnostic fallback banner Entire-Checkpoint: f957cd9849e0 * fix(xtream): preserve live category search scope Entire-Checkpoint: f957cd9849e0 |
||
|
|
724e4b1ab3 |
feat(playback): add embedded mpv (macos) stream recording (#916)
* feat(playback): add embedded mpv stream recording Entire-Checkpoint: f957cd9849e0 * fix(playback): address embedded mpv recording review Entire-Checkpoint: f957cd9849e0 * fix(playback): track mpv recording auto-stop replies Entire-Checkpoint: f957cd9849e0 |
||
|
|
ab905af285 |
feat(stalker): add radio support
Entire-Checkpoint: f957cd9849e0 |
||
|
|
90cda8731c | test(portal-shared-util): mock double-click setting | ||
|
|
6cbf2a1cfb |
feat(m3u): add context menus to recent channels
Entire-Checkpoint: f957cd9849e0 |
||
|
|
008bafbaae |
fix(recently-viewed): persist clear-all for M3U and Stalker playlists
Batch removal fanned out per-item read-modify-write calls against the playlist's recentlyViewed JSON column via Promise.all, racing each other so only the last write persisted. Group non-Xtream items by playlistId and use a new removeFromPlaylistRecentlyViewedBatch helper that filters all identities in a single read-filter-write per playlist. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Entire-Checkpoint: f957cd9849e0 |
||
|
|
e36c953865 |
feat(sidebar): implement shared collapse state for live-TV sidebar across components
Entire-Checkpoint: f957cd9849e0 |
||
|
|
15b6ba985a |
feat(live-tv): collapsible sidebar in live tv views
Entire-Checkpoint: f957cd9849e0 |
||
|
|
39ddaa2f9c |
perf(recents): batch Xtream remove-recent-item into a single IPC call
Clearing all recents of a given content type fired N concurrent IPC calls, each opening its own implicit transaction in the recently_viewed table. For users with hundreds of recently-watched VOD/series rows this added real overhead even though the UI updates optimistically. Add a new DB_REMOVE_RECENT_ITEMS_BATCH path end-to-end: - removeRecentItemsBatch() Drizzle op: one transaction, one prepared statement reused per row - Wire through worker → IPC handler → preload → window.electron typings → DatabaseService - UnifiedRecentDataService.removeRecentItemsBatch() groups items by source. Xtream items go through the new batch IPC. M3U/Stalker items still go per-playlist because they update a JSON column on the playlist row, not the recently_viewed table — but they now run in parallel with the Xtream batch via a single Promise.all. - Single call site updated: unified-collection-page "Clear all of type" confirmation handler. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 4bfb62f988b7 |
||
|
|
290843ef3f |
fix: restore recent live favorite toggles
Entire-Checkpoint: c2cea9c530e6 |
||
|
|
20445beaf0 |
fix(downloads): show loading skeletons before empty states
Entire-Checkpoint: c2cea9c530e6 |
||
|
|
0babd92304 |
feat: add live epg panel to collections
Entire-Checkpoint: c2cea9c530e6 |
||
|
|
51347fc226 |
feat: add collapsible live epg panel
Entire-Checkpoint: 0518c49b948d |
||
|
|
7caa18308d |
feat: enhance unified collection with workspace commands and backdrop handling
- Added WorkspaceViewCommandService to UnifiedCollectionPageComponent for workspace layout commands. - Implemented clear current view command for favorites and recent items. - Updated unified favorites data service to use buildXtreamCollectionUid for UID generation. - Enhanced unified recent data service to normalize timestamps and handle backdrop URLs. - Introduced withRecentItems feature to manage recent item additions with backdrop support. - Updated VodDetailsRouteComponent and SerialDetailsComponent to backfill content backdrops. - Modified IXtreamDataSource interface to include backdrop URL handling for favorites and recent items. - Added tests for recent items feature to ensure correct functionality and backdrop handling. |
||
|
|
8d6a387a9f | feat: add workspace view command service and related types | ||
|
|
3f79b01a9d |
feat: implement bulk clear favorites functionality with confirmation dialog
Entire-Checkpoint: c6e522b4276c |
||
|
|
4c6e65be9b |
feat: implement favorites channel sorting functionality and UI updates
Entire-Checkpoint: c6e522b4276c |
||
|
|
5e41e3d1ce |
refactor(favs-recent): adapt UI and routing behavior
- Introduced StalkerCollectionDetailComponent to handle detailed views for Stalker collections. - Added XtreamCollectionDetailComponent for managing Xtream collection details. - Updated routing components to integrate new detail components for both Stalker and Xtream. - Enhanced global favorites and recently viewed functionalities to support new detail navigation for Stalker and Xtream items. - Improved styling and structure for better responsiveness and user experience in detail views. Entire-Checkpoint: c6e522b4276c |
||
|
|
a8aa289735 | feat(groups): implement channel sorting functionality with UI controls | ||
|
|
03eadb2ba6 |
feat: enhance audio player and video player for radio support
- Updated video player component to conditionally render audio player for radio channels. - Added radio-specific styles to video player and unified live tab components. - Introduced new layout classes for radio and external players. - Enhanced audio player component with improved UI and volume controls. - Implemented logic to preserve radio flag in M3U playback details. - Updated tests to cover new radio functionality and ensure proper rendering. |
||
|
|
5a070f5550 | feat: enhance routing with reactive route parameter signals and update catalog facade for search query handling | ||
|
|
d22515657d | feat: enhance EPG handling and improve component tests for live streams | ||
|
|
91cd650c1a |
feat: enhance EPG and portal features with error suppression and status resolution
- Added suppressErrorLog option to EPG API calls in withEpg feature. - Introduced resolvePortalStatus function to streamline portal status checks in withPortal feature. - Updated checkPortalStatus to return PortalStatusType instead of void. - Enhanced XtreamStore to preserve cancelled content initialization block. - Expanded XtreamState to include contentInitBlockReason for better state management. - Added XtreamContentGateComponent to manage content initialization states. - Implemented tests for XtreamContentGateComponent to ensure correct rendering based on contentInitBlockReason. - Created PlaylistRefreshService to handle playlist refresh operations and events. - Introduced new IPC commands for playlist refresh functionality. - Added interfaces for playlist refresh events and payloads to improve type safety. |
||
|
|
04b0dd38e3 |
feat(portal-rail-links): update icons for M3U playlist links
feat(portal-activity-item): add PortalAddedItem interface for recently-added catalog items |
||
|
|
5f6ae5c743 |
feat: add unit tests for UnifiedLiveTabComponent and UnifiedRecentDataService
- Implemented comprehensive unit tests for UnifiedLiveTabComponent to validate rendering and playback functionality. - Created unit tests for UnifiedRecentDataService to ensure proper handling of recent items and playback recording. - Enhanced the UnifiedRecentDataService with improved methods for managing M3U and Stalker recent items. - Introduced new utility functions for extracting and normalizing data related to recent items. |