Commit graph

25 commits

Author SHA1 Message Date
Natalie
ee3da4e101 perf(watch-history): stop the background poll freezing the main thread
The 8s watch-history poll ran refresh() on the main actor, which read and
JSON-decoded the unioned watch log THREE times (playedPaths, resumePositions,
episodeProgress each re-read) and called MediaPaths.toRemote() per event — and
every toRemote rebuilt ProcessInfo.environment (~22µs each, the whole env dict
is reconstructed on every access) plus a homeDirectory lookup. A live sample
caught the main thread 100% in this path; the app sat at 78–113% CPU.

- Cache MediaPaths.remoteRoot / mappings (process-constant) → kills the
  per-call env-dictionary rebuild storm.
- WatchHistory.derivedState(): read+decode the log ONCE, feed all three
  derived computations → 3× fewer reads/decodes per refresh.
- WatchHistoryController.refreshAsync(): the background poll now parses off the
  main thread on a utility task and only assigns the small results on main.

Settled CPU drops from ~78% sustained to ~0% idle.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 01:44:06 -04:00
Natalie
40188f85a9 feat(offline): ⤴︎ priority download lane — user picks jump the warmup
On-demand downloads (e.g. goon clips picked in the Adult collection list) now
take priority over the background warmup plan instead of waiting behind it or
starting a competing rsync:

- new priority lane (priorityEpisodes/priorityCount/enqueuePriority) drained
  before each plan item and immediately when the cache is idle
- fetchFile routes through the lane when a warmup is already running (was: a
  second concurrent rsync that also stomped the queue UI), and awaits completion
- per-episode fetch extracted to fetchOne(), shared by plan + priority drains
- status line shows '⤴︎N prioritized'; prioritizeFetch()/awaitDownload() expose
  it for callers

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 01:06:46 -04:00
Natalie
3c67b547c6 fix(adult): 🔒 terminate ffprobe options with -- in duration probe
Defense-in-depth against option injection: a library path beginning with '-'
could be parsed as an ffprobe flag. Paths are always absolute today so it isn't
reachable, but '--' makes it safe regardless. Not command injection: $p is a
double-quoted expansion (contents not re-evaluated) and paths arrive as stdin
data, never on a command line — documented inline.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 01:00:02 -04:00
Natalie
eb0d75a126 feat(adult): ⏱ show clip length in collection detail list
Each clip row in the adult collection detail view now shows its runtime, and
the header shows total runtime of the queued set (for planning a session of a
given length). Durations are probed in one background SSH batch via ffprobe on
black (NUL-delimited paths over stdin, so the eporner filenames with spaces/
quotes/brackets pass verbatim), debounced on filter and capped at 400 per batch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 00:56:59 -04:00
Natalie
ee7efad888 feat(adult): 🍿 collection detail view — clip checklist + offline download
Tapping a collection card on the Adult page now opens a detail view listing
every clip in that collection (goon, pmv, etc) instead of silently firing the
whole set at a host with nothing cached. Each row shows:
- queued state as a tickable checklist (build a session clip by clip)
- freshness / last-played
- offline-cached state, with a per-clip download-to-offline button

Plus a title filter (find e.g. a specific 'brain rot'/gooner clip), queue-all-
fresh, download-all-queued-offline, and play-queued. Downloads land in the
offline cache where the new star/trash row controls manage them. Quick-play the
old fire path stays on the card context menu.

