- 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>
- Added `VodDetailsRouteComponent` to handle VOD details with route parameters.
- Refactored existing `VodDetailsComponent` to use a unified structure for Xtream and Stalker portals.
- Enhanced VOD details display with normalized metadata and improved playback position handling.
- Integrated resizable sidebar functionality in main container and live stream layout components.
- Updated routing to use the new VOD details route component.
- Improved favorite toggling and download handling in VOD details.
- Adjusted styles for responsive sidebar and grid layouts.
Add comprehensive download functionality for Xtream and Stalker portals:
Backend (Electron):
- Add downloads table schema with foreign key to playlists
- Create downloads.events.ts with IPC handlers for download operations
- Support download start, cancel, retry, remove, and status queries
- Auto-create playlist entries for Stalker portals to satisfy FK constraints
- Add download folder selection and file reveal/play functionality
Frontend (Angular):
- Create DownloadsService with reactive signal-based state management
- Add DownloadsComponent with queue management UI
- Implement download buttons with three states: download, downloading, play local
- Support both Xtream and Stalker modes with proper playlist ID handling
- Add download progress indicators and status badges
UI Components:
- Update VodDetailsComponent with download/play-local buttons
- Update SeasonContainerComponent with episode download buttons
- Add navigation link to downloads page
- Style download buttons and progress indicators
Stalker Portal Support:
- Resolve stream URLs via fetchLinkToPlay API before downloading
- Handle both vod-series and regular-series episode types
- Use playlist._id for Stalker (vs portalId for Xtream)
- Pass playlist info for auto-creation in database
Translations:
- Add download-related strings for en, de, es, fr
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add resolved flag to prevent double resolution race condition
- Use regex to parse numeric values instead of fragile line filtering
- Centralize cleanup in done() helper for consistent handling
- Increase timeout to 2000ms to match MPV
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use manual time calculation instead of fragile toISOString().substr()
- Explicitly resolve null on MPV IPC timeout to prevent hanging promises
- Clear timeout handle in all event paths to prevent races
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Return unsubscribe function from onPlaybackPositionUpdate to ensure
only the specific listener is removed on destroy, preventing issues
with multiple store instances.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace custom environment-based dev detection with Electron's
built-in app.isPackaged check. Import the app module from Electron
and remove reliance on ELECTRON_IS_DEV and the environment file.
This simplifies logic, improves reliability of development vs
production detection, and reduces dependency on external env vars.
Add a new Electron smoke test suite using Playwright to verify the
packaged application starts, renders the main window, and exposes
expected window properties. The tests launch the built Electron main
bundle, locate the primary (non-DevTools) window, wait for DOM load,
and assert the title contains "IPTVnator". They also check window
visibility and bounds, validate rendered body content, and capture
screenshots to dist/test-results/electron-backend-e2e for debugging.
Include helpers to resolve project paths, ensure the screenshot
directory exists, and robustly find the main application window. Set
NODE_ENV and ELECTRON_IS_DEV to ensure the app loads built artifacts.
Add the ability to hide irrelevant or empty categories in Xtream playlists.
Users can now manage category visibility through a dialog accessible from
the sidebar header in both VOD/Series and Live TV views.
Features:
- New category management dialog with search filter and select/deselect all
- Visibility settings persisted to database per playlist
- Hidden categories are filtered from sidebar navigation
- New categories added during playlist refresh default to visible
- Database migration for existing installations
Files changed:
- Database: schema.ts, connection.ts (hidden column + migration)
- Backend: category.events.ts, main.preload.ts (IPC handlers)
- Frontend: new dialog component, store method, UI integration
- Translations: en.json
- Documentation: docs/architecture/category-management.md
Reorder imports and remove an unused duplicate to improve clarity and
consistency. Reformat multi-argument and long console/log calls,
return objects and function arguments across multiple lines to keep
within line width and improve readability. Update array/object
literals and error handling pushes to use consistent multi-line
formatting. These changes are purely stylistic and do not alter
behavior; they make the code easier to read and maintain.
Refactor stalker-series-view template to guard fields with conditionals
so that only available metadata is displayed. Replace selectedItem() with
displayItem() to use the updated selection accessor. Add checks for
director, actors, year/release date, genre/genres_str, imdb and kinopoisk
ratings to avoid showing empty labels.
Enhance stalker-portal-import component by adding reactive form fields
for serial/device IDs and signatures, importing MatProgressSpinnerModule,
and wiring TranslateService and StalkerSessionService into the component.
Include a small loading-container style. These changes prepare the UI for
improved import UX and safer rendering of optional series metadata.
Add tables, indexes, FTS5 virtual table, and triggers to support EPG
(electronic program guide) data in the shared SQLite connection. The
changes introduce epg_channels and epg_programs tables, multiple
indexes for efficient lookups (by source, name, channel, start, and
time range), and an epg_programs_fts virtual table with triggers to
keep the full-text index synchronized with epg_programs.
Register EPG database event handlers in the Electron backend and
add an IPC handler for bulk-saving channels. The handler deletes
existing channels for a source and inserts new channels in chunks to
avoid large single inserts, returning the inserted count.
These changes enable storing, querying, and full-text searching EPG
data and prepare backend IPC endpoints for importing program guide
data.
Introduce a lowercase display name index (Map) to allow O(1) resolution
from display name to channel id. Rebuild the index during merged-data
rebuild and use it in channel lookups to avoid expensive full scans.
Add a fallback partial-match pass only when the index lookup fails.
Add automatic and manual cleanup of expired programs:
- Add cleanupExpiredPrograms(hoursToKeep) to remove programs older
than the specified number of hours from epgDataMerged.
- Invoke cleanup after worker fetches (auto-cleanup with 24 hours).
- Expose an IPC handler EPG_CLEANUP_EXPIRED to trigger cleanup on
demand.
Other changes:
- Clear epgData.programs after merging to free memory.
- Log merged data rebuild and cleanup counts for observability.
These changes improve performance of channel resolution, reduce memory
usage by pruning stale program entries, and provide a manual hook for
on-demand maintenance.
Replace full-file parsing with a streaming SAX parser to avoid loading
entire XMLTV payloads into memory. Add support for gzipped feeds by
using streaming gunzip (createGunzip) and piping into a SaxesParser,
allowing incremental processing of channels and programmes.
Introduce:
- StreamingEpgParser class that incrementally builds channel and program
objects and emits batches.
- parseXmltvDate helper to normalize XMLTV datetimes to ISO strings.
- batching constants and response types for channel/program batches and
progress reporting.
- use of Readable/Saxes for streaming parsing and reduced memory use.
This change improves performance and memory usage for large EPG files,
enables progress reporting and batch emission to the main thread, and
prepares for handling very large or gzipped EPG sources.
Introduce a shared database schema library for Drizzle ORM and
configure its TypeScript build settings. Move the canonical schema
into libs/shared/database/src/lib/schema.ts and expose strong
typing and table definitions for playlists, categories, content,
recently_viewed and favorites. Add tsconfig.lib.json to set
outDir, declaration output and node types for the shared lib.
Keep apps/electron-backend compatibility by re-exporting the
schema and types from the new shared library (apps/electron-backend
now imports the shared definitions rather than duplicating them).
These changes centralize the database schema as a single source
of truth, prevent duplication, and enable read-only consumers
(e.g. agent-backend) to depend on compiled type declarations.
Extract the file's basename and strip common playlist extensions
before passing it as the playlist title when loading from a selected
file. This replaces the previous hardcoded "from file" title with a
cleaner, context-aware name derived from the file path.
- import basename from node:path
- compute filename and remove .m3u, .m3u8, .pls, .txt extensions
- fall back to "from file" if resulting title is empty
This improves UX by giving imported playlists meaningful names.
Re-enable user selection for input and textarea elements so users
can select and copy text in form fields. Add an Electron context
menu handler that shows a focused edit menu only for recognized
text input types or editable fields. The menu includes Cut, Copy,
Paste and Select All and respects the editFlags to enable actions.
This restores native editing UX in the renderer while avoiding
global context menus elsewhere in the app.
Add support for displaying local remote-control URLs and QR code in the
Settings UI, including styles for URL list, row layout, monospaced links,
and a QR container. Expose a new global API signature getLocalIpAddresses
for retrieving local IPs.
Fix several UI issues:
- Correct typo in header method name (opedAddPlaylistDialog -> openAddPlaylistDialog).
- Fix malformed GitHub URL and collapse img tag formatting.
- Reformat imports and viewChild usage for readability.
Change local development backend URL to localhost:3000 in the local
environment to point to the running local API during development.
These changes improve developer ergonomics (local backend), add a remote
control discovery UX for users on the same network, and tidy up header
bugs and formatting.
Add macOS-specific title bar settings to the Electron main window
creation so the app uses a hidden title bar with an overlay on Darwin.
This ensures a more native, modern appearance on macOS while keeping
existing minimum size and saved bounds behavior unchanged.
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.
Remove @libsql/client and its transitive entries from package-lock and
add better-sqlite3 plus its TypeScript types. This updates the lockfile
to reflect switching DB client dependencies: drop the @libsql packages
and related node_modules entries, and add "better-sqlite3" and
"@types/better-sqlite3". The change reduces unused libsql artifacts and
ensures type definitions are available for the new native sqlite client.
Add webpack config and include it in the electron backend build so
worker scripts are correctly bundled for packaged apps. Move worker
files to be packaged as extraResources instead of asar unpack patterns
so the packaged app can load worker JS from Resources/dist/... at
runtime. Fix worker path resolution in epg.events: compute resourcesPath
from app.getAppPath() and point to dist/apps/electron-backend/workers
when app.isPackaged. Remove verbose app path logging and update comments
to reflect the actual packaged layout.
Why: ensure webworker entry points are included in the renderer/backend
bundle and accessible when the Electron app is packaged, preventing
worker loading failures in production builds.
Update EPG worker path handling and unpack worker files for production
builds so the worker can be spawned when the app is packaged with ASAR.
- Change workerPath to let and, when the resolved path includes
app.asar, replace it with app.asar.unpacked. This ensures the spawned
worker points to the unpacked resource in production.
- Add electron-builder asarUnpack pattern for workers/** so worker files
are packaged outside the ASAR archive.
These changes fix runtime errors where worker threads cannot be started
from inside app.asar and ensure the EPG parser can run in packaged apps.
Remove unused url.format import and switch from loadURL with a
formatted file: URL to loadFile for production. This simplifies code,
avoids manual file URL construction, and makes the production path
loading more robust.
Also update CI job to build the frontend via the NX command
(npx nx build web --skip-nx-cache) instead of npm run build:frontend,
aligning the workflow with the monorepo's canonical build command.
Add a new HttpServer class that serves the built remote-control-web
static assets and provides a simple REST/API routing layer for remote
control endpoints.
Key changes:
- Implement server lifecycle: start, stop, updateSettings with port and
enabled handling.
- Resolve distribution path depending on electron packaging (dev vs
production).
- Serve static files with basic security (normalize path to prevent
traversal) and SPA fallback to index.html for client-side routing.
- Provide registration API for remote control handlers mapped to
/api/remote-control/* endpoints.
- Log server status and listening URL on start, and on stop.
These changes enable the Electron backend to host the remote control
web app and route API calls without external web servers, simplifying
development and packaging.
Save and restore favorited and recently viewed Xtream items when
deleting and re-importing playlist content.
- Return favoritedXtreamIds and recentlyViewedXtreamIds from
deleteXtreamPlaylistContent so callers can capture user data before
.
- Add restoreXtreamUserData to the database service to allow restoring
favorites and recently viewed entries after a refresh.
- Query and collect xtreamIds and timestamps for favorites and recently
viewed items in the backend before deleting content.
- Persist the captured user data to localStorage in the recent playlists
component so it can be used to restore state after re-importing the
playlist.
- Keep existing playlist metadata update flow intact.
This prevents loss of user-specific favorites and recent history when
refreshing Xtream playlists.
Add automatic playlist refresh on application startup by listening
for successful playlist load and dispatching an IPC event for any
playlists with autoRefresh enabled.
- Inject Actions into AppComponent and add triggerAutoUpdatePlaylists
that waits for PlaylistActions.loadPlaylistsSuccess, selects
selectAllPlaylistsMeta from the store, filters playlists with
autoRefresh, and sends AUTO_UPDATE_PLAYLISTS via DataService.
- Call triggerAutoUpdatePlaylists from ngOnInit and remove a now-
unused commented commands list.
- Add helper functions in backend playlist events to fetch and parse
playlists from URL or file, consolidating parsing logic and creating
playlist objects.
This implements the previously noted TODO to trigger playlist auto-
refresh and centralizes playlist fetching/parsing for reuse and
clarity.
Refine MPV/VLC launch error handling in the renderer to extract and show
error.message when available, preventing unhelpful "[object Object]"
messages in the UI.
In the Electron backend, ensure failed MPV instances fall through to
creation by commenting intent, and wrap spawn in a promise to reliably
detect startup failures. On spawn error, clear stored references and
reject with a descriptive message that includes the mpv path. Add an
exit handler, conditional storage of the process for reuse, and proc.unref
for detached runs. Use a short timeout to resolve the promise when spawn
succeeds and log startup state. Convert a silent log to console.error and
rethrow the error to surface failures to callers.
These changes make MPV startup more robust and produce clearer error
feedback for debugging and UI notifications.
Enhance MPV player IPC handler to accept and forward extra parameters
(url, path, title, userAgent, referer, origin). Attempt to reuse an
existing MPV instance when reuse is enabled and an IPC socket is
available; if reuse fails, fall back to spawning a new process.
When creating a new MPV process, generate a unique platform-aware IPC
socket path, build arguments conditionally from provided metadata
(user-agent, referrer, origin via http-header-fields, force-media-title)
and append the URL last. Improve logging for debugging and handle
process spawn errors by clearing stale process/socket references.
These changes enable smoother playback handoff, preserve headers and
title for remote resources, and make MPV invocations more robust.