Skip to content

Conversation

@4gray
Copy link
Owner

@4gray 4gray commented Nov 8, 2025

Summary

  • Rework IPC events handling across the player subsystem and related modules.
  • Enhance MPV player IPC handler to accept and forward extra metadata: url, path, title, userAgent, referer, origin.
  • Attempt reuse of existing MPV instance when reuse is enabled and an IPC socket is available; fall back to spawning a new process if reuse fails.
  • Generate platform-aware unique IPC socket paths and conditionally build MPV args (http-header-fields, force-media-title) including appending URL last.
  • Improve logging and error handling for MPV process spawn failures, clearing stale process/socket references.
  • Ensure playlist headers are passed to external players.

What changed

  • IPC events handling refactored for cleaner, more robust flow.
  • MPV invocation logic updated to preserve headers and title for remote resources and enable smoother playback handoff.
  • Added support for user-agent, referrer, origin, path and title propagation to external players.
  • Various code-style and UI tweaks; Electron bumped to v39.x; minor accessibility rule changes and navigation sidebar visual improvements.

Testing notes

  • MPV reuse behavior and fallback spawning paths exercised.
  • Header/title propagation validated for remote playlists and external player launches.

Summary by CodeRabbit

Release Notes

New Features

  • Added Progressive Web App (PWA) build configuration for web deployment
  • Enhanced external player support with improved metadata handling
  • Auto-refresh success notifications for playlist updates
  • Electron window now enforces minimum size constraints (900x600px)

Bug Fixes

  • Fixed potential null reference issues in EPG display

UI/UX Improvements

  • Refined navigation interface with improved tooltips
  • Optimized sidebar layouts for better content visibility

4gray added 6 commits November 8, 2025 10:22
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.
@vercel
Copy link

vercel bot commented Nov 8, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
iptvnator Error Error Nov 8, 2025 10:26pm

@coderabbitai
Copy link

coderabbitai bot commented Nov 8, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key(s) in object: 'auto_review'
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Walkthrough

This PR modernizes the IPTVnator codebase by migrating from direct IPC messaging to NgRx-based state management, adding signal-based inputs to Angular components, extending the Electron player IPC handlers with additional metadata (userAgent, referer, origin), adding PWA build configuration, and making various UI/styling adjustments to navigation and layout.

Changes