Core: PornCollectionService.clips()/title() expose the full per-collection clip
list with freshness; PlaylistController gains single-item checklist queue ops
(isQueued/addToQueue/removeFromQueue) and pornClips().

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 00:50:05 -04:00
Natalie
4a2ceb9781 feat(offline): inline star-to-keep and trash-to-cull on cache rows
Surface the existing pin (keep-from-cull) and per-file delete actions as
visible inline buttons on each offline cache row instead of context-menu-only:
a star toggles protection from auto-cull (and restore-if-missing), a trash
culls that file early. Aligns wording/icons to the star metaphor.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 00:12:41 -04:00
Natalie
1d01adda2d feat(@applications/tv-anarchy): add black-watchlog sync for in-app playback tracking
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-10 04:00:48 -07:00
Natalie
e447f0a8f6 feat(@applications): add bridge deployment scripts
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-09 22:22:56 -07:00
Natalie
83a21ca105 feat(library): optimize scan merging with cached metadata
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-09 22:16:25 -07:00
Natalie
0a4cde36d1 feat(devices): add dependency issue warnings
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-09 21:57:08 -07:00
Natalie
ca1871f5dd feat(@applications/tv-anarchy): add roku device support
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-09 21:37:34 -07:00
Natalie
4466ff72cd feat(@applications/tv-anarchy): implement parallel fleet completion modules
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-09 21:30:14 -07:00
Natalie
a86e68c525 feat(apps): add fleet engine mesh core integration
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-09 21:23:36 -07:00
Natalie
7ff780fe56 feat(apps/tv-anarchy): add restart command support
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-09 21:17:10 -07:00
Natalie
8f12f470b7 feat(metadata): add local llm title refiner integration
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-09 21:10:47 -07:00
Natalie
b44b5a2d1a feat(@applications): add adult content browsing tab
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-09 19:51:12 -07:00
Natalie
68e107b03a feat(devices): per-device system-load badge (low/med/high) on Devices list
Sample every HostStatsProvider target's load while the Devices tab is
visible (gated like the existing detailed/detailVisible pollers), keyed
by device id in PlayerController.hostStatsByID. DevicesView renders a
capsule badge from load1/cores: <0.6/core low, <1.0/core med, else high.
Only SSH/mpv devices report stats; others show no badge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 14:07:45 -07:00
Natalie
9e38cf9f48 feat(core): player/playlist/porn-service rework + repo paths 2026-06-09 05:50:02 -07:00
Natalie
117e234a3c feat(core): offline cache, bandwidth policy, now-playing, notifications + torrent rework 2026-06-09 05:50:01 -07:00
Natalie
d8bc6c621e feat(library): show grouping, local-LLM grouper, content IDs, watch state + registry ingest 2026-06-09 05:50:01 -07:00
Natalie
6e9bccb992 refactor(fleet): rename Host→Device — DeviceConfig model + Devices UI, drop HostConfig/HostsView 2026-06-09 05:50:01 -07:00
Natalie
7ea1dad7b6 feat(vpn): VPN subsystem — OVPN profile/credential stores, controller, settings UI + parser tests 2026-06-09 05:50:01 -07:00
Natalie
0cc33e30b6 feat(queue): add test-isolated queue state directory
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-08 22:49:38 -07:00
Natalie
b8b148b788 feat(library): add queue context menu for shows
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-08 22:40:53 -07:00
Natalie
92b38b1bae refactor(tv-anarchy): rename PlumTV→TVAnarchy and land session work
Renames Sources/PlumTV→TVAnarchy and PlumTVCore→TVAnarchyCore (the rename
the auto-commit service couldn't stage — it git-add'd the old, now-gone
paths and aborted every cycle), and commits the accumulated work:

- Library: black-built index fast path (LibraryIndex + scanFromIndex) with
  NFS-walk fallback; incremental --add on download-complete; mtime staleness
  gate; loose-file series-collapse fix; determinate scan/index progress.
- Cover art: keyless TVmaze cartoon-vs-live-action disambiguation (type/year).
- Player: sleep timer (timed + end-of-episode); visibility-gated polling.
- Home: Continue Watching cover art + live refresh; Recently Added; adult gate.
- Logs: multi-line selection + copy; truncated giant tx-list errors.
- Hover previews (opt-in) via black ffmpeg + scp.

Also gitignores foreign project trees (governor/mcp/fleet/recommender) that
sit in this directory but belong to their own repos.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 22:04:22 -07:00