Add a new standalone ContentHero component (template and TS) that
provides a cinematic hero section with backdrop, poster, title,
description, tags/meta/action slots, and a back button event emitter.
The component chooses backdrop or poster as the background, falls back
to a default poster image on load error, and exposes inputs for title,
description, posterUrl, and backdropUrl.
Introduce extensive cinematic styles for the detail view:
- define CSS custom properties for light and dark themes, poster size,
shadows, and color tokens
- implement gradient vignette, layout sizing, and theming via
:host and :host-context(.dark-theme)
- change container sizing behavior to full-height and hide overflow
These changes create a reusable hero UI and themed detail-page styles
to support a Netflix-style streaming detail experience.
Update translations and refactor StalkerPortalImportComponent to use
Angular signals and readonly/dependency-injected readonly properties.
- Add new i18n keys: LOADING_SEASONS and NO_EPISODES; adjust
PLAYBACK_ERROR punctuation.
- Replace EventEmitter @Output with a signals-based readonly output and
mark form, constants and flags as readonly.
- Switch to inject() style for services and mark many injected fields
private/readonly to clarify intent.
- Replace DataService import with STALKER_SERIAL_NUMBER token import.
- Improve logging formatting, whitespace and minor code cleanup.
- Minor template/style whitespace fixes.
These changes modernize the component for better immutability,
improve DX with clearer logging, and add missing user-facing
translation strings.
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.
Update info-overlay template to read simplified EPG fields and
avoid indexing into arrays for title, icon and description so bindings
are resilient and clearer:
- Use epgProgram?.iconUrl instead of epgProgram?.icon?.[0]?.src
- Use epgProgram?.title instead of epgProgram?.title?.[0]?.value
- Use epgProgram?.desc instead of epgProgram?.desc?.[0]?.value
- Guard description rendering with epgProgram?.desc
Adjust multi-epg header layout and add search UI styles to support
desktop window chrome and draggable regions:
- Add left padding to #epg-navigation for macOS traffic lights, enable
backdrop drag via -webkit-app-region: drag and set z-index to keep
header above content.
- Exclude interactive elements (buttons, search inputs) from drag by
applying -webkit-app-region: no-drag to maintain native interactions.
- Add extensive styles for a channel search container (search input,
icons, clear button, filter count, animations) and scaffold a program
search container.
These changes improve robustness of EPG data rendering and add styled
search controls while ensuring proper window dragging behavior on
desktop builds.
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 standalone EpgProgressPanelComponent with template and
bindings to show active, completed and queued EPG imports. The new
component:
- provides a header with title and optional "dismiss all" button when
multiple imports exist.
- lists active/completed imports with status icon, URL display,
dismiss button, and conditional progress bar for loading state.
- shows stats (channels/programs) or error text when available.
- renders a queued section with positions and dismiss controls.
- wires to EpgProgressService observables (imports, visibility and
counts) and implements helper getters (activeImports).
This adds UI for import progress feedback and controls so users can
monitor and manage EPG import operations. Files added:
- epg-progress-panel.component.ts
- epg-progress-panel.component.html
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.
Add a new mat-menu component for filtering and sorting playlists in the
header area. The filter section iterates playlistTypes and allows toggling
type selection with visual check state. The sort section adds options for
name (asc/desc) and date added (newest/oldest) with active-state visuals
and click handlers that call setSortOptions. A close button is also
included.
Remove unused/duplicate CSS rules from header styles: drop .filter-
container and obsolete .dropdown-menu-header rules to avoid styling
conflicts and reduce dead code. Adjust surrounding selector formatting.
Reduce the settings page container height calculation from
calc(100vh - 100px) to calc(100vh - 70px) so the content fits the
visible viewport when the header height is 70px. This prevents
unnecessary vertical overflow and avoids extra whitespace at the
bottom of the settings page.
Update English, German, and Russian locale files to improve playlist
UI text and provide explicit playlist type labels.
- Rename and adjust several labels: change FILTER_BY_TYPE to a more
descriptive "Playlist Types" and add a new FILTER_AND_SORT string.
- Normalize capitalization for SORT_BY ("Sort By") in en.json.
- Add PLAYLIST_TYPES object with keys for M3U, XTREAM, and STALKER,
providing localized descriptions for each language.
- Keep existing sorting options and parsing messages intact.
These changes make filtering, sorting, and playlist source options
clearer to users in multiple locales and prepare the UI for showing
playlist type choices.
imports and update dispatch calls
Replace multiple direct or wildcard imports for actions with
namespaced action groups from 'm3u-state' (e.g. PlaylistActions,
ChannelActions, EpgActions). Update dispatch calls to use the
namespaced action creators (for example, setAdjacentChannelAsActive,
setEpgAvailableFlag, resetActiveEpgProgram, setCurrentEpgProgram,
setActiveEpgProgram, addPlaylist).
This cleans up imports, improves tree-shaking and readability,
and standardizes how actions are referenced across components. It
also fixes inconsistent import styles (wildcard vs. named) and
prepares the codebase for clearer action organization.
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.
Prevent global hotkeys from triggering while the user is typing in
input or textarea fields. Add a private isTypingInInput(event) helper
and short-circuit key handlers (info key and digit keys) to return
early when the event target is an input or textarea.
This avoids interfering with normal text entry (e.g., entering numbers
in forms) and prevents accidental overlay toggles or channel changes
while the user is focused on a form field.
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 new English keys for remote control URL and QR code to support
remote-control features in the settings UI. Extend French locale with
many missing and corrected translations: add "Playlists" root entry,
Xtream/Stalker import labels, UI copy improvements (e.g. "Chaînes",
grammar fixes), new playlist export/copy messages, search/auto-refresh
labels, and removal success message. Fix several typos and phrasing in
French strings (IPTV, chaînes, ajouter(e), requièrent).
These changes enable new remote-control functionality and improve UX
for French users by completing and correcting the translations.
Add app-region: drag to container and header elements and app-region:
no-drag to interactive controls multiple components so the
Tauri window dragging behaves correctly while keeping buttons and form
controls clickable. Expand header search max width from 500px to 800px
to give more room on larger screens. Clean up and restyle video-player
toolbar toolbar primary colors and unify toolbar spacing.
Files changed include navigation, sidebar, header, main containers,
live-stream layout, navigation-bar, stalker container, and video-player
toolbar. These changes improve window drag UX on desktop and refine
toolbar/header appearance.
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.
Introduce explicit empty-state handling in RecentPlaylists:
- Replace previous direct rendering of an empty mat-list item with
app-empty-state for two cases: a global "welcome" state when no
playlists exist at all, and a "no-results" state when filters/search
return nothing. This clarifies UX and provides a CTA for adding
playlists in the welcome state.
- Change playlist data binding from playlists$ to playlistsData$ and
adapt loops and accessors to data.playlists / data.totalCount.
- Keep existing global favorites item and playlist-item rendering.
Wire up addPlaylist event and components:
- Add addPlaylistClicked output to RecentPlaylists component and
forward the event from the home component so the parent can open
the add-playlist flow.
- Import EmptyStateComponent and PlaylistType types used by the new
output.
Minor cleanup and imports:
- Reformat some imports and add tap to RxJS imports.
- Adjust template structure and placeholders for deferred loading.
Raise the maximumError for anyComponentStyle from 8kb to
kb in the web app build configuration. This relaxes the
build-size enforcement for component styles to accommodate
slightly larger CSS bundles and avoid spurious build failures.
Add new strings for the PLAYLIST view across English,
Spanish, French, German, and translations. The additions include a
welcome title description, a prompt to the first playlist, feature
labels for supported playlist types (MU/M3U, Xtream Codes Stalker),
and "no results title and description to clarify search/filter
.
These changes improve the onboarding experience new users and giveclearer feedback when searches return no. They also
ize feature labels across languages to communicate
supported playlist formats
- Shorten German settings TITLE from "Einstellungen / IPTVnator" to
"Einstellungen" to remove redundant app name and keep UI labels concise.
- Reformat and normalize Korean i18n JSON indentation and structure to
match expected layout (consistent nesting and whitespace).
- Reintroduce missing HOME -> nested sections (TABS, PLAYLISTS,
FILE_UPLOAD, URL_UPLOAD, TEXT_IMPORT, STALKER_PORTAL, XTREAM_PLAYLIST)
in ko.json to restore previously collapsed keys and ensure all keys
are present for runtime lookup.
- Fix several untranslated/placeholder labels and ensure key presence
for dialogs, validations and UI strings so translations load
consistently across components.
Update header component UI and streamline imports.
- Remove MatToolbarModule import and module list entry
because the toolbar styling is handled by local SCSS and the
Angular Material toolbar is no longer required.
- Rewrite header SCSS to introduce a .modern-header wrapper with
consistent sizing, padding, alignment and a subtle bottom border.
- Add layered ambient and depth effects: refined ::before ambient
gradient (headerAmbience), ::after bottom accent, and adjusted
keyframes for a gentler motion.
- Refine home-header styles to target .modern-header and tune colors
and gradients for a cohesive dark theme.
- Rework .brand-block visuals: lighter glass effect, adjusted
radii, blur, borders, hover transform, and shadowing for a modern
elevated look.
- Minor cleanup: remove legacy variables and comments; improve
box-sizing, layout, and pointer-event handling to ensure expected
interaction regions.
These changes modernize the header's visual design, improve layout
consistency across pages, and remove an unnecessary module import.
Enhance the header component to support a distinct "home" appearance
and emit search updates. Add a HostBinding that toggles a home-header
class from the isHome flag so styles can target the home state.
Expose a searchQuery output and wire an onSearchQueryUpdate method to
emit the search text, enabling parent components to react to user
searches.
Refactor imports to include HostBinding and output. Tidy toolbar metrics
and adjust element sizing for a compact brand block and pulsing logo.
Introduce comprehensive SCSS for the home header:
- gradient background, animated glow overlay, and edge accent
- brand block styling with blur, border, hover states and box-shadow
- logo sizing, pulse animation and responsive tweaks
- reduced toolbar height and overall visual polish
These changes separate home-specific styling from the default header
appearance and provide a programmatic hook for search interactions.
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.
Refactor error handling for Xtream requests to avoid showing user
snackbars when the request is a portal status check (get_account_info).
Instead of treating these errors as full failures, log them with
console.log to indicate the portal may be unavailable and return early.
Key changes:
- Introduce isStatusCheck detection in electron and pwa services.
- Replace console.error + snackbar with console.log for status checks.
- Only display snackbars for non-status-check errors.
- Add a console.log when pwa response has no payload for status checks.
This prevents unnecessary user-facing error popups for routine
portal health/status checks while keeping errors surfaced for other
requests.
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.
Change overflow handling in the xtream detail-view SCSS files to avoid
unwanted scrollbars and ensure proper layout stretching. In the web
version, remove a global overflow:auto and set overflow:visible on the
.details block and the grid container so inner content can expand as
needed. In the tauri variant, remove a min-height that forced an
artificial viewport-based height.
These tweaks fix layout clipping and scrollbar issues when detail
content
grows, and allow natural sizing across web and Tauri builds.
Add clearSelectedItem() to the stalker store to reset selected item
state (selectedVodId, selectedSerialId, selectedItvId, selectedItem).
This centralizes clearing logic and avoids manual nulling elsewhere.
Introduce goBackToList() in the container component to use the new
store method when navigating back from item details. Update the
template to conditionally show the back button when a selected item
exists, and ensure category title rendering and the disabled category
button behave correctly with the new conditional structure.
These changes simplify state management for returning from detail
views and make the template logic clearer and less error-prone.
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 missing semicolon in apps/web/src/styles.scss to fix invalid CSS
that could break style parsing for .scroll-viewport.
- Change preconnect in apps/web/src/index.html from fonts.gstatic.com to
fonts.googleapis.com and consolidate multiple Google Fonts links into
a single stylesheet URL to reduce redundant requests and ensure
Material Icons and selected font families load together.
Remove duplicated @import of Outfit in
libs/ui/components/src/lib/multi-epg/multi-epg-container.component.scss,
switch component font-family to Roboto (with fallback) and update
button font to match, ensuring consistent typography and avoiding
external import duplication across components. ese changes fix a
ntax error, optimize font loading, and standardize
typography across the UI.
Revamp the Multi-EPG component stylesheet to introduce a polished,
broadcast-control-room inspired dark theme and improved layout
styling.
- Add Google fonts (Outfit, JetBrains Mono) for a clean UI and mono
date display.
- Introduce color variables, gradients and accents for consistent
theming and easier maintenance.
- Rework base container (.parent) with subtle grid overlay and updated
typography.
- Implement a frosted glass navigation bar (#epg-navigation) with
blur, glow, and accessible button styles.
- Add today-date styling using a monospace font and glowing accent.
- Expand channels column width, update background, borders, shadows,
and hover transitions for clearer channel separation.
- Replace many hard-coded colors with variables and add transitions
for smoother interactions.
- Add utility classes for navigation buttons and improved disabled/
hover states.
These changes improve visual hierarchy, accessibility, and maintainabiity
of the EPG UI while setting up a consistent design system for further
enhancements.
Add a transient channel number overlay to the video player UI so users
see the numeric channel feedback when entering or changing channels.
- Insert conditional overlay markup in the video-player template that
renders when showChannelNumberOverlay is true and displays the
channelNumberInput value.
- Add styles for .channel-number-overlay and
.channel-number-display to center the overlay, style the numeric
display (large bold font, dark translucent background, rounded
corners, shadow) and include a brief scale-in animation.
- Keep overlay pointer-events disabled so it doesn't block player input.
This improves user experience by giving clear visual confirmation of
channel changes.