Commit Graph
100 Commits
Author SHA1 Message Date
Dark-Alex-17 7d1ff86c68 feat(readarr): add the add author UI
Renders the author search box, the search results table, and the
multi-step add confirmation prompt with its five dropdown popups.

The prompt's per-field highlighting is conveyed purely by style, which
render_to_string_with_app discards, so the highlight mapping is extracted
into add_author_prompt_highlights and unit tested per selection step.

Enriches the fully populated author search fixture with a second result
that is absent from the library, so both branches of the in-library
marker render in one snapshot and every table column carries a value.
2026-09-03 18:03:12 -06:00
Dark-Alex-17 7500e2da24 feat(readarr): add the delete book handler
Handles the delete book prompt opened from the author details view,
toggling whether to delete files on disk and whether to add a list
exclusion before confirming.

Backing out of the prompt resets both toggles, so preferences from an
abandoned delete cannot leak into the next one.
2026-09-03 17:29:31 -06:00
Dark-Alex-17 6a7f9fe0da feat(readarr): add the delete author handler
Handles the delete author prompt, toggling whether to delete files on
disk and whether to add a list exclusion before confirming.

Backing out of the prompt resets both toggles, so preferences from an
abandoned delete cannot leak into the next one.
2026-09-03 17:18:48 -06:00
Dark-Alex-17 dc4b11cf1b feat(readarr): add the edit author handler
Handles the multi-step edit prompt covering monitored, monitor new
items, quality profile, metadata profile, path, tags, and confirmation.

The prompt can be opened from either the author list or the author
details view, so the originating block is threaded through to the
sub-block pushes and Esc returns to the view the user came from.
2026-09-03 17:07:53 -06:00
Dark-Alex-17 ab9645dee9 feat(readarr): add the add author handler
Handles the add author search input, search results, and the multi-step
add prompt covering root folder, monitor, monitor new items, quality
profile, metadata profile, tags, and confirmation.

Selecting a search result whose foreign author id already exists in the
library routes to the already-in-library popup instead of the add
prompt, so a duplicate add cannot be submitted.
2026-09-03 16:52:39 -06:00
Dark-Alex-17 da6c9e7b66 fix(ui): render detail popup labels in bold
Span::style assigns rather than patches, so chaining it after bold()
discarded the modifier that bold() had just set and every detail popup
label rendered plain. Apply the modifier to the style itself instead.

Snapshots compare rendered text and cannot observe styling, so this is
pinned by asserting the label span's modifier directly.
2026-09-03 16:31:12 -06:00
Dark-Alex-17 a311e2b895 fix(readarr): stop appending stray colons to the edition overview
Every line of the edition details popup was parsed as a label and a value,
so a line carrying no colon had one appended to it. A multi-line overview
therefore rendered with a spurious colon at the end of each continuation
line, and Goodreads sourced descriptions, which use CRLF, turned their
blank lines into a lone colon.

Split each line on the first colon only, leave a line without one
unlabelled, and trim the trailing carriage return so a CRLF blank line
renders as a real paragraph break.

Building the line is now a named function so its branches can be asserted
directly. Rendered text discards the carriage return, so a snapshot alone
cannot tell the trimming apart from leaving it in place.

A continuation line that happens to contain a colon is still styled as a
label. Telling those apart needs the details to be built as styled lines
rather than flattened to text and parsed back.
2026-09-03 13:20:21 -06:00
Dark-Alex-17 61a18cb222 fix(readarr): move the book file delete to the File tab
Pressing Del on the Editions tab opened a delete prompt operating on the
currently selected book file, which is not visible from that tab. On the
File tab, where the book files are listed, Del did nothing even though the
tab advertised a "delete book file" hint.

Gate the delete on the File tab instead and drop the now inaccurate hint
from the Editions tab clue set.

A Readarr edition carries no file id, unlike a Lidarr track, so the book
files live in their own table and the delete cannot be driven from the
editions table.
2026-09-03 13:11:51 -06:00
Dark-Alex-17 280e691a94 feat(readarr): render the edition details popup
Draw the edition details popup over the book details view. The popup body is
the scrollable text the book details handler builds from the already loaded
edition row, so it needs no tabs and no network call.

