Skip to content

Commit a020644

Browse files
docs: update backlog tasks
1 parent 4b5cb32 commit a020644

4 files changed

Lines changed: 215 additions & 0 deletions
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
id: TASK-336
3+
title: 'Follow up to PR #44: reduce remaining duplication and complexity hotspots'
4+
status: To Do
5+
assignee: []
6+
created_date: '2026-04-29 04:19'
7+
updated_date: '2026-04-29 04:21'
8+
labels:
9+
- refactor
10+
- complexity
11+
- tech-debt
12+
dependencies:
13+
- TASK-336.1
14+
- TASK-336.2
15+
- TASK-336.3
16+
references:
17+
- 'https://github.com/pythoninthegrass/mt/commit/4ba8be8'
18+
- 'https://github.com/pythoninthegrass/mt/pull/44'
19+
priority: medium
20+
---
21+
22+
## Description
23+
24+
<!-- SECTION:DESCRIPTION:BEGIN -->
25+
PR #44 (`4ba8be8`, "refactor: reduce complexity of codebase") removed ~485 LOC of mechanical duplication via two extractions: `tool_def()` in `crates/mt-tauri/src/agent/tools.rs` and `tauriInvoke()` in `app/frontend/js/api/shared.js`.
26+
27+
A follow-up audit (largest files, largest functions, duplicated patterns, dead code) identified another ~330 LOC of mechanical wins across the Rust backend, JS frontend, and CI/test scaffolding. This parent task tracks that follow-up effort. Each child task is independently reviewable and lands as its own PR.
28+
29+
The work is intentionally scoped to mechanical, low-risk extractions that reuse helpers that already exist (`Database::with_conn` at `crates/mt-tauri/src/db/mod.rs:190`, `row_to_track` in `crates/mt-tauri/src/db/library.rs`, `tauriInvoke` in `app/frontend/js/api/shared.js`). Out of scope: splitting the giant Rust files (`db/library.rs` 3374 LOC, `db/queue.rs` 2292 LOC, `library/commands.rs` 1798 LOC) and `components/settings-view.js` (1108 LOC) — those are wide rather than tangled, and structural splits are deferred until there's specific pressure.
30+
31+
This task is complete when all three child tasks are merged and the workspace remains green on `task lint`, `task format`, `task test`, and `task tauri:build`.
32+
<!-- SECTION:DESCRIPTION:END -->
33+
34+
## Acceptance Criteria
35+
<!-- AC:BEGIN -->
36+
- [ ] #1 All three child tasks are completed and merged
37+
- [ ] #2 Total LOC reduction across the three PRs is ≥250 LOC (target ~330)
38+
- [ ] #3 task lint, task format, task test all pass on main after final child merges
39+
- [ ] #4 task tauri:build (or cargo check at minimum) succeeds on main after final child merges
40+
- [ ] #5 No behavior changes are introduced — refactor-only
41+
<!-- AC:END -->
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
id: TASK-336.1
3+
title: >-
4+
Rust: collapse audio command boilerplate and adopt with_conn / row_to_track
5+
helpers
6+
status: To Do
7+
assignee: []
8+
created_date: '2026-04-29 04:20'
9+
labels:
10+
- refactor
11+
- rust
12+
- complexity
13+
dependencies: []
14+
references:
15+
- 'https://github.com/pythoninthegrass/mt/commit/4ba8be8'
16+
parent_task_id: TASK-336
17+
priority: medium
18+
---
19+
20+
## Description
21+
22+
<!-- SECTION:DESCRIPTION:BEGIN -->
23+
Highest-leverage Rust complexity wins identified during the PR #44 follow-up audit. Estimated ~150 LOC reduction. All extractions reuse helpers that already exist in the codebase — no new abstractions are introduced.
24+
25+
**Scope:**
26+
27+
1. **`crates/mt-tauri/src/commands/audio.rs:519-577`** — seven Tauri command wrappers (`audio_play`, `audio_pause`, `audio_stop`, `audio_seek`, `audio_set_volume`, `audio_get_volume`, `audio_get_status`) each manually create an `mpsc::channel`, call `state.send_command(...)`, and `recv().map_err(...)`. Replace with a generic helper such as `fn dispatch<R>(state: &AudioState, build: impl FnOnce(Sender<R>) -> AudioCommand) -> ...` plus a thin macro/closure for the `Result<(), String>` flavour. Cuts ~50 LOC.
28+
29+
2. **`crates/mt-tauri/src/commands/audio.rs:283-355`** — the `audio_thread` `match` arms for `Play`/`Pause`/`Seek`/`SetDevice` repeat `ensure_engine().and_then(|eng| eng.X().map_err(...))` then `reply.send(result)`. Collapse via a small closure inside `audio_thread`. `Stop`/`SetVolume`/`GetVolume`/`GetStatus` have different shapes — leave them alone. Cuts ~30 LOC.
30+
31+
3. **`crates/mt-tauri/src/commands/queue.rs` and `crates/mt-tauri/src/commands/favorites.rs`** — migrate the ~100 sites that currently do `let conn = db.conn().map_err(|e| e.to_string())?;` followed by `some_call(&conn).map_err(|e| e.to_string())?` to the existing `Database::with_conn` helper at `crates/mt-tauri/src/db/mod.rs:190`. Pattern is already proven in `crates/mt-tauri/src/commands/lastfm.rs` (33 call sites). Cuts ~70 LOC.
32+
33+
4. **`crates/mt-tauri/src/db/favorites.rs` and `crates/mt-tauri/src/db/playlists.rs`** — make `db::library::row_to_track` `pub(crate)` (currently private in `crates/mt-tauri/src/db/library.rs`) and replace the four inlined ~25-line `Track { id, filepath, title, ... }` row mappings. Cuts ~80 LOC.
34+
35+
**Files to modify:**
36+
- `crates/mt-tauri/src/commands/audio.rs`
37+
- `crates/mt-tauri/src/commands/queue.rs`
38+
- `crates/mt-tauri/src/commands/favorites.rs`
39+
- `crates/mt-tauri/src/db/library.rs` (visibility change only)
40+
- `crates/mt-tauri/src/db/favorites.rs`
41+
- `crates/mt-tauri/src/db/playlists.rs`
42+
<!-- SECTION:DESCRIPTION:END -->
43+
44+
## Acceptance Criteria
45+
<!-- AC:BEGIN -->
46+
- [ ] #1 Audio command wrappers in commands/audio.rs use a shared dispatch helper; total file LOC reduced by ≥40
47+
- [ ] #2 audio_thread match arms for Play/Pause/Seek/SetDevice share a helper closure; behavior unchanged
48+
- [ ] #3 commands/queue.rs and commands/favorites.rs use Database::with_conn instead of manual db.conn().map_err(...) acquisitions
49+
- [ ] #4 db::library::row_to_track is pub(crate) and reused by db/favorites.rs and db/playlists.rs in place of inlined Track row mappings
50+
- [ ] #5 cargo nextest run --workspace passes
51+
- [ ] #6 cargo clippy --workspace --all-targets passes with -D warnings
52+
- [ ] #7 cargo fmt --all leaves no diff
53+
- [ ] #8 Manual smoke: app launches, plays a track, pause/seek/volume work, favorites toggle works, queue add/remove works
54+
<!-- AC:END -->
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
---
2+
id: TASK-336.2
3+
title: 'Frontend: complete tauriInvoke migration and extract small helpers'
4+
status: To Do
5+
assignee: []
6+
created_date: '2026-04-29 04:20'
7+
labels:
8+
- refactor
9+
- frontend
10+
- complexity
11+
dependencies: []
12+
references:
13+
- 'https://github.com/pythoninthegrass/mt/commit/4ba8be8'
14+
parent_task_id: TASK-336
15+
priority: medium
16+
---
17+
18+
## Description
19+
20+
<!-- SECTION:DESCRIPTION:BEGIN -->
21+
Closes the leak left by PR #44's `tauriInvoke` extraction: the helper exists in `app/frontend/js/api/shared.js` but several components still call `window.__TAURI__.core.invoke(...)` directly. Also extracts two more small helpers that have multiple inline copies. Estimated ~100 LOC reduction.
22+
23+
**Scope:**
24+
25+
1. **Replace direct `window.__TAURI__.core.invoke` with `tauriInvoke`** in 14 sites:
26+
- `app/frontend/js/components/settings-view.js` (9 sites near lines 195, 211, 229, 296, 312, 345, 379, 427, 943)
27+
- `app/frontend/js/components/metadata-modal.js` (3 sites: 204, 266, 393)
28+
- `app/frontend/js/components/stats-view.js` (1 site: 215)
29+
- `app/frontend/js/utils/library-operations.js` (1 site: 489)
30+
31+
2. **Add `tauriConfirm(message, options)` to `app/frontend/js/api/shared.js`** wrapping `window.__TAURI__?.dialog?.confirm(...) ?? window.confirm(...)`. Replace the 5 inlined copies in:
32+
- `app/frontend/js/mixins/context-menu-actions.js` (~line 456)
33+
- `app/frontend/js/mixins/column-settings.js` (~line 218)
34+
- `app/frontend/js/mixins/playlist-crud.js` (~line 210)
35+
- `app/frontend/js/components/settings-view.js` (~lines 393, 798, 986)
36+
37+
3. **Move the local `formatDuration` shorthand from `app/frontend/js/components/stats-view.js:170-179`** into `app/frontend/js/utils/formatting.js` as a new export `formatDurationShorthand` (returns "3d 2h" / "45m" style). Note: the existing `formatDuration` in `formatting.js` returns `MM:SS` and is **not** a drop-in replacement — keep both.
38+
39+
**Files to modify:**
40+
- `app/frontend/js/api/shared.js` (add `tauriConfirm`)
41+
- `app/frontend/js/utils/formatting.js` (add `formatDurationShorthand`)
42+
- `app/frontend/js/components/settings-view.js`
43+
- `app/frontend/js/components/metadata-modal.js`
44+
- `app/frontend/js/components/stats-view.js`
45+
- `app/frontend/js/utils/library-operations.js`
46+
- `app/frontend/js/mixins/context-menu-actions.js`
47+
- `app/frontend/js/mixins/column-settings.js`
48+
- `app/frontend/js/mixins/playlist-crud.js`
49+
<!-- SECTION:DESCRIPTION:END -->
50+
51+
## Acceptance Criteria
52+
<!-- AC:BEGIN -->
53+
- [ ] #1 No remaining direct calls to window.__TAURI__.core.invoke outside app/frontend/js/api/
54+
- [ ] #2 tauriConfirm helper exists in api/shared.js and is used by all 5 previous inline confirm-dialog sites
55+
- [ ] #3 formatDurationShorthand exists in utils/formatting.js and is imported by stats-view.js; the local copy is removed
56+
- [ ] #4 deno lint and deno fmt --check pass
57+
- [ ] #5 cd app/frontend && npx vitest run passes
58+
- [ ] #6 cd app/frontend && npx playwright test --grep '@tauri' passes (or is skipped consistently with main)
59+
- [ ] #7 Manual smoke: open app, change settings, edit a track's metadata, view stats page, confirm a destructive action via context menu — no regressions
60+
<!-- AC:END -->
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
---
2+
id: TASK-336.3
3+
title: 'Build/test: extract reusable composite actions and consolidate test mocks'
4+
status: To Do
5+
assignee: []
6+
created_date: '2026-04-29 04:21'
7+
labels:
8+
- refactor
9+
- ci
10+
- tests
11+
- complexity
12+
dependencies: []
13+
references:
14+
- 'https://github.com/pythoninthegrass/mt/commit/4ba8be8'
15+
parent_task_id: TASK-336
16+
priority: low
17+
---
18+
19+
## Description
20+
21+
<!-- SECTION:DESCRIPTION:BEGIN -->
22+
Lower-LOC but high-maintenance-value cleanup of build/test scaffolding. Estimated ~80 LOC reduction.
23+
24+
**Scope:**
25+
26+
1. **`.github/actions/resolve-release-tag/action.yml`** — extract the release-tag-resolution block that is duplicated 4 times in `.github/workflows/release.yml` (currently around lines 54-66, 149-161, 204-217 in bash and 324-336 in pwsh). The composite action must support both `bash` and `pwsh` shells. Replace the 4 inline blocks with `uses: ./.github/actions/resolve-release-tag`.
27+
28+
2. **`.github/actions/setup-frontend/action.yml`** — extract the `actions/setup-node@v6` + `npm ci` block duplicated 3 times across `.github/workflows/test.yml` (around lines 163-172, 213-221) and `.github/workflows/test-local.yml` (around lines 43-52, 94-96). Replace inline blocks with `uses: ./.github/actions/setup-frontend`.
29+
30+
3. **`taskfiles/tauri.yml`** — add an internal task `_deps-base-build` that runs `:deno:install`, `:cargo:_setup-cargo-home`, `:cargo:install-sccache`. Replace the 7 places where this dependency triple is inlined (around lines 103, 127, 140, 173, 186, 196, 204) with `deps: [_deps-base-build]`.
31+
32+
4. **`app/frontend/__tests__/`** — consolidate the 3× duplicated `global.window.__TAURI__ = { core: { invoke: vi.fn(...) }, event: { listen: vi.fn(...) } }` mock and the 3× duplicated `vi.mock('../js/api.js', ...)` factory found in `player.props.test.js`, `playback-regression.test.js`, and `setup-player-mocks.js`. Move into shared modules under `app/frontend/__tests__/mocks/` (e.g. `mocks/tauri.js`, `mocks/api.js`) or the vitest setup file. Each test imports the shared factory and overrides only the parts it needs.
33+
34+
**Files to create:**
35+
- `.github/actions/resolve-release-tag/action.yml`
36+
- `.github/actions/setup-frontend/action.yml`
37+
- `app/frontend/__tests__/mocks/tauri.js`
38+
- `app/frontend/__tests__/mocks/api.js`
39+
40+
**Files to modify:**
41+
- `.github/workflows/release.yml`
42+
- `.github/workflows/test.yml`
43+
- `.github/workflows/test-local.yml`
44+
- `taskfiles/tauri.yml`
45+
- `app/frontend/__tests__/player.props.test.js`
46+
- `app/frontend/__tests__/playback-regression.test.js`
47+
- `app/frontend/__tests__/setup-player-mocks.js`
48+
<!-- SECTION:DESCRIPTION:END -->
49+
50+
## Acceptance Criteria
51+
<!-- AC:BEGIN -->
52+
- [ ] #1 resolve-release-tag composite action exists and is used by all 4 prior inline blocks in release.yml
53+
- [ ] #2 setup-frontend composite action exists and is used by all 3 prior inline blocks in test.yml/test-local.yml
54+
- [ ] #3 taskfiles/tauri.yml has a _deps-base-build internal task; the 7 inlined dep triples are replaced
55+
- [ ] #4 Tauri/API test-mock factories live in app/frontend/__tests__/mocks/ and are imported by the 3 affected test files — no duplicated inline mock blocks remain
56+
- [ ] #5 actionlint .github/workflows/ passes
57+
- [ ] #6 task lint passes
58+
- [ ] #7 cd app/frontend && npx vitest run passes
59+
- [ ] #8 Trigger a workflow_dispatch run of release.yml in dry-run mode (or local act run) to confirm the resolve-release-tag action works end-to-end on bash + pwsh
60+
<!-- AC:END -->

0 commit comments

Comments
 (0)