Cohort / File(s) Summary
Claude & Configuration
.claude/settings.local.json, CLAUDE.md, README.md, package.json, libs/m3u-state/tsconfig.lib.json
Added Claude AI settings file with Bash/WebSearch/WebFetch permissions; introduced developer documentation covering IPTVnator architecture, commands, and testing; updated README from Tauri to Electron/Angular stack; added npm scripts for PWA builds and updated electron to v39; added global type declarations to tsconfig.
Electron Backend IPC Enhancement
apps/electron-backend/src/app/events/player.events.ts, apps/electron-backend/src/app/events/xtream.events.ts, apps/electron-backend/src/app/api/main.preload.ts, apps/electron-backend/src/app/app.ts
Extended OPEN_MPV_PLAYER and OPEN_VLC_PLAYER IPC handlers with userAgent, referer, and origin parameters; added MPV process reuse logic with IPC socket management; replaced IPC channel constant with string literal in Xtream events; reformatted preload declarations; set minimum window size constraints (600×900).
IPC to NgRx Migration
apps/web/src/app/services/electron.service.ts, apps/web/src/app/services/pwa.service.ts, apps/web/src/app/app.component.ts, apps/web/src/app/home/home.component.ts, apps/web/src/app/home/video-player/video-player.component.ts
Replaced direct IPC postMessage communication with NgRx store actions (updateManyPlaylists, updatePlaylist, handleAddingPlaylistByUrl); removed IPC command listeners and error posting; replaced window messaging with snackbar notifications; simplified home and app components by removing IPC infrastructure; removed OnDestroy lifecycle from components.
Signal-Based Component Inputs
apps/web/src/app/xtream-tauri/playlist-error-view/playlist-error-view.component.ts, libs/ui/components/src/lib/recent-playlists/recent-playlists.component.ts, libs/ui/components/src/lib/multi-epg/multi-epg-container.component.ts
Migrated from @Input/@output decorators to Angular input()/output() signals; converted ViewChild to viewChild.required signal API; replaced constructor DI with inject() calls; removed OnInit lifecycle where applicable; updated component templates to invoke signal methods.
Player Service Metadata Propagation
apps/web/src/app/services/player.service.ts, apps/web/src/app/xtream/xtream-main-container.component.ts, apps/web/src/app/stalker/stalker.store.ts, apps/web/src/app/xtream-tauri/xtream.store.ts
Added userAgent, referer, and origin optional parameters to openPlayer; propagated playlist metadata through player service calls to external player IPC events.
State Management Updates
libs/m3u-state/src/lib/actions.ts, libs/m3u-state/src/lib/effects.ts, libs/m3u-state/src/lib/reducers.ts, libs/shared/interfaces/src/lib/playlist.interface.ts, libs/shared/interfaces/src/lib/ipc-commands.ts
Added handleAddingPlaylistByUrl NgRx action with isTemporary flag; updated addPlaylist$ effect to filter temporary playlists; added reducer case for new action; extended Playlist interface with referrer and origin fields; removed PLAYLIST_PARSE_RESPONSE and PLAYLIST_UPDATE_RESPONSE constants.
UI & Navigation Refinements
apps/web/src/app/xtream-tauri/navigation/navigation.component.html, apps/web/src/app/xtream-tauri/navigation/navigation.component.scss, apps/web/src/app/xtream-tauri/navigation/navigation.component.ts, apps/web/src/app/home/home.component.html, apps/web/src/app/home/home.component.scss, apps/web/src/app/stalker/stalker-shell/stalker-shell.component.scss, apps/web/src/app/xtream-tauri/xtream-shell/xtream-shell.component.scss
Narrowed navigation sidebars from 200px/300px to 60px; updated navigation to use tooltips instead of labels and commented out portal info blocks; simplified home component template by removing grid wrapper; removed MatIconButton from navigation imports; adjusted portal status container height and removed borders.
Styling & Layout Updates
apps/web/src/app/xtream-tauri/portal-channels-list/portal-channels-list.component.scss, apps/web/src/app/xtream-tauri/sidebar.scss, apps/web/src/app/xtream-tauri/xtream-shell/xtream-shell.component.scss, apps/web/src/app/xtream-tauri/category-view/category-view.component.scss, apps/web/src/app/xtream/playlist-error-view/playlist-error-view.component.scss, apps/web/src/app/home/video-player/video-player.component.html
Increased portal channels item width to 370px; increased main sidebar to 400px; removed left border from selected category items; updated button margins; added non-null assertion to async epg binding; normalized opacity notation to 0.X format.
Config & Build Updates
apps/web/project.json, libs/ui/components/eslint.config.mjs
Added PWA build configuration with baseHref targeting; disabled click/focus ESLint template rules.
Testing & Documentation
libs/ui/components/src/lib/html-video-player/html-video-player.component.spec.ts, libs/ui/components/src/lib/info-overlay/info-overlay.component.spec.ts, libs/ui/components/src/lib/epg-list/epg-list.component.ts, libs/ui/components/src/lib/epg-list/epg-list-item/epg-list-item.component.html, apps/web/src/assets/i18n/en.json, apps/web/src/app/xtream/playlist-error-view/playlist-error-view.component.ts, libs/services/src/lib/portal-status.service.ts
Deleted info-overlay spec file; refactored epg-list to use store-based observables and removed DataService dependency; converted Material module imports to component-level; added null check in epg template; added AUTO_REFRESH_UPDATE_SUCCESS translation key; added deprecation comment to legacy Xtream playlist-error component; replaced IPC constant with string literal in portal-status service.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant FrontendComponent
    participant PlayerService
    participant ElectronBackend
    participant ExternalPlayer as External Player<br/>(MPV/VLC)

    User->>FrontendComponent: Open stream
    FrontendComponent->>PlayerService: openPlayer(url, title, playlist metadata)
    PlayerService->>ElectronBackend: IPC invoke 'OPEN_MPV_PLAYER'<br/>(url, path, title, userAgent,<br/>referer, origin)
    ElectronBackend->>ElectronBackend: Check if MPV reuse enabled
    alt MPV reuse enabled
        ElectronBackend->>ExternalPlayer: Send loadfile via IPC socket
    else Create new instance
        ElectronBackend->>ExternalPlayer: Spawn MPV with args:<br/>--user-agent, --referrer,<br/>--http-header Origin, title
    end
    ExternalPlayer->>User: Stream playback