The text styling is extracted into a named function so both branches are unit
tested, and the shared test fixture now holds the real field lines instead of a
placeholder, which exercises the scroll offset and the values that themselves
contain a colon.
2026-09-03 12:18:56 -06:00
Dark-Alex-17 b4c6994362 feat(readarr): render the book details popup
Draw the book details popup over the author details view, with the editions
table, book history, the book file info tab, and the manual search releases
table, plus the automatic search, delete book file, download release, and
history details prompts.

Edition row styling is extracted into a named function so each branch is unit
tested; text snapshots discard colour and cannot see it. The shared test
fixture now populates the edition format, ISBN13, ASIN, and publisher, and the
book file media info, so the rendered columns are exercised rather than blank.
2026-09-03 12:12:03 -06:00
Dark-Alex-17 d97c20d5ac feat(readarr): reach the book file info tab from the book details tabs
The book details handler already accepted the book file info block, but the
tab state declared only three tabs, so left and right could never reach it.
Add the File tab between History and Manual Search, backed by a new context
clue static covering refresh, delete book file, and esc.
2026-09-03 12:00:40 -06:00
Dark-Alex-17 751ff6ecf5 feat(readarr): scroll and dismiss the edition details popup
Add EditionDetailsHandler, the single block popup opened from the editions
table. It owns the arrow, Home and End scrolling over its ScrollableText body,
and the Esc that pops the popup and clears the edition details modal.

The handler is nested under BookDetailsHandler, which claims the block ahead
of its own tables. It never sees the keypress that opens it, so it performs no
build, and it dispatches no network events: the popup is assembled from an
already loaded row.

Scrolling is implemented rather than stubbed. The body is mostly the edition
overview, which routinely overflows the popup, so empty scroll methods would
leave the arrow keys dead on the longest text in the view.
2026-09-03 11:51:20 -06:00
Dark-Alex-17 14deed6b81 feat(readarr): handle the book details tabs and open the edition details popup
Add BookDetailsHandler, covering the editions, history and manual search
tables, the automatic search, manual download and delete book file prompts,
and tab movement across the book details modal.

Selecting an edition builds the EditionDetailsModal client side from the
already loaded row and pushes the popup block. Readarr has no edition detail
endpoint, so there is no network request and no event to dispatch.

The delete book file prompt is guarded on the book files table being
populated. Unlike Lidarr, where a track row carries its own file id, an
edition carries none and the file id comes from a separate table that can be
empty while editions are present.
2026-09-03 11:43:49 -06:00
Dark-Alex-17 baf74d95e1 fix(readarr): render the update all authors confirmation prompt 2026-09-03 01:49:28 -06:00
Dark-Alex-17 5480514b12 fix(readarr): drop the always-empty author type column from the authors table 2026-09-03 01:46:44 -06:00
Dark-Alex-17 a8d13ae5c8 feat(readarr): render the author details view
Add AuthorDetailsUi: the author description pane plus the three author info
tabs (Books, History, and Author Search), along with the history item details,
automatic search, update and scan, and manual search confirmation popups.
LibraryUi now accepts and draws it over the authors table.

The description pane omits the Disambiguation and Type lines that the Lidarr
equivalent renders. GET /author returns neither key, so both lines would be
blank on every record. The books table drops the Type and Duration columns for
the same reason, since books have no type and no duration, and renders Files as
the book file count over the total book count.

Land create_history_event_details together with this first caller so it is not
committed as an unused function.

