diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 795acc939..36b24391f 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,38 +1,55 @@ { - "permissions": { - "allow": [ - "Bash(tree:*)", - "WebSearch", - "WebFetch(domain:www.electronjs.org)", - "Bash(npm run build:frontend:*)", - "Bash(cat:*)", - "Bash(npx asar:*)", - "Bash(npm run package:app:*)", - "Bash(npm run build:backend:*)", - "Bash(pnpm add:*)", - "WebFetch(domain:github.com)", - "WebFetch(domain:www.npmjs.com)", - "Skill(example-skills:frontend-design)", - "Bash(npm run test:frontend:*)", - "Bash(nx lint:*)", - "Bash(npx tsc:*)", - "Bash(find:*)", - "Bash(xargs sed:*)", - "Skill(frontend-design)", - "mcp__angular-cli__get_best_practices", - "mcp__nx-mcp__nx_workspace", - "Bash(grep:*)", - "Bash(npx nx lint:*)", - "Bash(npx nx build:*)", - "Bash(npx eslint:*)", - "Bash(npx nx run:*)", - "Bash(lsof:*)", - "Bash(xargs kill:*)", - "Bash(curl:*)" - ], - "deny": [], - "ask": [] - }, - "enableAllProjectMcpServers": true, - "enabledMcpjsonServers": ["nx-mcp"] + "permissions": { + "allow": [ + "Bash(tree:*)", + "WebSearch", + "WebFetch(domain:www.electronjs.org)", + "Bash(npm run build:frontend:*)", + "Bash(cat:*)", + "Bash(npx asar:*)", + "Bash(npm run package:app:*)", + "Bash(npm run build:backend:*)", + "Bash(pnpm add:*)", + "WebFetch(domain:github.com)", + "WebFetch(domain:www.npmjs.com)", + "Skill(example-skills:frontend-design)", + "Bash(npm run test:frontend:*)", + "Bash(nx lint:*)", + "Bash(npx tsc:*)", + "Bash(find:*)", + "Bash(xargs sed:*)", + "Skill(frontend-design)", + "mcp__angular-cli__get_best_practices", + "mcp__nx-mcp__nx_workspace", + "Bash(grep:*)", + "Bash(npx nx lint:*)", + "Bash(npx nx build:*)", + "Bash(npx eslint:*)", + "Bash(npx nx run:*)", + "Bash(lsof:*)", + "Bash(xargs kill:*)", + "Bash(curl:*)", + "Bash(npx:*)", + "Bash(wc:*)", + "Bash(nx build:*)", + "Bash(agent-browser:*)", + "Bash(sqlite3:*)", + "Bash(agent-browser --cdp 9222 eval \"window.ng?.getComponent\\(document.querySelector\\(''app-unified-collection-page''\\)\\)?.playlistId\\(\\)\")", + "Bash(npx --yes agent-browser --cdp 9222 eval \"document.querySelector\\(''.nav-item.category-item''\\)?.click\\(\\)\")", + "Bash(agent-browser --cdp 9222 eval \"document.querySelector\\(''.playlist-switcher-trigger''\\).click\\(\\)\")", + "Bash(agent-browser --cdp 9222 eval \"document.querySelector\\(''''.playlist-switcher-trigger''''\\).click\\(\\)\")", + "Bash(npx agent-browser:*)", + "Bash(agent-browser --cdp 9222 eval \"fetch\\(''http://localhost:9222/json''\\).then\\(r=>r.json\\(\\)\\).then\\(t=>t[0].webSocketDebuggerUrl\\)\")", + "Bash(npx --yes agent-browser --cdp 9222 eval 'document.querySelector\\(\"\".mat-mdc-paginator-range-label\"\"\\)?.textContent?.trim\\(\\)')", + "Skill(electron)", + "Bash(node:*)", + "Bash(pkill -f \"chrome-cdp-debug\")" + ], + "deny": [], + "ask": [] + }, + "enableAllProjectMcpServers": true, + "enabledMcpjsonServers": [ + "nx-mcp" + ] } diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..3549e8a3f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,132 @@ +# AGENTS.md + +This file provides guidance to coding agents working in this repository. + +## Plan Mode + +- When an agent is in Plan Mode and produces a final ``, it must also save that finalized plan as a Markdown file in the repo-root `.plans/` directory. +- Save only finalized plans. Do not write interim exploration, questions, or draft revisions to `.plans/`. +- Use the filename pattern `YYYY-MM-DD-short-topic.md` such as `.plans/2026-03-12-channel-filtering.md`. +- If the intended filename already exists, append a numeric suffix such as `-2`, `-3`, and so on. + +## Documentation After Changes + +- After implementing a meaningful change, agents must assess whether canonical repo docs need updates before considering the task complete. +- Meaningful changes include new or changed user-visible behavior, architecture or data-flow changes, non-obvious maintenance workflows, new setup/debugging steps, and new subsystem contracts or boundaries. +- Skip doc updates for trivial refactors with unchanged behavior, formatting-only edits, and isolated test-only changes. +- Prefer updating an existing authoritative doc before creating a new one: + 1. `README.md` for top-level developer or user workflows + 2. `docs/architecture/` for architecture, ownership, and behavior contracts + 3. the nearest module `README.md` for local usage or behavior +- Repo docs are canonical even when they were originally drafted by an LLM. External wiki pages are derivative or synthesis content unless explicitly promoted back into the repo. +- The external wiki sync is one-way by default: repo docs -> external wiki `_repo-context/`. +- If repo docs changed and `IPTVNATOR_WIKI_VAULT` is configured, run `pnpm wiki:export --mode changed` after the doc update. +- The wiki exporter only owns `_repo-context/` in the external vault. It must never overwrite repo docs or maintained wiki pages outside that folder. +- Final task summaries should state whether docs were updated, which doc changed, and whether wiki export ran, was skipped, or failed. + +## Electron Debugging (CDP) + +- Start the Electron development app with: `nx serve electron-backend` +- Package-script equivalent: `pnpm run serve:backend` +- Electron is configured to start with: `--remote-debugging-port=9222` +- Connect Chrome DevTools Protocol tools to: `127.0.0.1:9222` +- For Electron automation/debugging tasks, use the `electron` skill +- Do not auto-open DevTools during normal CDP automation. In development, DevTools is opt-in via `ELECTRON_OPEN_DEVTOOLS=1`. +- If DevTools is open, `agent-browser --cdp 9222 ...` may attach to the DevTools page instead of the IPTVnator window. Symptoms: `tab list` shows `about:blank`, snapshots are empty, and screenshots are black. +- If that happens, inspect targets with `curl http://127.0.0.1:9222/json/list` and connect directly to the IPTVnator page websocket from the `webSocketDebuggerUrl` field. + +### Trace / Debug Startup + +- Full startup tracing: + +```bash +IPTVNATOR_TRACE_STARTUP=1 nx serve electron-backend +``` + +- Narrower trace flags: + - `IPTVNATOR_TRACE_IPC=1` traces renderer `window.electron.*` bridge calls + - `IPTVNATOR_TRACE_DB=1` traces DB worker requests and request-scoped DB events + - `IPTVNATOR_TRACE_SQL=1` traces SQLite statements in the main process and DB worker + - `IPTVNATOR_TRACE_WINDOW=1` traces BrowserWindow lifecycle and unresponsive events + - `IPTVNATOR_TRACE_RENDERER_CONSOLE=1` mirrors renderer console output into the Electron terminal + +- GPU/compositor debugging: + +```bash +IPTVNATOR_DISABLE_HARDWARE_ACCELERATION=1 nx serve electron-backend +``` + +- If local Nx state gets weird before a rerun: + +```bash +pnpm nx reset +``` + +### agent-browser (global install) + +```bash +agent-browser --cdp 9222 tab list +agent-browser --cdp 9222 tab 1 +agent-browser --cdp 9222 snapshot -i -c -d 4 +agent-browser --cdp 9222 screenshot /tmp/iptvnator-cdp.png +``` + +### Fallback + +```bash +npx --yes agent-browser --cdp 9222 tab list +``` + +### DevTools Workaround + +```bash +ELECTRON_OPEN_DEVTOOLS=1 nx serve electron-backend +curl http://127.0.0.1:9222/json/list +agent-browser connect ws://127.0.0.1:9222/devtools/page/ +agent-browser screenshot /tmp/iptvnator-cdp.png +``` + +## Radio / Audio Player + +M3U playlists can contain radio channels identified by the `radio="true"` attribute on `#EXTINF` lines. When a radio channel is selected: + +- The dedicated `AudioPlayerComponent` (`libs/ui/playback/src/lib/audio-player/`) renders instead of a video player +- The audio player always uses the built-in inline player — external player settings (MPV/VLC) are ignored +- The EPG panel is hidden (radio streams have no EPG data) +- The layout uses a cinematic hero pattern: the station logo is blurred as a full-area backdrop with a vignette overlay, and the artwork card + controls float above it +- Volume is shared with the video player via `localStorage` key `'volume'` +- Keyboard shortcuts: ArrowUp/ArrowDown (volume +/-5%), M (mute toggle) +- Radio detection in the video player template: `activeChannel.radio === 'true'` — this is a string comparison, not boolean + +Key files: +- `libs/ui/playback/src/lib/audio-player/audio-player.component.ts` — the audio player component +- `libs/ui/playback/src/lib/audio-player/audio-player.component.scss` — cinematic hero styling +- `libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.html` — template conditionals for radio vs video +- `libs/shared/interfaces/src/lib/channel.interface.ts` — `radio: string` field on Channel interface + +## Repo Skills + +- `iptvnator-ui-design` + Repository-specific UI design guidance for IPTVnator. + Use when working on channel rows, EPG views, settings surfaces, shared selection styles, or light/dark theme consistency. + File: `.codex/skills/iptvnator-ui-design/SKILL.md` + +- `iptvnator-theme-style` + Theme architecture, design token reference, shared SCSS library, portal header pattern, Electron drag region, and common styling mistakes. + Use when adding/changing CSS tokens, styling portal headers or sidebars, using shared SCSS mixins (`portal-layout`, `content-grid`, `portal-sidebar`), or auditing cross-portal visual consistency. + File: `.codex/skills/iptvnator-theme-style/SKILL.md` + +- `iptvnator-nx-architecture` + Repository-specific Nx monorepo structure, library placement rules, path alias guidance, and migration guardrails for portal/workspace/app code. + Use when deciding where code belongs, extracting code into libs, choosing imports, or refactoring Xtream/Stalker/Workspace boundaries. + File: `.codex/skills/iptvnator-nx-architecture/SKILL.md` + +- `iptvnator-sqlite-db-worker` + Repository-specific guidance for the Electron non-EPG SQLite worker, including worker boundaries, request-scoped DB progress events, and validation steps for slow DB operations. + Use when moving heavy database work off the main thread, adding worker-backed SQLite operations, or wiring loading/progress UI for Xtream and playlist DB flows. + File: `.codex/skills/iptvnator-sqlite-db-worker/SKILL.md` + +- `xtream-electron` + Repository-specific guidance for IPTVnator's Electron-first Xtream implementation, including feature/data-access boundaries, worker-backed DB flows, and Xtream loading/progress UX expectations. + Use when working on Xtream routes, store/data-source logic, or Electron-backed Xtream import/search/delete behavior. + File: `.codex/skills/xtream-electron/SKILL.md` diff --git a/CLAUDE.md b/CLAUDE.md index 68129166a..c060b18fa 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,6 +2,28 @@ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +## Plan Mode + +- When Claude Code is in Plan Mode and produces a final ``, it must also save that finalized plan as a Markdown file in the repo-root `.plans/` directory. +- Save only finalized plans. Do not write interim exploration, question turns, or draft revisions to `.plans/`. +- Use the filename pattern `YYYY-MM-DD-short-topic.md` such as `.plans/2026-03-12-channel-filtering.md`. +- If the intended filename already exists, append a numeric suffix such as `-2`, `-3`, and so on. + +## Documentation After Changes + +- After implementing a meaningful change, Claude Code must assess whether canonical repo docs need updates before considering the task complete. +- Meaningful changes include new or changed user-visible behavior, architecture or data-flow changes, non-obvious maintenance workflows, new setup/debugging steps, and new subsystem contracts or boundaries. +- Skip doc updates for trivial refactors with unchanged behavior, formatting-only edits, and isolated test-only changes. +- Prefer updating an existing authoritative doc before creating a new one: + 1. `README.md` for top-level developer or user workflows + 2. `docs/architecture/` for architecture, ownership, and behavior contracts + 3. the nearest module `README.md` for local usage or behavior +- Repo docs are canonical even when they were originally drafted by an LLM. External wiki pages are derivative or synthesis content unless explicitly promoted back into the repo. +- The external wiki sync is one-way by default: repo docs -> external wiki `_repo-context/`. +- If repo docs changed and `IPTVNATOR_WIKI_VAULT` is configured, run `pnpm wiki:export --mode changed` after the doc update. +- The wiki exporter only owns `_repo-context/` in the external vault. It must never overwrite repo docs or maintained wiki pages outside that folder. +- Final task summaries should state whether docs were updated, which doc changed, and whether wiki export ran, was skipped, or failed. + ## Project Overview IPTVnator is a cross-platform IPTV player application built with Angular and Electron, supporting M3U/M3U8 playlists, Xtream Codes API, and Stalker portals. @@ -54,6 +76,63 @@ pnpm run make:app nx run electron-backend:make ``` +### Electron CDP Debugging + +- Start Electron in dev mode with: `nx serve electron-backend` +- Package-script equivalent: `pnpm run serve:backend` +- The workspace is configured to always launch Electron with: `--remote-debugging-port=9222` +- Use CDP clients (Chrome DevTools Protocol tools) against: `127.0.0.1:9222` +- When the task is Electron automation/debugging, use the `electron` skill + +For startup tracing or white-screen debugging: + +```bash +IPTVNATOR_TRACE_STARTUP=1 nx serve electron-backend +``` + +Useful narrower flags: + +- `IPTVNATOR_TRACE_IPC=1` traces renderer `window.electron.*` bridge calls +- `IPTVNATOR_TRACE_DB=1` traces DB worker requests and DB progress events +- `IPTVNATOR_TRACE_SQL=1` traces SQLite statements in both main and worker connections +- `IPTVNATOR_TRACE_WINDOW=1` traces BrowserWindow navigation/load lifecycle +- `IPTVNATOR_TRACE_RENDERER_CONSOLE=1` mirrors renderer console logs into the Electron terminal + +For GPU/compositor debugging: + +```bash +IPTVNATOR_DISABLE_HARDWARE_ACCELERATION=1 nx serve electron-backend +``` + +If the Nx daemon gets into a bad state before rerunning Electron: + +```bash +pnpm nx reset +``` + +Use global `agent-browser` (preferred): + +```bash +# Verify CDP targets +agent-browser --cdp 9222 tab list + +# Switch to the app tab and inspect interactive elements +agent-browser --cdp 9222 tab 1 +agent-browser --cdp 9222 snapshot -i -c -d 4 + +# Capture debug artifacts +agent-browser --cdp 9222 screenshot /tmp/iptvnator-cdp.png +agent-browser --cdp 9222 trace start /tmp/iptvnator.trace.zip +agent-browser --cdp 9222 wait 1500 +agent-browser --cdp 9222 trace stop /tmp/iptvnator.trace.zip +``` + +If `agent-browser` is not in PATH, use: + +```bash +npx --yes agent-browser --cdp 9222 tab list +``` + ### Testing ```bash @@ -84,6 +163,16 @@ nx lint web nx lint electron-backend ``` +### Documentation And Wiki Export + +```bash +# Export a full canonical-doc snapshot into the external Obsidian vault +pnpm wiki:export --mode full + +# Export only the latest repo context into the external Obsidian vault +pnpm wiki:export --mode changed +``` + ## Architecture ### Monorepo Structure (Nx Workspace) @@ -206,6 +295,32 @@ The M3U playlist module handles traditional M3U/M3U8 playlists with support for └─────────────────────────────────────────────────────────────────────┘ ``` +**Radio Channel Layout** (when `channel.radio === 'true'`): + +``` +┌─────────────────────────────────────────────────────────────────────┐ +│ ┌─────────────┐ ┌────────────────────────────────────────────────┐│ +│ │ Sidebar │ │ Blurred backdrop (station logo) ││ +│ │ │ │ ┌──────────┐ ││ +│ │ │ │ │ Artwork │ ← cinematic hero layout ││ +│ │ │ │ └──────────┘ ││ +│ │ │ │ Station Name ││ +│ │ │ │ [LIVE] badge ││ +│ │ │ │ ⏮ ▶/⏸ ⏭ ← transport controls ││ +│ │ │ │ 🔊 ━━━━━━━━━ ← volume slider ││ +│ │ │ │ (no EPG panel) ││ +│ └─────────────┘ └────────────────────────────────────────────────┘│ +└─────────────────────────────────────────────────────────────────────┘ +``` + +Key radio behavior: +- Detection: `channel.radio === 'true'` (string from M3U `radio` attribute) +- The audio player always renders inline — `shouldShowInlinePlayer` is bypassed for radio +- EPG panel is conditionally hidden in the template when radio is active +- Volume is shared with video player via `localStorage` key `'volume'` +- Keyboard: ArrowUp/Down adjusts volume by 5%, M toggles mute +- Component: `libs/ui/playback/src/lib/audio-player/audio-player.component.ts` + Channel List Component Structure (parent coordinator pattern): ``` libs/ui/components/src/lib/channel-list-container/ @@ -407,6 +522,16 @@ This project uses modern Angular signal-based APIs and patterns. **ALWAYS** use - Built-in HTML5 player with HLS.js or Video.js - External players: MPV, VLC (via IPC to Electron backend) +**Radio Player**: + +- Dedicated audio player for channels with `radio="true"` M3U attribute +- Cinematic layout: blurred station logo as backdrop, floating artwork card, transport controls +- Always uses the built-in inline player — external player settings (MPV/VLC) are ignored for radio +- EPG panel is hidden for radio channels (radio streams have no EPG data) +- Volume synced with video player via shared `localStorage` key `'volume'` +- Keyboard shortcuts: ArrowUp/ArrowDown (volume), M (mute) +- Component: `libs/ui/playback/src/lib/audio-player/audio-player.component.ts` + **EPG (Electronic Program Guide)**: - XMLTV format support diff --git a/README.md b/README.md index e43703b51..bebe37717 100644 --- a/README.md +++ b/README.md @@ -21,38 +21,39 @@ The application is a cross-platform, open-source project built with Electron and ## Features -- M3u and M3u8 playlist support 📺 -- Xtream Code (XC) and Stalker portal (STB) support -- External player support - MPV, VLC -- Add playlists from the file system or remote URLs 📂 -- Automatic playlist updates on application startup -- Channel search functionality 🔍 -- EPG support (TV Guide) with detailed information -- TV archive/catchup/timeshift functionality -- Group-based channel list -- Favorite channels management -- Global favorites aggregated from all playlists -- HTML video player with HLS.js support or Video.js-based player -- Internationalization with support for 16 languages: - * Arabic - * Moroccan arabic - * English - * Russian - * German - * Korean - * Spanish - * Chinese - * Traditional chinese - * French - * Italian - * Turkish - * Japanese - * Dutch - * Belarusian - * Polish -- Custom "User Agent" header configuration for playlists -- Light and Dark themes -- Docker version available for self-hosting +- M3u and M3u8 playlist support 📺 +- Radio playlist support with dedicated audio player 📻 +- Xtream Code (XC) and Stalker portal (STB) support +- External player support - MPV, VLC +- Add playlists from the file system or remote URLs 📂 +- Automatic playlist updates on application startup +- Channel search functionality 🔍 +- EPG support (TV Guide) with detailed information +- TV archive/catchup/timeshift functionality +- Group-based channel list +- Favorite channels management +- Global favorites aggregated from all playlists +- HTML video player with HLS.js support or Video.js-based player +- Internationalization with support for 16 languages: + - Arabic + - Moroccan arabic + - English + - Russian + - German + - Korean + - Spanish + - Chinese + - Traditional chinese + - French + - Italian + - Turkish + - Japanese + - Dutch + - Belarusian + - Polish +- Custom "User Agent" header configuration for playlists +- Light and Dark themes +- Docker version available for self-hosting ## Screenshots: @@ -112,7 +113,7 @@ sudo emerge iptvnator-bin ### macOS: "App is damaged and can't be opened" -Due to Apple's Gatekeeper security and code signing requirements, you may need to remove the quarantine flag from the downloaded application: +Older unsigned macOS builds may require removing the quarantine flag from the downloaded application: ```bash xattr -c /Applications/IPTVnator.app @@ -148,14 +149,14 @@ sudo chmod 4755 chrome-sandbox Edit the desktop launcher file to add the `--no-sandbox` flag: 1. Find your desktop file location: - - **Ubuntu/Debian**: `~/.local/share/applications/iptvnator.desktop` - - **System-wide**: `/usr/share/applications/iptvnator.desktop` + - **Ubuntu/Debian**: `~/.local/share/applications/iptvnator.desktop` + - **System-wide**: `/usr/share/applications/iptvnator.desktop` 2. Edit the file and modify the `Exec` line: - ``` - Exec=iptvnator --no-sandbox %U - ``` + ``` + Exec=iptvnator --no-sandbox %U + ``` 3. Save the file and relaunch the application from your application menu. @@ -169,7 +170,7 @@ iptvnator --no-sandbox Requirements: -- Node.js with pnpm (via Corepack) +- Node.js with pnpm (via Corepack) 1. Clone this repository and install project dependencies: @@ -185,6 +186,51 @@ Requirements: This will open the Electron app in a separate window, while the Angular dev server will run at http://localhost:4200. +The equivalent Nx command is: + +``` +$ nx serve electron-backend +``` + +If you need to debug renderer freezes or GPU/compositor issues in Electron, you +can disable hardware acceleration for a run: + +``` +$ IPTVNATOR_DISABLE_HARDWARE_ACCELERATION=1 pnpm run serve:backend +``` + +If you need startup diagnostics for a white screen or a frozen route, you can +also turn on opt-in Electron tracing. These logs are written to the Electron +terminal output so they still help when the renderer DevTools never open: + +``` +$ IPTVNATOR_TRACE_STARTUP=1 pnpm run serve:backend +``` + +Nx equivalent: + +``` +$ IPTVNATOR_TRACE_STARTUP=1 nx serve electron-backend +``` + +Useful narrower flags: + +- `IPTVNATOR_TRACE_IPC=1` logs renderer `window.electron.*` calls reaching the + Electron bridge +- `IPTVNATOR_TRACE_DB=1` logs DB worker requests and request-scoped DB events +- `IPTVNATOR_TRACE_SQL=1` logs SQLite statements in both the main connection and + DB worker connection +- `IPTVNATOR_TRACE_WINDOW=1` logs BrowserWindow load, navigation, and + unresponsive events +- `IPTVNATOR_TRACE_RENDERER_CONSOLE=1` mirrors renderer console messages into + the Electron terminal output + +If the local Nx daemon gets into a bad state before rerunning Electron, reset it: + +``` +$ pnpm nx reset +``` + To run only the Angular app without Electron, use: ```