* fix(epg): wire catch-up Watch button in unified live tab, surface resolve failures
The favorites/recent live views (UnifiedLiveTabComponent) passed
archivePlaybackAvailable/archiveDays to the EPG timeline and list view, so
the "Watch" button and the dialog's "Watch from start" action rendered —
but neither (programActivated) nor (returnToLive) was bound. Clicking
Watch emitted an event nobody listened to: no error, no feedback, no
playback change.
- Handle programActivated in the unified live tab: resolve the catch-up
URL via resolveM3uCatchupUrl, swap the inline player's playback target
(or hand it to the configured external player), show the
"Archive playback" summary label, "From archive" block tag and
"Return to live"; clear the override on channel switch/close/return.
- Never fail silently: both the unified tab and the m3u-state effect now
show an EPG.TIMELINE.CATCHUP_FAILED snackbar when the replay URL can't
be resolved. New i18n key translated into all 17 locales via the
i18n-fill workflow.
- Extract the effect's resolve branch into a pure
resolveActiveEpgProgramAction util and the unified tab's EPG summary
helpers into unified-live-epg-summary.util.ts (component shrinks
598 → 572 lines despite the new feature).
- Regression coverage: 6 component tests for the catch-up flow,
3 unit tests for the resolver action; docs updated in
m3u-playlist-module.md.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(epg): address PR review — untrack progress tick in archive summary, open live external without prior timeshift
- liveEpgPanelSummary no longer tracks the 30s progressTick while an
archived programme is shown (Greptile P2): the archive summary is
frozen, so re-running the computed each tick only produced needless
re-renders.
- returnToLivePlayback no longer early-returns when no timeshift is
active (Codex P2): with an external player configured and
openStreamOnDoubleClick enabled, the programme dialog's "Watch live"
action now launches the external player instead of being dropped.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
fix(m3u): highlight active archive epg program
* Store the active archive EPG program with the resolved playback URL so the clicked M3U catch-up row stays highlighted during archive playback.
* Show archive playback state and return-to-live controls in the inline player panel.
* Hide duplicate EPG program rows that share the same time slot while keeping the richer provider entry.
iptv-playlist-parser statically imports the entire validator library
(~130KB across 113 files). Because PlaylistsService is eager (re-exported
through the 'services' barrel that AppComponent imports), validator was
landing in the cold-start preloaded chunk even though parse() only runs
on user-triggered playlist imports (FILE/URL/TEXT add).
Switch handlePlaylistParsing() to dynamic-import the parser. The two
callers (playlist-backup.service and the parsePlaylist$ NgRx effect)
needed minor adjustments — the effect now uses mergeMap(from(...)) to
flatten the Promise back into the action stream.
Cold-start preloaded chunk: 1511KB -> 1374KB (-9%).
Validator now sits in a separate ~129KB chunk that loads only when
the user adds a playlist.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 3ec205264762
- Implemented a loading state for channel lists in various components, enhancing user experience during data fetching.
- Added `ChannelListLoadingStateComponent` to display loading skeletons for channels and groups.
- Updated `M3uWorkspaceRouteSession` to manage loading states more effectively when fetching playlists.
- Modified `VideoPlayerComponent`, `SidebarComponent`, and `ChannelListContainerComponent` to utilize the new loading state.
- Enhanced tests to cover new loading behaviors and ensure proper dispatching of loading actions.
- 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.
- Updated the `selectFavorites` selector to filter favorites ensuring they are strings.
- Added new interfaces for `PortalActivityItem`, `PortalRecentItem`, and `PortalFavoriteItem` to standardize activity item representation.
- Introduced `StalkerPortalItem` interface to represent items in Stalker portals.
- Created utility functions for extracting and normalizing data from Stalker portal items.
- Refactored `DashboardDataService` to utilize new interfaces and utility functions for managing recent and favorite items.
- Removed deprecated mapping functions and replaced them with direct usage of new interfaces.
- Added navigation utilities for recent and favorite items to streamline routing logic.
- Consolidated SCSS styles for the live stream layout, reducing redundancy and improving maintainability.
- Introduced a new portal layout mixin for better structure.
- Enhanced sidebar and content container styles for improved user experience.
- Updated TypeScript component to utilize new styles and improve readability.
- Refactored channel list and recently viewed components for consistency in design.
- Optimized playlist service and store interactions for better performance.
- Added new translations for enhanced user interface clarity.
- Improved database schema with additional indexing for EPG programs.
- Add o_name (original title) field to Stalker VOD interfaces
- Prefer o_name over name in adapters and grid list display
- Add playback position tracking for Stalker VOD content
- Support resume playback from last position in vod-details
- Add real-time position updates via IPC listener
- Add progress indicators for Stalker VOD items in grid view
- Add debug logging for VOD series seasons resource
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move playlist reducers into a dedicated reducers module and re-export a
composed playlistReducer built from smaller reducer arrays (epg,
channel, playlist, favorites, filter). This extracts and organizes the
previously monolithic reducer implementation into focused reducer files,
improving modularity and maintainability.
Add simple selectors in the new reducers index for commonly accessed
pieces of PlaylistState (playlists, selected playlist id, epg availability,
active channel, current EPG program, channels list, playlists loaded flag,
current playlist id) so callers can import them from a single place.
These changes make reducer logic easier to reason about, enable
incremental testing and extension of individual reducer groups, and
centralize basic selectors for consistent usage across the app.
Add a new IPC handler_DELETE_ALL_PLAYLIST that removes all
and related data from the SQLite database in a safe order that respects
foreign key relationships. The handler deletes favorites and recently
viewed entries first, then content, categories, and finally playlists.
Errors are logged and propagated.
Expose the new operation in the renderer preload API as
dbDeleteAllPlaylists() to allow UI code to invoke the purge. This
provides a single-call way to clear playlists and their dependent
records for testing or user-driven reset.
Add title, user-agent, refer and origin fields to IPC payloads sent
when opening MPV/VLC players and when launching streams from effects.
Replace legacy userAgent property with standardized 'user-agent' key and
consistently include referer and origin from channel.http. This ensures
external players receive correct HTTP header metadata and stream titles
for proper request handling and display.
Update channel.model to import Channel from the local interface file
instead of the package namespace. This fixes an incorrect module
resolution and keeps the codebase consistent with local typings.
Add a new SidebarView union type ('CHANNELS' | 'PLAYLISTS') to expose
possible sidebar view options for consumers of the shared interfaces.