Extract decorate_book_row_with_style rather than inlining the row styling in
the table closure, matching decorate_author_row_with_style in the sibling
library view. Rendering to a string discards colour, so the styling branches
are only reachable by tests through a named function.
2026-09-03 01:41:01 -06:00
Dark-Alex-17 d1d5033710 test(readarr): snapshot the Readarr context row, loading, and empty states
The stats, downloads, and logo panes of the Readarr context row had no test
exercising them. Add snapshots for the populated, loading, and empty variants
of the context row, plus loading and empty variants of the tab view.
2026-09-03 01:05:43 -06:00
Dark-Alex-17 fb465b06f8 feat(readarr): handle key events for the author details view 2026-09-03 00:55:36 -06:00
Dark-Alex-17 06e2d7841e feat(readarr): handle key events for the authors library table
Add LibraryHandler, which owns the authors table and its sort, search,
and filter overlays through TableHandlingConfig, along with the add,
edit, toggle monitoring, update all, and refresh key actions and the
delete prompt. Dispatch into it from ReadarrHandler and add the main tab
left and right movement helper.

authors_sorting_options offers eight sorts: name, status, quality
profile, metadata profile, books, size, monitored, and tags. It omits
the type and tracks sorts that the artists table has. GET /author never
returns authorType, so that column would be empty on every row, and
author statistics carry no track count.

Also cover the Readarr arm of handle_events, which was previously
unreachable from any test: neutering the arm entirely left the suite
green.
2026-09-02 16:57:47 -06:00
Dark-Alex-17 d6deb6eea2 feat(readarr): fetch data on tick for the active block
Give dispatch_by_readarr_block a real match so each view requests what it
needs, and refresh the shared metadata on first render and on every poll
tick. Until now the Readarr tab rendered but never fetched anything.

Guard the conditional arms the way the other servarrs do: the manual
author search only fetches when no releases are cached, book history only
when the books table is populated, and the manual book search only when
the book details modal exists with no cached releases.

Add the selection id helpers the arms read from, named to avoid colliding
with the equivalents the other servarrs already define on App.

Book edition details gets no arm on purpose. There is no endpoint to fetch
a single edition, and the popup is fully populated before it opens.
2026-09-02 16:32:06 -06:00
Dark-Alex-17 dbd84d929d feat(readarr): edit the shared indexer settings and expose the command on the CLI 2026-09-02 15:37:25 -06:00
Dark-Alex-17 0867ae918e feat(readarr): fetch the shared indexer settings and expose them on the CLI
The fetched settings are only written into app state when nothing is
already held there, so a refresh landing while the user has the settings
prompt open cannot overwrite edits in progress.

The fixtures give every field a distinct value. Settings whose fields
all share one value cannot detect two of them being mapped to each
other's keys.
2026-09-02 13:52:26 -06:00
Dark-Alex-17 cd5ef8e093 feat(readarr): test all indexers and expose the command on the CLI
Results come back keyed only by indexer id, so each one is joined
against the cached indexer list to recover a display name, and its
validation failures are flattened into a single line for the results
table.

The endpoint reports failures with a non-2xx status, so the request
ignores the status code and parses the body either way. When the
request itself fails the results table is replaced with an empty one
rather than being left showing the previous run.
2026-09-02 13:46:36 -06:00
Dark-Alex-17 f4fd8516a6 feat(readarr): test an indexer and expose the command on the CLI
Fetch the indexer's full details, then post them back verbatim to the
test endpoint. The payload round-trips through serde_json::Value so the
fields Indexer does not model, such as infoLink and the per-field label
and type metadata, survive the round trip intact.