Loading
sequenceDiagram
    participant Service as Electron/<br/>PWA Service
    participant Store as NgRx Store
    participant Effect as addPlaylist$ Effect
    participant SnackBar
    participant User

    rect rgb(200, 220, 240)
    note over Service,User: Before: IPC postMessage
    Service->>Service: window.postMessage(...)
    end

    rect rgb(220, 240, 200)
    note over Service,User: After: NgRx + SnackBar
    Service->>Store: dispatch(handleAddingPlaylistByUrl)
    Store->>Effect: emit action
    Effect->>Effect: Check isTemporary flag
    alt isTemporary = true
        Effect->>Store: Populate channels, skip persist
    else isTemporary = false
        Effect->>Effect: addPlaylist to store
    end
    Service->>SnackBar: Show success notification
    SnackBar->>User: Display message
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Areas requiring extra attention:

  • IPC to NgRx migration (electron.service.ts, pwa.service.ts): Verify all postMessage flows have proper NgRx action counterparts and snackbar coverage, especially error paths and async operation sequencing.
  • Player metadata propagation (player.events.ts, player.service.ts, xtream.store.ts, stalker.store.ts, xtream-main-container.component.ts): Ensure userAgent, referer, and origin parameters flow correctly through all player invocation paths (MPV/VLC) and that optional chaining handles missing values.
  • Signal-based refactoring (playlist-error-view.component.ts, recent-playlists.component.ts, multi-epg-container.component.ts): Verify signal API usage is consistent (input(), output(), viewChild), template bindings correctly invoke signal methods, and change detection behavior remains correct.
  • Temporary playlist handling (effects.ts, reducers.ts, handleAddingPlaylistByUrl action): Confirm the isTemporary branching logic properly skips persistence for temporary playlists while still populating channels.
  • Navigation UI overhaul (navigation.component.html, navigation.component.scss): Verify tooltip positioning, accessibility of collapsed navigation, and that commented-out portal info blocks don't impact state management.

Possibly related PRs

  • chore: update to angular v20 #613: Angular modernization across components (NgIf/NgFor imports removal, standalone component conversion, signal adoption) overlaps with this PR's component-level refactoring patterns.
  • ci-add-github-actions-ui-fixes #638: Touches Electron backend IPC surface (main.preload.ts saveFileDialog and related IPC patterns) with similar infrastructure changes as this PR's player events IPC enhancements.

Poem

🐰 Signals spring forth, replacing old Input ways,
NgRx actions light the frontend maze,
MPV takes metadata, userAgent in tow,
Navbars shrink and sidebars glow,
IPC fades to snackbar's gentle cheer—
Modern patterns bloom this season clear! 🌱

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'refactor/ipc-events-handling' directly reflects the main change: refactoring IPC event handling logic, particularly for player subsystem. It is concise and relates to the primary objective of the PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Nov 8, 2025

View your CI Pipeline Execution ↗ for commit 0d6e519

Command Status Duration Result
nx run electron-backend:make ✅ Succeeded 4m 41s View ↗
nx build electron-backend ✅ Succeeded 7s View ↗
nx build web ✅ Succeeded 37s View ↗

☁️ Nx Cloud last updated this comment at 2025-11-08 22:32:00 UTC

@4gray
Copy link
Owner Author

4gray commented Nov 8, 2025

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Nov 8, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/web/src/app/services/player.service.ts (1)

24-73: IPC payload structure mismatch: frontend sends object but backend expects individual parameters

The backend handlers in player.events.ts are registered to receive individual positional parameters: (event, url, path, title, userAgent?, referer?, origin?). However, the frontend in player.service.ts (lines 40–47, 53–60) sends an object payload { url, mpvPlayerPath, title, ... }, causing parameter misalignment. The url argument receives the entire object instead of the stream URL, path becomes undefined instead of the player path, and so on.

Additionally, the frontend passes 'user-agent' (hyphenated) while the backend handler expects userAgent (camelCase).

Ensure the IPC calls match the backend signature by passing individual arguments in the correct order: (OPEN_MPV_PLAYER, streamUrl, mpvPlayerPath, title, userAgent, referer, origin) rather than as an object.

apps/web/src/app/services/electron.service.ts (1)

64-89: Fix user agent property name passed to Electron player launchers
The payload we emit from PlaylistEffects.setActiveChannel$ and other IPC senders uses the camel-cased userAgent field, but here we read 'user-agent'. As a result the MPV/VLC bridges never receive the header we just wired through this PR, defeating the whole metadata propagation change. Please switch to data.userAgent (and mirror this in both MPV and VLC branches) so the user agent actually flows through.

-                    data['user-agent'] ?? undefined,
+                    data.userAgent ?? undefined,

…and similarly for the VLC call just below.

🧹 Nitpick comments (7)
apps/web/src/app/xtream-tauri/navigation/navigation.component.scss (1)

40-44: LGTM: Formatting improvements enhance readability.

The multiline gradient formatting and opacity standardization (.7 to 0.7) improve code readability without affecting visual appearance.

Also applies to: 62-82, 117-127, 204-204

apps/web/src/app/xtream-tauri/navigation/navigation.component.html (1)

13-22: Consider removing commented code.

Multiple sections contain commented-out code (portal-info, portal-actions, nav-group-labels, item titles). If these sections are no longer needed, consider removing them entirely to reduce technical debt. If they're kept for future reference, add a comment explaining why.

Also applies to: 23-52, 56-56, 67-67, 84-84, 92-94, 105-107, 118-120, 131-133

apps/web/src/app/xtream/playlist-error-view/playlist-error-view.component.ts (1)

