Fold the Jobs tab into the places the work is started #147

Merged
logan merged 7 commits from feat/27-jobs-into-settings into main 2026-08-20 01:02:41 +00:00
7 Commits
Author SHA1 Message Date
logan f9ba9a87d7 docs: note that CI's two engines share one app
CI / check (push) Skipped
CI / e2e (push) Skipped
CI / check (pull_request) Successful in 2m31s
CI / e2e (pull_request) Successful in 7m32s
Which is why a shared-selector fault can be green on chromium and red
on webkit in the same run, and how to reproduce it locally.
2026-08-19 20:44:16 -04:00
logan e4efec6f0c fix(e2e): the third spec that located a disclosure by class
CI / check (push) Skipped
CI / e2e (push) Skipped
CI / check (pull_request) Canceled after 8s
CI / e2e (pull_request) Canceled after 0s
`config-section .header` is ambiguous once a section holds a job, and
`failure-voice.spec.ts` was the one I did not grep for. It passed on
chromium and failed on webkit in the same CI run, which is the tell:
the two engines share one app, so the second one runs with a finished
scan the first one left behind.

The NOTES entry already says a class name is not a selector's contract;
this is the same fix, by role and name.
2026-08-19 20:44:02 -04:00
logan 99f355b2fc docs: record where background jobs went, and two traps
CI / check (push) Skipped
CI / e2e (push) Skipped
CI / check (pull_request) Successful in 2m37s
CI / e2e (pull_request) Failing after 7m35s
The retired-destination note sits beside #25's storage paragraph
because it is the exception to it: an absent key is free, a value is
not.

`config-section .header` resolving to two elements is in NOTES because
it cannot be reproduced by opening Settings and looking -- the drawer
only exists once a job does.
2026-08-19 20:27:55 -04:00
logan c79d4d47a3 test: cover jobs in Settings, and unpick two shared selectors
The spec worth having is not that the tab is gone -- that is one line
of a table -- but that nothing became unreachable when it went. #24
promises that no action is ever unreachable at any supported size, and
deleting a destination is exactly the change that quietly breaks it.

Two existing selectors had to give. `config-section .header` is
ambiguous the moment a section holds a job, because `job-details-drawer`
carries that class too -- so `settings-reach.spec.ts` locates a
disclosure by role and name instead. And `page-header`'s and
`offline-icons`'s view lists lose an entry each.

Closes #27
2026-08-19 20:27:48 -04:00
logan 8efed2dd2b refactor(shell): retire the Jobs destination
Nothing it carried is gone -- the two commits before this put all of it
somewhere the work is already being done.

A retired destination is the one shape #25's storage decision does not
make free. A visibility entry is a map key and an unknown key is
dropped on load; a launch page is a *value*, and an unknown one fails
validation -- which on the load path means the app refuses to start for
whoever had Jobs selected. `RetiredViews` is that list, read by
`ApplyDefaults`, which treats a retired name as a zero value. An
unknown-but-not-retired name still errors, because that is a typo and
saying so is the useful answer.
2026-08-19 20:27:40 -04:00
logan 12af6ec1f7 feat(settings): scan from Settings, and watch every job in place
Scanning goes back where libraries are managed -- the Jobs tab's own
comment said the per-library controls had been taken out of Settings to
build it. "Scan All" and "Full Rescan" join "Add Library", "Scan now"
joins the per-library overflow menu beside Rename and Remove, and a
library being scanned says so where its track count goes.

Each surface then gets the job rows for its own kind: scans under
Libraries, index and enrichment under Search Index, downloads under the
download clients, and the autotag apply in the Autotag view -- where
stopping a run matters most, since applying rewrites tags on disk and
that view had no cancel at all.

The autotag panel shares the header's grid row through a wrapper rather
than taking a third row: it is display:none while nothing is applying,
which is nearly always, and a grid row would still spend the
container's gap on it.

The Launch Page select is derived from `VIEW_META` instead of listing
its ten options, since removing a destination is exactly the change
that leaves two hand-written copies disagreeing.
2026-08-19 20:27:33 -04:00
logan f3d1ae1c8c feat(jobs): show background work where the work is started
Reading the app before moving anything turned up that four of the five
job kinds already have a home showing their work: Settings → Search
Index draws per-tier index progress, `downloads-view` draws every
download's lifecycle state, `autotag-view` draws its own apply ring,
and only `library-scan` had nowhere but the Jobs tab. What none of the
four had is the *generic* affordances — pause, cancel, Details, the
log, and a finished job you can dismiss.

So this is a panel embedded beside each of them rather than one
"Background jobs" section in Settings, which would have been the tab
again under another name.

Three rules in it. The controls are `applyJobControl`, not a
reimplementation, which is what keeps the index build's "you will
discard hours of downloading" confirmation alive across the move. A
panel with nothing to say is `hidden` rather than empty, host margin
included, because an idle panel in four places is four pieces of
furniture describing an absence. And there is no "Clear finished":
`ClearFinishedJobs` is global, so a Clear under Libraries would discard
the index build's history too.

`JobKind` also gains `download`, which the backend has had all along.
2026-08-19 20:27:22 -04:00