feat(library): remove a track from the library without deleting the file
RemoveFromLibrary deletes the audio_files rows the way the scan's own orphan cleanup does and records each path in excluded_paths. The exclusion is not an enhancement: without it the next scan finds the file, sees no row and imports it again, so the button undoes itself. The soft scan compares files on disk against rows in the database, so surveyAudioFiles and countAudioFiles both take the exclusion set — otherwise an excluded path makes the two disagree forever and queues a full scan on every launch. Deleting a row cascades to queue_tracks, so the removal calls the same CompactQueue hook RemoveLibrary does. Also lands the requested badge: library-status-indicator is a button again where it can act, utils/library-status.ts states once what owning and wanting mean, and the long-declared queued state finally has a producer. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UDCbcCZQepnpSQYJ6SxxZm
This commit is contained in:
@@ -18,7 +18,7 @@ here has disappeared.
|
||||
|
||||
## Read this part before you fail
|
||||
|
||||
Fourteen things cost a cycle each the first time. They are here, not in a
|
||||
Fifteen things cost a cycle each the first time. They are here, not in a
|
||||
reference, because you need them *before* the failure, not after.
|
||||
|
||||
- **Time out every binding call.** A bound Go method called with wrong
|
||||
@@ -54,6 +54,16 @@ reference, because you need them *before* the failure, not after.
|
||||
`label` to `aria-labelledby` — so a new dialog that forgets to call
|
||||
the helper from `updated()` is invisible to
|
||||
`getByRole('dialog', {name})`.
|
||||
- **A name is computed on the element carrying the *role*, and Web
|
||||
Awesome puts the role in its own shadow root.** `aria-label` on a
|
||||
`<wa-slider>` or a `<wa-dialog>` host never reaches the tree. Use the
|
||||
component's own `label` (plus `styles/wa-slider-label.css.ts`, since
|
||||
a slider's is visible) or `utils/name-dialog.ts`. And in the light
|
||||
DOM, a `<label>` that is a *sibling* of its control with no `for`
|
||||
names nothing — that was 24 of the 93 controls on Settings.
|
||||
**`getFullAXTree` is how you check, and "0 unnamed" is not the whole
|
||||
answer**: a `placeholder` is an accname fallback, so a box labelled
|
||||
only by one reports clean.
|
||||
- **The a11y snapshot cannot check an accessible name on a dialog.**
|
||||
`playwright-cli snapshot` prints `- dialog [ref=…]` with no name
|
||||
whether the dialog is named by `aria-labelledby`, by `aria-label`,
|
||||
@@ -66,7 +76,7 @@ reference, because you need them *before* the failure, not after.
|
||||
`--browser=webkit` is CI-only; local work is Chromium. CI runs it
|
||||
with `if: !cancelled()` so a chromium failure does not silently
|
||||
skip it, which it did for two sessions.
|
||||
- **CI's `e2e` job is green on both engines** (54 specs each) since the
|
||||
- **CI's `e2e` job is green on both engines** (88 specs each) since the
|
||||
container got an audio device that keeps time. If playback specs
|
||||
start failing there again, check the **`The sink plays at real time`**
|
||||
step first: ALSA's `null` plugin consumes 3000 ms of audio in 2.96 ms,
|
||||
@@ -74,9 +84,9 @@ reference, because you need them *before* the failure, not after.
|
||||
reads as an app bug and cost two sessions of that suspicion.
|
||||
- **`make e2e` needs `SEED=default`.** Its specs assert on fixture
|
||||
content — unicode tracks, the fixture artists, a known playable file.
|
||||
Run against the `bulk` seed a measurement session left behind and 13
|
||||
of 36 fail, in a list that reads exactly like a regression in
|
||||
whatever you are holding. `make dev-headless SEED=default` first.
|
||||
Run against the `bulk` seed a measurement session left behind and a
|
||||
third of them fail (13 of 36, when it was measured), in a list that
|
||||
reads exactly like a regression in whatever you are holding. `make dev-headless SEED=default` first.
|
||||
- **…and the suite spends state it cannot always give back.**
|
||||
`view-lifecycle.spec.ts` **skips an autotag album** on every run, out
|
||||
of the eleven the seed has, and does not put it back — so around the
|
||||
@@ -180,7 +190,7 @@ and a CI step over every commit in a push) rejects a subject that is not
|
||||
`--no-verify` commit skips it locally and meets it in CI.
|
||||
|
||||
Two things about the e2e tier that are not obvious until they bite.
|
||||
**The 36 specs share one backend process in file order**, so a spec
|
||||
**The 88 specs share one backend process in file order**, so a spec
|
||||
that leaves the app somewhere passes alone and fails the suite — leave
|
||||
the UI as you found it, and *wait* for it rather than trusting the
|
||||
click to have finished. The queue panel's width is animated and the
|
||||
|
||||
@@ -5,7 +5,21 @@ chain got wrong, and when squashing is legitimate — is in `CLAUDE.md`
|
||||
under *Backend packages → database*. Read it once. This is the
|
||||
checklist.
|
||||
|
||||
A schema change needs **two** files, not one:
|
||||
**A brand-new table needs one file, not two.** The rule below is about
|
||||
a *column added to a table that already exists*. `applySchema` runs
|
||||
every file in `sql/schemas/` on every open, so a
|
||||
`CREATE TABLE IF NOT EXISTS` reaches an existing install verbatim and a
|
||||
migration for it would be a second description of the same table — the
|
||||
thing the third rule forbids. Its indexes go in the schema file too,
|
||||
because the column and the index arrive together.
|
||||
|
||||
A new table has a second gate: **`backend/datamap`**. Add an entry
|
||||
stating its Kind and Lifetime, or `TestCatalogCoversSchema` fails — and
|
||||
if it is `Authored` and cascades, `TestAuthoredCascadesAreDeliberate`
|
||||
wants an explicit exemption with a note, because authored data is what
|
||||
a user cannot get back.
|
||||
|
||||
Adding a **column** to an existing table needs **two** files, not one:
|
||||
|
||||
1. **`backend/database/sql/schemas/*.sql`** — `CREATE TABLE ... IF NOT
|
||||
EXISTS`, the literal target shape, what sqlc reads and what a fresh
|
||||
|
||||
Reference in New Issue
Block a user