A successful test returns an empty JSON object and clears
indexer_test_errors; a failure returns an array whose first entry
carries the error message. The test endpoint reports failures with a
non-2xx status, so the request ignores the status code and parses the
body either way.
2026-09-02 13:39:29 -06:00
Dark-Alex-17 aea7fd2607 feat(readarr): delete an indexer and expose the command on the CLI 2026-09-01 17:16:23 -06:00
Dark-Alex-17 daf991d1eb feat(readarr): edit an indexer and expose the command on the CLI 2026-09-01 17:11:32 -06:00
Dark-Alex-17 be5826f2c4 feat(readarr): fetch all indexers and expose them on the CLI 2026-09-01 16:59:57 -06:00
Dark-Alex-17 c94b2a40d0 feat(readarr): clear the blocklist and expose the command on the CLI 2026-09-01 16:44:07 -06:00
Dark-Alex-17 fb91c2edd6 feat(readarr): delete an item from the blocklist and expose the command on the CLI 2026-09-01 16:38:09 -06:00
Dark-Alex-17 5c593b3770 feat(readarr): fetch the blocklist and expose it on the CLI 2026-09-01 16:32:13 -06:00
Dark-Alex-17 5a730f2f05 feat(readarr): manually download a release and expose the command on the CLI 2026-08-28 14:22:57 -06:00
Dark-Alex-17 999a22a37f feat(readarr): fetch releases for an author and expose them on the CLI 2026-08-28 14:15:28 -06:00
Dark-Alex-17 666084a30f feat(readarr): fetch releases for a book and expose them on the CLI 2026-08-28 14:07:15 -06:00
Dark-Alex-17 1edceba056 feat(readarr): mark a history item as failed and expose the command on the CLI 2026-08-28 13:46:39 -06:00
Dark-Alex-17 40be5714e9 feat(readarr): fetch Readarr history and expose it on the CLI 2026-08-28 13:40:40 -06:00
Dark-Alex-17 f5bcb7d83a feat(readarr): refresh Readarr downloads and expose the command on the CLI 2026-08-28 13:23:26 -06:00
Dark-Alex-17 5c9fead725 feat(readarr): delete a download and expose the command on the CLI 2026-08-28 13:18:53 -06:00
Dark-Alex-17 6139b48d90 feat(readarr): fetch Readarr downloads and expose them on the CLI 2026-08-28 13:14:07 -06:00
Dark-Alex-17 3569bcc036 feat(readarr): delete a book file and expose the command on the CLI 2026-08-28 12:58:41 -06:00
Dark-Alex-17 fbfd64eb2a feat(readarr): delete a book and expose the command on the CLI
The delete flags travel as query parameters rather than a request body,
and Readarr spells the exclusion key addImportListExclusion, not the
addImportExclusion that Radarr uses.
2026-08-27 16:19:49 -06:00
Dark-Alex-17 e30d4dbd0c feat(readarr): toggle book monitoring and expose the command on the CLI
The PUT body round-trips through serde_json::Value rather than the typed
Book, so the fields Readarr returns but Book does not declare survive the
toggle instead of being silently dropped. BOOK_JSON now carries a few of
those undeclared fields so a regression to a typed round-trip fails the
tests rather than passing unnoticed.
2026-08-27 16:12:50 -06:00
Dark-Alex-17 f2787560d6 feat(readarr): trigger an automatic book search and expose the command on the CLI 2026-08-27 15:52:44 -06:00
Dark-Alex-17 b48ce5db2e feat(readarr): fetch Readarr book history and expose it on the CLI 2026-08-27 15:40:08 -06:00
Dark-Alex-17 634d1fc1b1 feat(readarr): fetch Readarr book files and expose them on the CLI 2026-08-27 15:22:50 -06:00
Dark-Alex-17 4c6a9ece4e feat(readarr): fetch Readarr book editions and expose them on the CLI 2026-08-27 14:58:47 -06:00
Dark-Alex-17 817ebeaf90 feat(readarr): fetch Readarr book details and expose them on the CLI 2026-08-27 14:51:40 -06:00
Dark-Alex-17 41830cc072 feat(readarr): fetch Readarr books and expose them on the CLI 2026-08-27 14:38:51 -06:00
Dark-Alex-17 8752a85db5 feat(readarr): fetch Readarr author history and expose it on the CLI
Add the GetAuthorHistory event, backed by GET /history/author?authorId=N,
which returns a flat array of history records for a single author. The
fetcher mirrors the artist-history equivalent, sorting by id and carrying
the sort-prompt route guard so a refresh landing while the sort prompt is
open cannot clobber an in-progress sort selection.

Expose it as `readarr list author-history --author-id N`.
2026-08-27 11:11:24 -06:00
Dark-Alex-17 9572b68f97 feat(readarr): refresh all Readarr authors and expose the command on the CLI
Posts the RefreshAuthor command to the command endpoint with no author ID, which is how Readarr distinguishes a library wide refresh from a single author refresh. The response is returned verbatim and no app state is mutated.
2026-08-27 10:50:53 -06:00
Dark-Alex-17 c82006862e feat(readarr): refresh and rescan a Readarr author and expose the command on the CLI
Posts the RefreshAuthor command to the command endpoint with the author ID, queueing a metadata refresh and a disk scan for that author. The response is returned verbatim and no app state is mutated.