13-15: Consider consolidating duplicate components.

The deprecation comment indicates there's another instance of this component in xtream-tauri. Having duplicate components can lead to maintenance burden and inconsistencies.

Consider consolidating the two implementations into a shared component or creating a clear migration plan to remove this deprecated version.

README.md (1)

125-134: Consider addressing markdown linting issues.

The documentation updates accurately reflect the Electron/Angular stack. Static analysis has flagged a few minor markdown formatting issues:

  • Line 125: Dollar signs before commands without showing output
  • Line 128: Bare URL (consider using link syntax)
  • Lines 132-133: Fenced code block missing language specifier

Apply these improvements:

-    ```
     $ npm run serve:backend
-    ```
+    ```shell
+    $ npm run serve:backend
+    ```

-This will open the Electron app in a separate window, while the Angular dev server will run at http://localhost:4200.
+This will open the Electron app in a separate window, while the Angular dev server will run at <http://localhost:4200>.

-```
+```shell
 $ npm run serve:frontend

</blockquote></details>
<details>
<summary>apps/electron-backend/src/app/events/player.events.ts (3)</summary><blockquote>

`30-54`: **Consider adding connection timeout for robustness.**

The socket connection has no timeout, which could cause the promise to hang indefinitely if MPV becomes unresponsive or the socket is stale.

Consider adding a timeout:

