Files
arr/.impeccable/surfaces/web-src-main-ts.md
T
Miguel Palhas 043ebffa1c feat(web): series and episodes in unified search
In-library hits now read as whatever they are: movies open the release
deck as before, series hits render display-only until issue 129's detail
view gives them a link target, and an episode hit reads as its series
plus SxxEyy plus the episode title. TMDB results show TV alongside film,
and the add panel filters roots by kind; a series adds the one §4.1
add-time choice, auto_track, stated plainly: future seasons are tracked
automatically, past seasons are not.
2026-08-23 18:00:54 +01:00

4.7 KiB

version, slug, primary_target, related_targets
version slug primary_target related_targets
1 web-src-main-ts web/src/main.ts
web/index.html
web/src/search.ts
web/src/releases.ts
web/src/library.ts
web/src/style.css

Surface: unified search + release deck + library (web/src/main.ts, §9.2 + §9.3 + §4.2)

Mode: Operate. The operator finds or adds a title without knowing which of the two they are doing, picks a release from decisions, not name dumps, and reads the library as derived status, not flags.

  • Audience: the household operator; desktop mostly, phone sometimes.
  • Task: one rail-mounted command input. Typing swaps the current surface for the search deck; clearing or Esc returns to the board. "/" focuses from anywhere.
  • Structure (pinned by DESIGN.md §9.2): IN LIBRARY group first, ON TMDB below, engraved micro-label headings, machined rows, chips on the right.
  • Add flow: inline panel under a TMDB row of either kind — root radio cards (audience name, policy name, path), main pre-selected, one confirm. Never a separate page. A series adds the one §4.1 add-time question: an auto-track pressed control (default on) with the plain line "future seasons are tracked automatically; past seasons are not", echoed in the added confirmation.
  • Release deck (§9.3, issue #31): a library row opens the buckets view. ELIGIBLE leads with fixed-width attribute chips in aligned mono columns (rem-width .cw-* classes shared by chips and the column header, so the pseudo-table survives flex wrapping); WAIVED and REJECTED collapse to counts behind cyan show/hide toggles. Release name is a secondary truncated line, full string plus indexer/date/bytes on row expand. Every waived/rejected row carries a verdict chip naming the rule. Grab is its own control per row; on a waived row it is "waive + grab" and writes the per-title override (rule→override mapping in releases.ts — bookkeeping, never policy; verdicts always come from the API). Esc steps back one layer: deck → search results → board.
  • Removal (§7.4, issue 104): REMOVE is a quiet control in the deck head, never a row affordance — a dense list is the wrong place for a delete. It opens one inline confirmation carrying the evidence first (file count, total size, the §7.4 folder as reported by /api/movies/{id}/files), then the decision, then the cost. "delete files from disk" is a separate toggle that starts OFF and stays disabled when nothing is on disk or the file list cannot be read; armed, the panel, its toggle word, the note and the confirm button all turn caution amber, and the confirm reads "remove and delete files" instead of "remove from library". The note says what does not happen either: the torrent keeps seeding (§7.3). Esc abandons the confirmation before it abandons the deck. On success the deck closes and the surface it opened over repaints, so a removed title never lingers in a list.
  • Library view (§4.2, issue #32): the LIBRARY rail control opens the library deck — SERIES then MOVIES groups. Status is derived and only displayed (§4.2 status chips in the channel-violet/neutral family for series, state chips for movies); intent is wanted at the leaf and no surface offers a monitored flag. Default set = airing + incomplete series and wanted-and-missing movies; everything satisfied collapses behind ONE cyan toggle carrying its count. A waived import reads honestly as a dashed amber chip ("english, no dub"). A movie row opens the release deck over the library and Esc returns there; series rows are inert until #39. Esc layering uses capture + stopImmediatePropagation — three surfaces listen for Escape on the same window.
  • Manual intake: magnet / .torrent input routes to a MANUAL GRAB panel showing parsed display name and btih; magnet grab wiring is issue #22, and the panel says so honestly.
  • Constraints: 250 ms debounce, AbortController cancellation, token-gated CSS, cyan for interaction only, dead-air rule (no idle animation), no horizontal scroll at any viewport (§9.3 acceptance criterion).
  • Unified search covers both kinds (issue 130): in-library hits read as whatever they are — a movie row, a series hit (display-only until the detail view of issue 129 exists) and an episode hit rendered as its series, an SxxEyy chip and the episode title in sans beside it. TMDB rows show TV alongside film; the "in library" dedup spans movies and series.
  • Unresolved: releases land in the persisted store only once the daemon consumes search commands (#68-adjacent); episode hits have no link target until issue 129's series detail view exists — they render display-only for now; per-season and per-episode library actions are #39; attention queues surface is #33.