Adds the refresh subcommand group to the Readarr CLI.
2026-08-27 10:43:37 -06:00
Dark-Alex-17 e9b9aa3a14 feat(readarr): trigger automatic author searches and expose the command on the CLI
Posts the AuthorSearch command to the command endpoint with the author ID, queueing an indexer search for that author. The response is returned verbatim and no app state is mutated.

Introduces ReadarrCommandBody, the request body shared by the author and book command calls. Both ID fields are omitted from the payload when absent rather than sent as null.
2026-08-27 10:35:04 -06:00
Dark-Alex-17 f896b65fd9 feat(readarr): toggle Readarr author monitoring and expose the command on the CLI 2026-08-27 10:09:04 -06:00
Dark-Alex-17 ac8a11233f feat(readarr): delete Readarr authors and expose the command on the CLI 2026-08-27 09:54:38 -06:00
Dark-Alex-17 fcfc29894e feat(readarr): edit Readarr authors and expose the command on the CLI 2026-08-27 09:43:07 -06:00
Dark-Alex-17 e514e9b6cc feat(readarr): add authors to Readarr and expose the command on the CLI 2026-08-26 17:17:41 -06:00
Dark-Alex-17 9238c1b9d2 feat(readarr): search for new Readarr authors and expose the command on the CLI 2026-08-26 16:57:26 -06:00
Dark-Alex-17 5042dbdb3a feat(readarr): fetch Readarr author details and expose them on the CLI 2026-08-26 14:35:46 -06:00
Dark-Alex-17 817fe4d135 test(readarr): add shared network test factories 2026-08-26 14:23:15 -06:00
Dark-Alex-17 84eba9beac feat(readarr): fetch Readarr authors and expose them on the CLI
Add ReadarrEvent::ListAuthors, mapping to GET /author, and wire it up as
`managarr readarr list authors`.

This is the first Readarr event that touches the library rather than
configuration, so it creates the library/authors module tree mirroring
Lidarr's library/artists layout.

list_authors mirrors Lidarr's list_artists, including the sort-prompt
route guard: a response landing while the user has the sort prompt open
must not clobber their in-progress sort selection. Both directions of
that guard are covered by tests.
2026-08-26 11:41:42 -06:00
Dark-Alex-17 e1be1df68a feat(readarr): delete Readarr root folders and expose the command on the CLI 2026-08-26 10:38:58 -06:00
Dark-Alex-17 3475660eb2 feat(readarr): add Readarr root folders and expose the command on the CLI 2026-08-26 10:31:40 -06:00
Dark-Alex-17 e8e3376327 feat(readarr): delete Readarr tags and expose the command on the CLI 2026-08-26 10:21:55 -06:00
Dark-Alex-17 b9fa3b36c0 feat(readarr): add Readarr tags and expose the command on the CLI 2026-08-20 22:47:41 -06:00
Dark-Alex-17 29186ea03c feat(readarr): fetch Readarr root folders and expose them on the CLI
Adds the GetRootFolders event backed by GET /rootfolder, storing the result
on the Readarr root folders table, and surfaces it as
"managarr readarr list root-folders".

Root folders reuse the shared RootFolder model. Readarr omits the
unmappedFolders key that the other servarrs return, and the field is
optional, so it deserializes to None without changing the shared type.

Only the read path is included here. Adding and deleting root folders
mutate the library layout, so they are left for separate work.
2026-08-20 22:32:16 -06:00
Dark-Alex-17 ce8c51b02f test(readarr): seed system app data so empty and failure assertions can fail
The system network tests asserted that queued events, disk space, logs,
version, tasks, and updates were empty against a default state that was
already empty. Those assertions passed even with the fetcher body removed,
so they reported coverage that did not exist.

Seeding a stale value first makes the empty response test prove the fetcher
replaces rather than merges, and makes the failure tests prove the update
closure never runs on a non-success response by pinning the exact seeded
value.

The assertion on the deserialized payload in the empty response test is
left alone: it reads the response body rather than app state, so it was
never vacuous.
2026-08-20 22:24:57 -06:00
Dark-Alex-17 0cc49089b6 test(readarr): seed profile and tag maps so empty and failure assertions can fail
The empty-response and failure tests asserted the maps were empty against a
default state that was already empty, so they passed even with the fetcher
body removed. Seeding a stale entry first makes the empty-response tests prove
the fetcher replaces rather than merges, and the failure tests prove the update
closure never runs on a non-success response.
2026-08-20 22:16:38 -06:00
Dark-Alex-17 1d8ccd7ff6 feat(readarr): fetch Readarr tags and expose them on the CLI 2026-08-20 22:06:23 -06:00
Dark-Alex-17 de41d6fef7 feat(readarr): fetch Readarr metadata profiles and expose them on the CLI 2026-08-20 22:04:38 -06:00
Dark-Alex-17 4a7cf922e8 feat(readarr): fetch Readarr quality profiles and expose them on the CLI 2026-08-20 22:02:34 -06:00
Dark-Alex-17 44d147ce37 feat(readarr): fetch Readarr queued events and expose them on the CLI
An empty array is a valid response when nothing is queued, so the empty case is covered by its own test.
2026-08-20 21:52:18 -06:00
Dark-Alex-17 ab3992c372 feat(readarr): trigger Readarr tasks and expose the command on the CLI
The task name is sent as the shared CommandBody, matching the Radarr, Sonarr, and Lidarr implementations. The response is returned verbatim and no app state is mutated.
2026-08-20 21:49:28 -06:00
Dark-Alex-17 bd0274411c feat(readarr): fetch Readarr tasks and expose them on the CLI
Adds ReadarrEvent::GetTasks backed by get_readarr_tasks, populating the
Readarr tasks table, and surfaces it as 'readarr list tasks'.
2026-08-20 21:36:37 -06:00
Dark-Alex-17 690a17e152 feat(readarr): fetch Readarr logs and expose them on the CLI
Adds ReadarrEvent::GetLogs backed by get_readarr_logs, which formats each
record into the Readarr logs list, and surfaces it as
'readarr list logs --events N'.

The --output-in-log-format branch reads the Readarr log lines, and is
covered by a test that pins that source so it cannot silently drift to
another servarr's data.
2026-08-20 21:33:57 -06:00
Dark-Alex-17 c6d729162a feat(readarr): fetch Readarr updates and expose them on the CLI
Adds ReadarrEvent::GetUpdates backed by get_readarr_updates, rendering the
update history into the Readarr updates view, and surfaces it as
'readarr list updates'.

Covers the case where an update record omits the changes key, which the
live instance returns for its most recent release.
2026-08-20 21:22:31 -06:00
Dark-Alex-17 e0e82e654e fix: tolerate update records that omit the changes list
The changes field was required, so a single record without it failed the
whole response and emptied the updates list. A live instance returns five
update records of which one has no changes key, so this is reachable rather
than theoretical.

This affects every servarr, since Update is shared.
2026-08-20 21:06:28 -06:00
Dark-Alex-17 97d67a6938 feat(readarr): fetch the Readarr security config and expose it on the CLI 2026-08-20 16:15:34 -06:00
Dark-Alex-17 1072585903 feat(readarr): fetch the Readarr host config and expose it on the CLI 2026-08-20 16:07:33 -06:00
Dark-Alex-17 520b422dcc feat(readarr): fetch Readarr disk space and expose it on the CLI
Add ReadarrEvent::GetDiskSpace, mapped to GET /diskspace, and
get_readarr_diskspace, which stores the result on ReadarrData for the
root folder and system views.

Surface it as `managarr readarr list disk-space`, matching the other
three servarrs.