```diff
 function sendMpvCommand(command: string, args: string[]): Promise<void> {
     return new Promise((resolve, reject) => {
         if (!mpvSocketPath) {
             reject(new Error('No MPV socket path available'));
             return;
         }
 
         const client = createConnection(mpvSocketPath);
+        const timeout = setTimeout(() => {
+            client.destroy();
+            reject(new Error('MPV socket connection timeout'));
+        }, 5000);
+
         // MPV expects commands in the format: { "command": ["cmd", "arg1", "arg2"] }
         const request = JSON.stringify({ command: [command, ...args] }) + '\n';
 
         client.on('connect', () => {
+            clearTimeout(timeout);
             console.log('Connected to MPV socket, sending command:', request);
             client.write(request);
             client.end();
             resolve();
         });
 
         client.on('error', (err) => {
+            clearTimeout(timeout);
             console.error('MPV socket error:', err);
             reject(err);
         });
     });
 }

106-110: Socket path uniqueness could be improved.

Using Date.now() for socket path uniqueness could theoretically result in collisions if multiple MPV instances are spawned within the same millisecond, though this is unlikely in practice.

Consider using a more robust unique identifier:

+import { randomBytes } from 'crypto';
+
 // Generate unique socket path
 const socketPath =
     process.platform === 'win32'
-        ? `\\\\.\\pipe\\mpv-${Date.now()}`
-        : `/tmp/mpvsocket-${Date.now()}`;
+        ? `\\\\.\\pipe\\mpv-${randomBytes(8).toString('hex')}`
+        : `/tmp/mpvsocket-${randomBytes(8).toString('hex')}`;

67-77: Missing validation of MPV player path.

The handler doesn't validate that the MPV executable exists before attempting to spawn the process. This could lead to unclear error messages when the player is not installed or the path is incorrect.

Add validation before spawning:

+        const mpvPath = getMpvPath();
+        if (!existsSync(mpvPath)) {
+            throw new Error(`MPV player not found at path: ${mpvPath}`);
+        }
+
-        const mpvPath = getMpvPath();
         const reuseInstance = store.get(MPV_REUSE_INSTANCE, false);
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f36f946 and 8467702.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (50)
  • .claude/settings.local.json (1 hunks)
  • CLAUDE.md (1 hunks)
  • README.md (2 hunks)
  • apps/electron-backend/src/app/api/main.preload.ts (1 hunks)
  • apps/electron-backend/src/app/app.ts (1 hunks)
  • apps/electron-backend/src/app/events/player.events.ts (2 hunks)
  • apps/electron-backend/src/app/events/xtream.events.ts (2 hunks)
  • apps/web/project.json (2 hunks)
  • apps/web/src/app/app.component.ts (3 hunks)
  • apps/web/src/app/home/home.component.html (1 hunks)
  • apps/web/src/app/home/home.component.scss (0 hunks)
  • apps/web/src/app/home/home.component.ts (1 hunks)
  • apps/web/src/app/home/video-player/video-player.component.html (1 hunks)
  • apps/web/src/app/home/video-player/video-player.component.ts (2 hunks)
  • apps/web/src/app/services/electron.service.ts (7 hunks)
  • apps/web/src/app/services/player.service.ts (3 hunks)
  • apps/web/src/app/services/pwa.service.ts (4 hunks)
  • apps/web/src/app/stalker/stalker-shell/stalker-shell.component.html (1 hunks)
  • apps/web/src/app/stalker/stalker-shell/stalker-shell.component.scss (1 hunks)
  • apps/web/src/app/stalker/stalker.store.ts (1 hunks)
  • apps/web/src/app/xtream-tauri/category-view/category-view.component.scss (0 hunks)
  • apps/web/src/app/xtream-tauri/navigation/navigation.component.html (3 hunks)
  • apps/web/src/app/xtream-tauri/navigation/navigation.component.scss (6 hunks)
  • apps/web/src/app/xtream-tauri/navigation/navigation.component.ts (1 hunks)
  • apps/web/src/app/xtream-tauri/playlist-error-view/playlist-error-view.component.html (1 hunks)
  • apps/web/src/app/xtream-tauri/playlist-error-view/playlist-error-view.component.ts (2 hunks)
  • apps/web/src/app/xtream-tauri/portal-channels-list/portal-channels-list.component.scss (9 hunks)
  • apps/web/src/app/xtream-tauri/sidebar.scss (1 hunks)
  • apps/web/src/app/xtream-tauri/xtream-shell/xtream-shell.component.scss (1 hunks)
  • apps/web/src/app/xtream-tauri/xtream.store.ts (1 hunks)
  • apps/web/src/app/xtream/playlist-error-view/playlist-error-view.component.scss (1 hunks)
  • apps/web/src/app/xtream/playlist-error-view/playlist-error-view.component.ts (1 hunks)
  • apps/web/src/app/xtream/xtream-main-container.component.ts (2 hunks)
  • apps/web/src/assets/i18n/en.json (1 hunks)
  • libs/m3u-state/src/lib/actions.ts (1 hunks)
  • libs/m3u-state/src/lib/effects.ts (2 hunks)
  • libs/m3u-state/src/lib/reducers.ts (1 hunks)
  • libs/m3u-state/tsconfig.lib.json (1 hunks)
  • libs/services/src/lib/portal-status.service.ts (1 hunks)
  • libs/shared/interfaces/src/lib/ipc-commands.ts (0 hunks)
  • libs/shared/interfaces/src/lib/playlist.interface.ts (1 hunks)
  • libs/ui/components/eslint.config.mjs (1 hunks)
  • libs/ui/components/src/lib/epg-list/epg-list-item/epg-list-item.component.html (1 hunks)
  • libs/ui/components/src/lib/epg-list/epg-list.component.ts (4 hunks)
  • libs/ui/components/src/lib/html-video-player/html-video-player.component.spec.ts (2 hunks)
  • libs/ui/components/src/lib/info-overlay/info-overlay.component.spec.ts (0 hunks)
  • libs/ui/components/src/lib/multi-epg/multi-epg-container.component.ts (4 hunks)
  • libs/ui/components/src/lib/recent-playlists/recent-playlists.component.html (2 hunks)
  • libs/ui/components/src/lib/recent-playlists/recent-playlists.component.ts (4 hunks)
  • package.json (2 hunks)
💤 Files with no reviewable changes (4)
  • libs/shared/interfaces/src/lib/ipc-commands.ts
  • apps/web/src/app/xtream-tauri/category-view/category-view.component.scss
  • apps/web/src/app/home/home.component.scss
  • libs/ui/components/src/lib/info-overlay/info-overlay.component.spec.ts
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
README.md

125-125: Dollar signs used before commands without showing output

(MD014, commands-show-output)


128-128: Bare URL used

(MD034, no-bare-urls)


132-132: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


133-133: Dollar signs used before commands without showing output

(MD014, commands-show-output)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build on ubuntu-latest
  • GitHub Check: Build on macos-latest
  • GitHub Check: Build on windows-latest
🔇 Additional comments (49)
apps/electron-backend/src/app/api/main.preload.ts (1)

11-14: LGTM! Formatting improvement for readability.

The multi-line formatting of the saveFileDialog signature enhances readability and aligns with the style used by other multi-parameter functions in this file (e.g., openInMpv, openInVlc).

libs/services/src/lib/portal-status.service.ts (1)

31-41: LGTM! Clean refactoring to string literal.

The replacement of the imported XTREAM_REQUEST constant with the string literal 'XTREAM_REQUEST' aligns with the PR's IPC refactoring objectives. The channel name matches the backend handler in xtream.events.ts, ensuring consistent communication.

apps/electron-backend/src/app/events/xtream.events.ts (2)

19-19: LGTM! Consistent IPC channel naming.

The string literal 'XTREAM_REQUEST' matches the frontend usage in portal-status.service.ts, ensuring proper IPC communication. This refactoring reduces coupling to the shared constants file.


79-83: LGTM! Improved readability.

The multiline formatting of the error type guard improves code readability without changing the logic. The defensive checks (error && typeof error === 'object' && 'message' in error) are appropriate for safely handling unknown error types.

libs/ui/components/src/lib/html-video-player/html-video-player.component.spec.ts (2)

4-4: LGTM: Alias import improves maintainability.

The switch to an alias-based import path aligns with the PR's modernization strategy.


49-51: LGTM: Explicit empty implementation improves clarity.

The expanded block body with the /* empty */ comment makes the intentional no-op implementation more obvious.

libs/ui/components/src/lib/recent-playlists/recent-playlists.component.ts (2)

7-8: Excellent migration to Angular signal-based API!

The migration from decorator-based @Input() and @Output() to signal-based input() and output() is correctly implemented. This modernization provides better reactivity, type safety, and aligns with Angular's current best practices. The addition of allPlaylistsLoaded signal for reactive store selection is also well done.

All three signals are properly marked as readonly, and the template correctly invokes them as functions where needed.

Also applies to: 62-67


143-146: Method rename improves clarity.

The rename from getGlobalFavorites() to navigateToGlobalFavorites() better reflects the method's actual behavior, which is to navigate to the global favorites view and emit an event. The previous name suggested data retrieval, while the new name accurately describes the navigation action.

libs/ui/components/src/lib/recent-playlists/recent-playlists.component.html (1)

28-28: Template correctly updated for signal-based API.

The template changes properly align with the TypeScript migration to signal-based inputs and method rename. Line 45 correctly invokes sidebarMode() as a function to access the signal's value, and line 28 uses the renamed navigateToGlobalFavorites() method.

Also applies to: 45-45

libs/ui/components/src/lib/multi-epg/multi-epg-container.component.ts (4)

9-9: LGTM! Modern Angular patterns adopted.

The imports correctly reflect the shift to inject-based DI and signal-based view queries.

Also applies to: 13-13


59-59: LGTM! Signal-based view query correctly implemented.

The migration to viewChild.required is appropriate, and the signal is correctly invoked at line 122.


83-83: LGTM! Improved type safety.

The number type is correct for browser/Electron environments and removes the unsafe any type.


122-124: LGTM! Correct usage of viewChild signal.

The signal is properly invoked with this.epgContainer() and the nativeElement is accessed correctly.

libs/ui/components/src/lib/epg-list/epg-list-item/epg-list-item.component.html (1)

20-27: Null guard on item looks good.

This defensive check prevents template errors when the EPG item hasn’t hydrated yet.

apps/web/src/app/xtream-tauri/xtream-shell/xtream-shell.component.scss (1)

16-16: LGTM: Sidebar width reduced for icon-only navigation.

The width reduction from 200px to 60px aligns with the icon-only navigation pattern implemented in the corresponding HTML template changes.

apps/web/src/app/stalker/stalker-shell/stalker-shell.component.scss (1)

16-16: LGTM: Consistent sidebar width adjustment.

The width reduction matches the change in xtream-shell.component.scss, ensuring consistent icon-only navigation across both stalker and xtream shell components.

apps/web/src/app/xtream-tauri/sidebar.scss (1)

2-2: LGTM: Sidebar width increased for content display.

The width increase from 300px to 400px provides more space for content, which contrasts appropriately with the narrowed navigation sidebar (60px) in the shell components.

apps/web/src/app/xtream-tauri/navigation/navigation.component.scss (1)

47-47: LGTM: Min-height reduction aligns with UI changes.

The reduction from 120px to 50px is appropriate given that the portal info and actions sections are now hidden (commented out in the HTML template).

package.json (3)

65-65: LGTM: PWA build configuration scripts.

The new PWA-specific build and serve scripts are well-defined and align with the documented dual-environment architecture (Electron + PWA) mentioned in CLAUDE.md.

Also applies to: 68-68


180-180: Good: More flexible versioning for electron-builder.

Adding the caret allows automatic updates to compatible versions (patches and minor releases) while preventing breaking major version changes.


179-179: No breaking changes identified. Electron 39.0.0 upgrade is compatible with this codebase.

Verification of the identified breaking changes shows none apply:

  • IPC communication: Uses modern ipcMain.handle() and ipcRenderer.invoke() patterns, fully compatible with Electron 39.
  • Preload script & contextBridge: Correctly configured with contextIsolation: true and proper contextBridge.exposeInMainWorld() syntax—compatible with v39.
  • MPV/VLC player integration: Uses standard IPC invoke pattern with no deprecated APIs.
  • Breaking changes assessment:
    • OSR paint handlers: not used
    • window.open popups: used only for external URLs, not affected by resize-behavior change
    • --host-rules: not used
    • Stack upgrades (Node 22, Chromium 142, V8 14.2): no native modules, no impact

No code changes are required for this upgrade.

.claude/settings.local.json (1)

1-11: LGTM: Scoped permissions for development assistance.

The local Claude configuration appropriately scopes permissions for development tasks. The WebFetch restriction to electronjs.org domain is sensible given the Electron version upgrade in this PR.

libs/m3u-state/tsconfig.lib.json (1)

10-10: LGTM: Including global type declarations.

Explicitly including global type declarations ensures they're available during library compilation. This is particularly relevant given the interface extensions mentioned in the PR (new referrer and origin fields on Playlist).

apps/web/src/app/xtream-tauri/portal-channels-list/portal-channels-list.component.scss (2)

10-10: LGTM: Increased list item width for better content display.

The width increase from 280px to 370px provides more space for channel information, improving readability and reducing text truncation.


138-138: Good: Normalized opacity values for consistency.

Standardizing opacity values from .6 to 0.6 improves code consistency across the stylesheet.

Also applies to: 145-145

CLAUDE.md (1)

1-290: Excellent documentation for codebase understanding.

This comprehensive guide clearly explains the dual-environment architecture (Electron + PWA), factory pattern for service injection, development workflows, and common patterns. This will significantly help with onboarding, maintenance, and AI-assisted development.

apps/web/src/app/xtream-tauri/playlist-error-view/playlist-error-view.component.ts (1)

1-1: LGTM: Modern signal-based input pattern.

The migration from @Input() decorators to Angular's input() signal API is excellent:

  • Provides better type safety and reactivity
  • Aligns with modern Angular (v17+) best practices
  • Correctly preserves types and default values
  • Making currentPlaylist private is appropriate since it's only used internally

The corresponding template (playlist-error-view.component.html) correctly uses function call syntax for these signal-based inputs.

Also applies to: 28-37

apps/web/src/app/xtream-tauri/playlist-error-view/playlist-error-view.component.html (2)

2-2: LGTM: Correct signal syntax with template updates.

Template bindings correctly updated to use function call syntax (viewType(), title(), etc.) to match the signal-based inputs in the component class. This change is required for the new input API.

Also applies to: 4-4, 10-10, 14-15, 18-18


3-3: Good: Accessibility improvements with alt text.

Added descriptive alt attributes to images ("Something went wrong", "empty category"), improving screen reader support and WCAG compliance.

Also applies to: 6-6

apps/web/src/app/home/video-player/video-player.component.html (1)

99-99: Verify the non-null assertion is safe.

The non-null assertion operator ! tells TypeScript that epgProgram$ | async will never be null or undefined. If the observable can emit null/undefined values, this could lead to runtime errors in the child component.

Please verify that epgProgram$ is guaranteed to emit a non-null value. If there's a possibility of null/undefined, consider using the safe navigation operator or an @if guard instead:

@if (epgProgram$ | async; as epgProgram) {
    <app-info-overlay
        [channel]="activeChannel"
        [epgProgram]="epgProgram"
    />
}
apps/web/src/app/stalker/stalker-shell/stalker-shell.component.html (1)

7-7: LGTM!

Reordering the bindings has no functional impact in Angular templates.

apps/web/src/app/xtream/playlist-error-view/playlist-error-view.component.scss (1)

25-25: LGTM!

Adding uniform margins improves button spacing when multiple buttons are displayed horizontally.

apps/electron-backend/src/app/app.ts (1)

81-82: LGTM!

Setting minimum window dimensions ensures the UI remains usable and prevents layout breakage at very small sizes.

libs/shared/interfaces/src/lib/playlist.interface.ts (1)

26-27: LGTM!

Adding optional referrer and origin fields enables richer metadata propagation to external players while maintaining backward compatibility with existing code.

apps/web/src/app/stalker/stalker.store.ts (1)

482-492: LGTM!

The implementation correctly propagates playlist metadata (userAgent, referrer, origin) to the player service using safe optional chaining to handle undefined values gracefully.

apps/web/project.json (2)

48-66: LGTM!

The PWA build configuration properly sets production-grade settings with an appropriate root-relative baseHref for PWA deployment.


82-84: LGTM!

The PWA serve configuration correctly maps to the PWA build target.

apps/web/src/app/xtream/xtream-main-container.component.ts (2)

345-385: LGTM! Metadata propagation is well-structured.

The playlist metadata extraction and forwarding to external players is implemented correctly with appropriate null safety using optional chaining.


396-425: No issues found—the code is correct as written.

The destructured referrer property from the Playlist interface is intentionally passed as the referer key in IPC payloads. This is a consistent pattern throughout the codebase (also seen in m3u-state/effects.ts line 155). The Playlist interface uses referrer (double 'r') for semantic clarity, while the IPC and backend handlers use referer (single 'r', following the HTTP header standard). This is by design, not an error.

Likely an incorrect or invalid review comment.

apps/web/src/app/home/home.component.html (1)

1-5: LGTM! Clean template simplification.

The template refactor removes unnecessary wrapper elements while preserving the functionality.

libs/m3u-state/src/lib/actions.ts (1)

137-140: LGTM! Well-structured NgRx action.

The new handleAddingPlaylistByUrl action follows NgRx conventions with a clear payload structure and descriptive naming.

apps/web/src/assets/i18n/en.json (1)

69-70: LGTM! Translation key added correctly.

The new AUTO_REFRESH_UPDATE_SUCCESS key is well-placed and provides a clear user-facing message.

apps/web/src/app/xtream-tauri/xtream.store.ts (1)

842-858: LGTM! Metadata forwarding implemented correctly.

The openPlayer method properly extracts and forwards playlist metadata to the player service. The use of optional chaining ensures null safety.

Note: This method exhibits the same referrer vs referer naming pattern flagged in xtream-main-container.component.ts. Please verify consistency across the codebase as mentioned in that review.

apps/electron-backend/src/app/events/player.events.ts (6)

26-28: LGTM: Module-level state for MPV reuse.

The module-level variables properly track the MPV process and socket path for the reuse feature.


78-101: LGTM: MPV reuse logic with graceful fallback.

The reuse logic properly validates preconditions and gracefully falls back to creating a new instance if the existing one is unavailable or the command fails.


112-136: LGTM: MPV arguments built correctly.

The argument building logic properly handles optional parameters and correctly places the URL last, which is important for MPV.


138-142: Question: Should detached always be true?

The detached flag is currently !reuseInstance, meaning the process is attached when reuse is enabled. This seems counterintuitive—when reusing, you want to keep the process reference but still allow it to run independently of the parent.

Please verify if this is the intended behavior. Typically, external players should always be detached so they continue running even if the Electron app closes.

Consider changing to:

 const proc = spawn(mpvPath, args, {
     shell: false,
-    detached: !reuseInstance,
+    detached: true,
     stdio: 'ignore',
 });

227-228: Good documentation of VLC origin limitation.

The comment appropriately notes that VLC doesn't have a direct origin option. The origin is typically included in the referer for most IPTV use cases, so this limitation is acceptable.


262-379: LGTM: Comprehensive platform-aware path resolution.

The helper functions provide robust path resolution across Windows, Linux, and macOS, checking multiple common installation locations and falling back gracefully to PATH lookup.

4gray added 9 commits November 8, 2025 23:02
Update navigation components to improve sidebar usability and layout.
- Reformat stalker-shell navigation binding to align attributes consistently.
- Add matTooltip and matTooltipPosition to portal icon and nav items to
  surface portal status and item labels on hover.
 Rework navigation markup to use mat-nav-list, add home shortcut and dividers,
  and hide several textual labels/actions by commenting them out to create a
  more compact icon-only sidebar while preserving code for future restore.
- Collapse unused portal info/actions and library labels into comments to
  simplify DOM while keeping structure for reactivation.

These changes make the left navigation more compact, provide quick hover
context via tooltips, and prepare the UI for a condensed icon-driven layout.
Standardize generated installer/artifact file names across build
targets by adding explicit artifactName patterns in package.json.
Add a general artifactName at the top-level build config, ensure
linux targets (snap/deb/rpm) carry the same pattern, and set a
Windows-specific artifactName for win and nsis outputs that includes
the platform and arch.

This makes build outputs predictable for CI, releases, and automated
upload tooling by embedding name, version, OS, arch, and extension in
artifact filenames.
Update the GitHub release action to mark releases from pull 
request events as prerelease and to set a safe tag name when the
 is not triggered by a tag ref.

- Set prerelease to true when github.event_name == 'pull_request'
  so draft releases created during PR workflows are marked as
  prereleases.
- Use the tag name from github.ref_name when the workflow is
  triggered by a tag; otherwise generate a deterministic test tag
  "test-<sha>" to avoid using an invalid or empty tag name.

This prevents accidental full releases from PR runs and ensures the
action always has a valid tag_name value.
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.
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.
@4gray 4gray force-pushed the refactor/ipc-events-handling branch from da91d44 to c4f7213 Compare November 8, 2025 22:05
Update Angular in pnpm-lock to newer 20.3.x versions
and align CDK/Material specifiers to the compatible 20.2.12/20.2.12
releases. This brings core, common, compiler, platform-browser,
animations, forms and related packages to the 20.3.x series to fix
version skew and ensure dependency compatibility.

Add tsConfig for tests in libs/shared/interfaces project config so
jest runner uses the correct TypeScript spec configuration, fixing
test/compile issues for that library.

Remove husky commit-msg hooks and local pre-commit checks to avoid
running commitlint, tests and eslint on commit (CI remains unaffected).
@4gray 4gray merged commit b8650be into nx Nov 8, 2025
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants