Commit Graph
2253 Commits
Author SHA1 Message Date
4gray ce0e61a92d docs: publish embedded MPV macOS blog post 2026-05-11 20:44:01 +02:00
4gray f922dd2d00 style: adjust size and remove unnecessary styles for action buttons
Entire-Checkpoint: f957cd9849e0
2026-05-10 23:37:15 +02:00
4gray a2ecdc358f fix(electron): resolve macOS external player app paths (#924)
* fix(electron): resolve macOS external player app paths

* fix(electron): make macos player executable mapping explicit
2026-05-10 23:36:35 +02:00
4gray 1ca291d35c chore(nx): update Nx to 22.7.1 (#923)
* chore(nx): update Nx to 22.7.1
Entire-Checkpoint: f957cd9849e0

* fix(ci): patch nx-electron package metadata copy
Entire-Checkpoint: f957cd9849e0

* fix(packaging): preserve electron package metadata
Entire-Checkpoint: f957cd9849e0

* fix(packaging): address package verifier review
Entire-Checkpoint: f957cd9849e0
2026-05-10 22:01:25 +02:00
4gray 6305dcf00e Add browser playback diagnostics and MPV/VLC fallback (#921)
* feat(playback): add codec diagnostics fallback
Entire-Checkpoint: f957cd9849e0

* fix(playback): address diagnostics review feedback
Entire-Checkpoint: f957cd9849e0

* fix(playback): ignore recoverable hls diagnostics
Entire-Checkpoint: f957cd9849e0

* fix(playback): polish diagnostic fallback banner
Entire-Checkpoint: f957cd9849e0

* fix(xtream): preserve live category search scope
Entire-Checkpoint: f957cd9849e0
2026-05-10 17:27:54 +02:00
4gray 5f4cf01467 fix(playback): avoid redundant VideoJS source resets (#920)
* fix(playback): avoid redundant VideoJS source resets

* fix(playback): clean up cleared VideoJS sources

* refactor(playback): use signal APIs in VideoJS player

closes #608
2026-05-10 15:32:00 +02:00
4gray 724e4b1ab3 feat(playback): add embedded mpv (macos) stream recording (#916)
* feat(playback): add embedded mpv stream recording
Entire-Checkpoint: f957cd9849e0

* fix(playback): address embedded mpv recording review
Entire-Checkpoint: f957cd9849e0

* fix(playback): track mpv recording auto-stop replies
Entire-Checkpoint: f957cd9849e0
2026-05-10 12:27:09 +02:00
4gray 935ed1b1a9 fix(lockfile): remove duplicate minimatch snapshot 2026-05-10 11:06:06 +02:00
dependabot[bot] e94617fe83 chore(deps): bump ajv from 6.12.6 to 6.14.0 (#783)
Bumps [ajv](https://github.com/ajv-validator/ajv) from 6.12.6 to 6.14.0.
- [Release notes](https://github.com/ajv-validator/ajv/releases)
- [Commits](https://github.com/ajv-validator/ajv/compare/v6.12.6...v6.14.0)

---
updated-dependencies:
- dependency-name: ajv
  dependency-version: 6.14.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-10 10:53:29 +02:00
dependabot[bot] c84d65016a chore(deps): bump rollup from 4.52.3 to 4.59.0 (#796)
Bumps [rollup](https://github.com/rollup/rollup) from 4.52.3 to 4.59.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.52.3...v4.59.0)

---
updated-dependencies:
- dependency-name: rollup
  dependency-version: 4.59.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-10 10:53:26 +02:00
dependabot[bot] 5d66a04d05 chore(deps): bump immutable from 5.1.4 to 5.1.5 (#807)
Bumps [immutable](https://github.com/immutable-js/immutable-js) from 5.1.4 to 5.1.5.
- [Release notes](https://github.com/immutable-js/immutable-js/releases)
- [Changelog](https://github.com/immutable-js/immutable-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/immutable-js/immutable-js/compare/v5.1.4...v5.1.5)

---
updated-dependencies:
- dependency-name: immutable
  dependency-version: 5.1.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-10 10:53:23 +02:00
dependabot[bot] a4fb202b62 chore(deps): bump svgo from 3.3.2 to 3.3.3 (#808)
Bumps [svgo](https://github.com/svg/svgo) from 3.3.2 to 3.3.3.
- [Release notes](https://github.com/svg/svgo/releases)
- [Commits](https://github.com/svg/svgo/compare/v3.3.2...v3.3.3)

---
updated-dependencies:
- dependency-name: svgo
  dependency-version: 3.3.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-10 10:53:20 +02:00
dependabot[bot] 62f904ec86 chore(deps): bump express-rate-limit from 8.2.1 to 8.3.0 (#810)
Bumps [express-rate-limit](https://github.com/express-rate-limit/express-rate-limit) from 8.2.1 to 8.3.0.
- [Release notes](https://github.com/express-rate-limit/express-rate-limit/releases)
- [Commits](https://github.com/express-rate-limit/express-rate-limit/compare/v8.2.1...v8.3.0)

---
updated-dependencies:
- dependency-name: express-rate-limit
  dependency-version: 8.3.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-10 10:53:17 +02:00
dependabot[bot] 23c74d6313 chore(deps): bump devalue from 5.6.2 to 5.6.4 (#818)
Bumps [devalue](https://github.com/sveltejs/devalue) from 5.6.2 to 5.6.4.
- [Release notes](https://github.com/sveltejs/devalue/releases)
- [Changelog](https://github.com/sveltejs/devalue/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sveltejs/devalue/compare/v5.6.2...v5.6.4)

---
updated-dependencies:
- dependency-name: devalue
  dependency-version: 5.6.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-10 10:53:14 +02:00
dependabot[bot] d6417c699d chore(deps): bump flatted from 3.3.3 to 3.4.2 (#827)
Bumps [flatted](https://github.com/WebReflection/flatted) from 3.3.3 to 3.4.2.
- [Commits](https://github.com/WebReflection/flatted/compare/v3.3.3...v3.4.2)

---
updated-dependencies:
- dependency-name: flatted
  dependency-version: 3.4.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-10 10:53:10 +02:00
dependabot[bot] 1ea40216ce build(deps): bump fast-uri from 3.1.0 to 3.1.2 (#912)
Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.0 to 3.1.2.
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](https://github.com/fastify/fast-uri/compare/v3.1.0...v3.1.2)

---
updated-dependencies:
- dependency-name: fast-uri
  dependency-version: 3.1.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-10 10:52:44 +02:00
dependabot[bot] 7da715c37f build(deps): bump @babel/plugin-transform-modules-systemjs (#915)
Bumps [@babel/plugin-transform-modules-systemjs](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-modules-systemjs) from 7.28.5 to 7.29.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.29.4/packages/babel-plugin-transform-modules-systemjs)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-modules-systemjs"
  dependency-version: 7.29.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-10 10:52:23 +02:00
4gray eb0da5951f Merge pull request #914 from 4gray/codex/fix-linux-window-identity
fix(linux): align packaged app identity
2026-05-09 20:11:07 +02:00
4gray 48463953db test(packaging): harden package identity regression
Entire-Checkpoint: f957cd9849e0
2026-05-09 19:28:35 +02:00
4gray 4a755b43ec Merge pull request #885 from sapireli/fix/xtream-catchup-server-timezone
fix(xtream): use server timezone when constructing catchup/timeshift URLs
2026-05-09 19:28:16 +02:00
4gray aead89e3e6 fix(xtream): keep category management available
Fixes #913
2026-05-09 18:34:57 +02:00
4gray 6cdd02f010 fix(linux): align packaged app identity
Entire-Checkpoint: f957cd9849e0
2026-05-09 16:22:37 +02:00
4gray 8b3b1c9bb7 chore: merge master into xtream timezone fix 2026-05-09 16:15:01 +02:00
4gray 134b5fb779 Merge pull request #911 from 4gray/codex/stalker-radio
feat(stalker): add radio support
2026-05-09 15:50:10 +02:00
4gray 0d93301520 fix(stalker): address radio review feedback
Entire-Checkpoint: f957cd9849e0
2026-05-09 13:08:41 +02:00
4gray 9261794b4a Merge pull request #902 from weeco/feat/xtream-xmltv-epg-fallback
feat(xtream): fall back to uploaded XMLTV when provider has no EPG
2026-05-09 13:06:51 +02:00
4gray 4020822b90 fix(xtream): prevent stale epg queue fetches 2026-05-09 12:08:14 +02:00
4gray ab905af285 feat(stalker): add radio support
Entire-Checkpoint: f957cd9849e0
2026-05-09 01:28:39 +02:00
4gray e9875f9f29 Merge pull request #903 from sapireli/search_all_fix
Fix Xtream section search across categories
2026-05-08 22:09:36 +02:00
4gray 3bafeb8377 Merge remote-tracking branch 'origin/master' into search_all_fix
# Conflicts:
#	libs/portal/xtream/feature/src/lib/live-stream-layout/live-stream-layout.component.html
2026-05-08 22:01:01 +02:00
4gray 6efa8b9072 fix(xtream): preserve live search playback sidebar
Entire-Checkpoint: f957cd9849e0
2026-05-08 21:05:10 +02:00
4gray 90cda8731c test(portal-shared-util): mock double-click setting 2026-05-08 20:17:18 +02:00
4gray f884c3479a Merge pull request #906 from TeddJohnson/codex/double-click-stream-start
feat: Add double-click stream open setting
2026-05-08 20:08:23 +02:00
4gray 268d4b9114 cover external player double-click workflow 2026-05-08 20:01:19 +02:00
4gray 5dbf258a2b refine double-click setting visibility 2026-05-08 19:51:06 +02:00
4gray e350a2ea96 fix double-click external playback handling 2026-05-08 10:59:52 +02:00
Tedd Johnson 626948f2f5 Add double-click stream open setting 2026-05-07 20:03:33 -07:00
Eliran Sapir a3a4c6b5ea Fix Xtream section search across categories 2026-05-07 17:42:29 -04:00
weeco 505e75b67e fix(xtream): address review feedback on XMLTV fallback PR
- pruneEphemeralMaps now uses getCached() so TTL-expired entries also
  drop their XMLTV preview / channel-id mapping, instead of clinging
  to them until the next explicit cache read.
- portal-channels-list attaches a .catch() to the now-async enqueue so
  any future internal rejection surfaces in the console rather than
  bubbling silently as an unhandled promise rejection.
- XtreamXmltvFallbackService binds the bridge receiver when calling
  the extracted function reference, in case a preload wrapper relies
  on `this`.

Adds a regression test for the TTL-aware prune.
2026-05-07 08:52:59 -07:00
weeco e751e82c07 feat(xtream): fall back to uploaded XMLTV when provider has no EPG
Live TV channels in Xtream playlists go blank whenever the provider's
get_short_epg returns nothing, even when the user has working XMLTV
URLs in Settings. The XMLTV pipeline already populates epg_programs
but only the M3U module was reading it.

Wire those uploads up as a fallback for Xtream too: when the provider
returns nothing for a channel with an epg_channel_id, look it up in
the local table. A settings toggle flips the priority for users whose
curated XMLTV is better than the provider's auto guide.

EpgQueueService.enqueue() became async to batch the XMLTV lookup once
per viewport change. To keep the queue consistent under fast scroll,
all shared-state mutations now happen behind a generation counter so
only the latest call commits. Per-method bridge gating in the new
XtreamXmltvFallbackService keeps each path working when the preload
exposes only one of the two endpoints.
2026-05-07 08:52:59 -07:00
4grayandClaude Opus 4.7 f9843fcb0c docs(blog): add release notes for IPTVnator v0.21
Covers the embedded MPV player on macOS, toggleable Live TV sidebars,
command palette upgrades, and module fixes. Credits the Telegram tip
about using IINA as the external player and links the related GitHub
issues.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 23:39:23 +02:00
4gray 8c0e038b7d chore: bump version to 0.22.0
Entire-Checkpoint: f957cd9849e0
2026-05-06 23:26:53 +02:00
4gray ed6302c059 feat(m3u): add channel list sorting controls
Entire-Checkpoint: f957cd9849e0
v0.21.0
2026-05-06 00:14:52 +02:00
4grayandClaude Opus 4.7 7478ea8665 docs(embedded-mpv): document renderer architecture and reactivity rules
Capture the audit findings and refactor outcome in the canonical embedded-mpv
architecture doc so the next person to extend the player does not re-introduce
the same class of regression.

New "Renderer Architecture And Reactivity" section covers:

- The post-refactor file layout (format utils, shortcuts, overlay-visibility,
  ui-state, session-controller, view component) and what each owns.
- The bounds compositing strategy: HIDDEN_BOUNDS for modal overlays,
  partial bottom cutout for control popovers, full host rect otherwise —
  plus why (NSView paints over WebContents, z-index is unwinnable).
- The reactivity rule learned from the audit: any signal read inside an
  effect that feeds a one-shot side effect must be wrapped in untracked().
  Only re-trigger sources stay tracked.
- A short ledger of the four bugs from the audit (support write loop,
  volume-tracked session restart, scheduleControlsHide transitive deps,
  stalled-tracker 2 Hz no-op) so they do not get reintroduced.
- IPC safety notes: gate on sessionId() not session()?.id; guardIpc
  swallows addon-side throws.
- Pointer to the powerSaveBlocker integration.

Also documents the bundle 3 native surface additions (sid, speed,
video-aspect-override observers and exports, capability probe via
EmbeddedMpvSupport.capabilities) so renderers can feature-detect against
older addon binaries.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: f957cd9849e0
2026-05-05 16:45:17 +02:00
4grayandClaude Opus 4.7 42f718568e fix(embedded-mpv): tighten effect signal-tracking to prevent latent re-run bugs
Audit followup to the support-loop and volume-restart fixes. Two more
effects pulled in transitive signal deps that would have caused the same
class of regression the next time the surrounding helpers grew.

1. Component session-fan-out effect: the body called
   scheduleControlsHide(), which reads isPlaying/menus.anyOpen/statusLabel/
   controlsVisible. Those became tracked deps of the effect, so opening a
   popover, pausing, or hovering re-ran the whole body — re-emitting
   timeUpdate. If a parent ever wires timeUpdate back into
   playback.startTime as a "resume where I left off" feature, this would
   have been the next stream-restart bug. Wrap the side-effect block in
   untracked() so the effect only listens to session changes.

2. Controller stalled-tracker effect: tracked the full session signal
   even though only status was needed. The session payload updates ~2 Hz
   during playback (positionSeconds advances), making the effect re-run
   constantly to call a no-op. Add a sessionStatus computed and track
   that instead — fires only on real status transitions.

No behavior change for current users; both fixes are preventative.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: f957cd9849e0
2026-05-05 16:31:25 +02:00
4grayandClaude Opus 4.7 c12b660594 fix(embedded-mpv): do not restart the stream on every volume change
Same root cause as the loading-loop fix: the session-creation effect
read this.volume() while building startSession's initialVolume argument,
which made volume a tracked dependency of the effect. Each volume tick
re-ran the effect, the cleanup disposed the active session, and a fresh
one was created — which for VOD/series meant restarting playback from
the beginning.

Read volume via untracked() inside the effect. The value is only needed
once at session creation; subsequent volume changes flow through
controller.applyVolume() and never go near the effect.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: f957cd9849e0
2026-05-05 10:55:09 +02:00
4grayandClaude Opus 4.7 6ab62cfd8d fix(embedded-mpv): stop re-setting support inside startSession (infinite reload loop)
Regression introduced in the bundle 3 refactor. After calling
prepareEmbeddedMpv, the controller wrote the response back into
this.support — but the component's session-creation effect tracks
this.support(), so updating it cleaned up the just-created session and
ran startSession again, which prepared again, set support again, and so
on. Net effect: endless "Loading stream…" spinner because every session
was disposed before MPV could finish loading the file.

The initial loadSupport() in the constructor already populates support
(including capabilities). Drop the redundant set in startSession; leave
a comment explaining why so it does not get re-added.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: f957cd9849e0
2026-05-05 10:41:59 +02:00
4grayandClaude Opus 4.7 b5dbc33e62 fix(embedded-mpv): make slider track and thumb visible
The timeline and volume sliders were rendering invisibly because:

- --embedded-mpv-accent resolved to var(--mat-sys-primary) with no
  fallback. If the Material 3 theme tokens did not cascade into the
  component scope, the variable was empty and both the thumb and the
  Firefox progress fill rendered with no color.
- The track contrast was 22% of var(--mat-sys-on-surface) which has the
  same scoping fragility on top of being subtle even when it does
  resolve.
- The thumb had no border, so even when accent was present it could
  blend into similarly-toned popover backgrounds.
- The played portion of the timeline had no fill in Chromium because
  ::-webkit-slider-runnable-track does not support a native progress
  state.

Fixes:

- Add hard fallbacks on every theme-token reference (accent falls back to
  #7dd3fc, surface to #0f1620, outline-variant to a translucent white).
- Add --embedded-mpv-track and --embedded-mpv-thumb-ring as theme-
  independent CSS variables so the slider stays legible regardless of
  the parent theme provider.
- Give the thumb a 2 px white ring border + a stronger drop shadow so it
  reads on any background (panel glass, dark backdrop, accent-coloured
  area).
- Implement played-progress fill via a linear-gradient on
  ::-webkit-slider-runnable-track keyed off a CSS variable
  --slider-progress, set per-slider from the template based on the
  current playback position / volume. Firefox uses native
  ::-moz-range-progress.
- Tidy disabled state styling so live-stream timelines (no duration)
  are dim but still visible.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: f957cd9849e0
2026-05-05 10:33:18 +02:00
4grayandClaude Opus 4.7 9424dedafc fix(embedded-mpv): stop crashing on IPC for not-yet-created sessions
The renderer was reading session.id and forwarding it to the addon, but
during the loading window that id is the placeholder
"embedded-mpv-starting" set by createLoadingSession. If the user adjusted
volume, seeked, or toggled audio/subtitle/speed/aspect before the addon's
createSession returned the real id, that placeholder id reached the
addon — and the addon's getSessionOrThrow threw a raw std::runtime_error
which libc++abi terminated the process on.

Two fixes, defense in depth:

1. Renderer (session controller): use the canonical sessionId() signal,
   which is null until the addon hands back a real id, as the gate for all
   IPC calls. Wrap every IPC call in a guardIpc helper that swallows
   addon-side throws so a torn-down session or race won't surface as an
   uncaught promise rejection.

2. Native (embedded_mpv.mm): change getSessionOrThrow to take a
   Napi::Env and throw Napi::Error::New(env, ...) instead of
   std::runtime_error. node-addon-api converts Napi::Error to a JS
   exception cleanly; the previous std::runtime_error escaped the C++
   frame and aborted the process when the addon was built without
   NAPI_CPP_EXCEPTIONS translation. Refactor splits findSession (returns
   nullptr) from getSessionOrThrow (env-aware) so call paths that just
   probe a session's existence don't pay the throw cost.

The native fix needs an addon rebuild to take effect; the renderer fix
prevents the crash trigger immediately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: f957cd9849e0
2026-05-05 10:29:23 +02:00
4grayandClaude Opus 4.7 126025aa41 fix(embedded-mpv): expose popover area by shrinking MPV view, not just hiding
Same root cause as the modal-dialog occlusion: control popovers (volume,
audio, subtitle, speed, aspect) extend upward from the controls strip into
the area covered by the MPV NSView. They render in DOM but the native view
paints over them.

Replace the simple boolean overlayActiveProvider with a richer
boundsProvider closure on the session controller. The component drives it
from both the modal overlay state and the popover menu state:

- Modal dialog open (command palette, MatDialog) -> HIDDEN_BOUNDS, MPV
  fully off-screen so the dialog has the whole window.
- Popover menu open -> shrink MPV from the bottom by 300 px so the popover
  region lives in DOM-receiving space; video keeps playing in the upper
  region instead of disappearing entirely.
- Otherwise -> full host bounds.

Bounds-resync effect now tracks menus.anyOpen() in addition to
overlayActive() so opening or closing a popover triggers an immediate
re-sync.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: f957cd9849e0
2026-05-05 10:16:33 +02:00