Readarr returns a label field on some records that DiskSpace does not
model; serde drops it, so the CLI prints only the path and the free and
total space, as it does for the other three servarrs.
2026-08-20 15:49:56 -06:00
Dark-Alex-17 d8f171ec6f feat(readarr): fetch the Readarr system status and expose it on the CLI
Add ReadarrEvent::GetStatus, mapped to GET /system/status, and
get_readarr_status in the new readarr_network/system module. It stores
the version and start time on ReadarrData so the system view and the
tick refresh can read them.

Surface it as `managarr readarr get system-status`, matching the
Radarr, Sonarr, and Lidarr spelling of the same call. A `list status`
spelling would have made the same command a different verb on the
fourth servarr, which is a difference the user would have to remember
for no benefit.

Readarr instances answer /system/status with thirty keys; SystemStatus
models the two that are used and serde ignores the rest, as it does for
the other three servarrs.

This is the first ReadarrCommand variant, so ReadarrCliHandler now
reads its app and network fields.
2026-08-20 15:47:40 -06:00
Dark-Alex-17 cd341c3d71 feat(readarr): add the Readarr health check network call
Inhabit ReadarrEvent with its first variant, HealthCheck, mapped to
GET /health, and add get_readarr_healthcheck alongside the equivalent
Lidarr, Radarr, and Sonarr fetchers. The call is internal only and has
no CLI surface, matching the other three servarrs; it exists so that an
unreachable instance surfaces an error banner on tick.

The healthcheck fetcher lives in readarr_network/mod.rs rather than a
submodule, so its tests live in readarr_network_tests.rs next to the
resource() and NetworkEvent conversion tests, mirroring Lidarr.

MockServarrApi::build_for matched NetworkEvent by value with no Radarr
fallback arm. It compiled only while ReadarrEvent was uninhabited and
no value could reach it; the first variant makes the match non
exhaustive, so it now assigns the config to the Readarr server tab.
2026-08-20 15:44:07 -06:00
Dark-Alex-17 29f043f5c7 feat: scaffold Readarr support across the state, app, handler, UI, and CLI layers
Promote Route::Readarr from a unit stub to a tuple variant and wire Readarr
through every layer, mirroring the Lidarr tree. Readarr appears as a fourth
servarr tab and its library view renders the Authors table.

Adds ReadarrData and its modals, the tick and context clue modules, the
top-level ReadarrHandler, ReadarrUi with the Authors library view, and an
empty ReadarrCommand behind ReadarrCliHandler. The default port is 8787.

Promoting the route variant compiles cleanly without any of the arms that
give it behaviour, so all six of those sites are wired explicitly here:
App::on_tick, handlers::handle_events, handle_prompt_toggle,
ServarrContextClueProvider, ui(), and verify_config_present_for_cli. Each was
checked by removing the arm and confirming its covering assertion then fails.

ReadarrEvent and ReadarrCommand are both declared empty. They gain variants
alongside the network calls and CLI commands that use them, which keeps each
later change to a single function.

Adding the tab changes the rendered tab bar, so 13 existing snapshots
regenerate. The only delta in each is that single tab bar line.

This scaffold adds 24 dead_code warnings, all inside the Readarr tree and
none outside it. They clear as the handlers, UI, network events, and CLI
commands that consume these items land: block arrays awaiting their accepts
implementations and BlockSelectionState seeding, modal and state fields
awaiting their handlers, the CLI handler fields awaiting an inhabited command
enum, and the top-level handler fields awaiting sub-handlers. The count must
strictly decrease from here, so a later increase is a defect rather than
transient noise. The 12 pre-existing collapsible_match warnings are unrelated
and untouched.
2026-08-20 15:28:49 -06:00
Dark-Alex-17 4db9b92146 refactor: move shared servarr types into servarr_models
SystemStatus was declared three times, byte for byte identically, in
radarr_models, sonarr_models, and lidarr_models. MetadataProfile and the
Lidarr release download body were each declared in a single servarr module
despite having nothing servarr specific about them: MetadataProfile is an
id and name pair structurally identical to QualityProfile, which already
lives in servarr_models, and a download body of a guid plus an indexer id
is the generic form of that request.

Move all three into servarr_models, preserving that file's alphabetical
ordering, and drop the prefix from LidarrReleaseDownloadBody now that it is
no longer owned by one servarr.

RadarrReleaseDownloadBody and SonarrReleaseDownloadBody deliberately stay
where they are. Radarr's carries a movie id and Sonarr's carries optional
series, episode, and season fields, so the three types are not
interchangeable and only the Lidarr shape is the common one.

Behavior is unchanged. Every remaining edit is an import path update or the
rename at a call site.
2026-08-20 10:52:05 -06:00
Dark-Alex-17 a362add8f0 feat: updated gitignore to not include coyote memory or workspace config 2026-08-19 13:03:14 -06:00
Dark-Alex-17 6e7707f6df build: upgraded MSRV in the Dockerfile 2026-06-25 15:41:56 -06:00
Dark-Alex-17 6df68b8a66 tests: Addressed additional CR comments and added tests for tail-logs 2026-06-25 14:21:57 -06:00
Dark-Alex-17 cbca6bd916 fix: addressed code review comments 2026-06-25 14:11:18 -06:00
Dark-Alex-17 92187c5f16 fix: tail-logs subcommand follows log rollovers and sleeps to minimize idle CPU loops 2026-06-25 13:51:32 -06:00
Dark-Alex-17 366809d8c6 fmt: applied formatting 2026-06-25 13:32:31 -06:00
Dark-Alex-17 dd93fe117d feat: Implemented log rolling so the log file doesn't just grow exponentially [#60] 2026-06-25 13:29:56 -06:00
Dark-Alex-17 10e18af1bf build: upgraded to openssl 0.10.79 to fix security vulnerabilities 2026-06-25 13:20:14 -06:00
Dark-Alex-17 a4d93692a9 build: Upgraded to Rust v1.95.0 2026-06-25 13:19:27 -06:00
Dark-Alex-17 03d134bec9 refactor: Refactored several usages of sort_by_key and match guards to utilize newer Rust version APIs 2026-06-25 13:18:43 -06:00
Dark-Alex-17 4cad9e1755 docs: Improved the README to demonstrate what a truly minimal configuration looks like for each service and explain the "reasonable defaults" [#61] 2026-06-25 12:35:51 -06:00
Dark-Alex-17 47a2fbf0cc docs: removed the lines-of-code counter from the README since the link is dead 2026-04-20 16:02:18 -06:00
Dark-Alex-17 7067902752 build: updated reqwest and build dependencies 2026-04-20 15:53:42 -06:00
Dark-Alex-17 ba1cf0182b build: Updated the docker image so that it ships with trusted CA root certs from trusted providers like LetsEncrypt, DigiCert, etc. for docker SSL users 2026-04-02 09:58:30 -06:00
Dark-Alex-17 5cccec88c9 docs: Updated the README to have a more detailed section on how to acquire SSL certificate information 2026-03-30 10:13:51 -06:00
Dark-Alex-17 bbcd3f00a9 feat: Created a separate 'ssl' property for the config so users don't have to specify an ssl_cert_path to use SSL or use the uri workaround for HTTPS API access 2026-03-29 12:39:26 -06:00
Dark-Alex-17 2e339dd73b docs: Created an authorship policy and PR template that requires explicit acknowledgement of AI assistance 2026-02-24 17:41:34 -07:00
Dark-Alex-17 f988cf0f26 docs: Fixed some typos found in the README
Check / stable / fmt (push) Successful in 9m57s
Check / beta / clippy (push) Successful in 11m0s
Check / stable / clippy (push) Successful in 10m59s
Check / nightly / doc (push) Successful in 1m2s
Check / 1.89.0 / check (push) Successful in 1m9s
Test Suite / ubuntu / beta (push) Successful in 1m47s
Test Suite / ubuntu / stable (push) Successful in 1m43s
Test Suite / ubuntu / stable / coverage (push) Successful in 12m52s
Test Suite / macos-latest / stable (push) Has been cancelled
Test Suite / windows-latest / stable (push) Has been cancelled
2026-02-05 18:50:42 -07:00