Commit Graph

8 Commits

Author SHA1 Message Date
cucadmuh 54bc9814f1 fix(windows): startup hang, stable device IDs, boot barrel guards (#1277) 2026-07-12 21:28:58 +03:00
ImAsra 41ae30f05d feat(discord): add dismissible community banner 2026-07-05 18:32:14 +02:00
cucadmuh 32a21ec2c3 fix(playlist): batch playlist writes past the GET URL limit (#1227) (#1235)
* fix(playlist): batch playlist writes past the GET URL limit (#1227)

Adding tracks failed past ~341 songs because the write path re-sent the
entire song list as createPlaylist.view?songId=<all> query params on a GET,
blowing past the server's ~8 KiB URL limit. Writes now append incrementally
via updatePlaylist.view?songIdToAdd=<batch> (and songIndexToRemove for
clears/removals) in 150-id batches, so there is no practical size cap. A
per-server in-memory membership cache removes the full getPlaylist refetch
on every dedup, fixing the "slow add on big playlists" report.

Layering detangle (keeps the new cache from adding dep-cruiser cycles):
- lib/api/subsonicPlaylists.ts is pure of the store again; cache invalidation
  on write failure moved to the feature callers' catch blocks.
- membership cache extracted to the core layer (src/store/playlistMembershipStore.ts)
  so offline/orbit/contextMenu/playlist read it directly instead of routing
  through the @/features/playlist barrel.
- severed the offline -> playlist-barrel edge (pinnedOfflineSync name fallback
  through the live playlist list was dead: nameless callers are all gated by
  isSourcePinnedOffline, where offline meta already carries the name).
- confirmAddAllDuplicates moved into the playlist feature; contextMenu submenus
  import the add/merge helpers via the playlist barrel, not deep paths.

dep-cruiser baseline regenerated: 742 -> 714 (net -28, all no-circular). The
churn in the baseline is path-shift of the frozen playerStore SCC (cover/
playback/orbit), not new coupling; the new playlist modules have zero violations.

* docs(changelog): record #1235 playlist URL-limit fix (changelog + credits)

* fix(playlist): seed membership cache from full list, not library-scoped view (#1235 review)

F1: runPlaylistLoad seeded the dedup membership cache from the
library-scope-filtered songs, so out-of-scope members looked "new" and
addTracksToPlaylistWithDedup/collectMergeSongIds could re-add them as
duplicates. Cache now holds the full unfiltered server list while the UI
still shows the filtered view; add a regression test.

Also documents the two accepted trade-offs flagged in review:
- F2: >batch updatePlaylist clears then appends non-atomically (URL-limit
  workaround); a mid-step failure truncates server state, cache invalidation
  lets the client re-read truth.
- F3: dedup read-modify-append isn't atomic across the await; rare missed
  dedup on concurrent adds, self-heals on next load.
2026-07-05 01:24:04 +03:00
Psychotoxical 77ab95170d refactor(ipc): complete tauri-specta typed-IPC cutover, contract guards, and layering cleanup (#1230) 2026-07-04 17:00:31 +03:00
Psychotoxical b722b1abaf refactor(server): move serverCapabilities into lib
The serverCapabilities cluster (catalog, context, resolve, storeView, types) is
lib-level infra: it imports only @/lib/server and is consumed by both lib and
feature code, so a feature home would invert the two lib consumers. Move it to
src/lib/serverCapabilities and repoint consumers.

Pure move + import updates, no behavior change. Baseline gains one lib->store
entry (storeView reads authStore, only now caught under lib/).
2026-07-01 14:45:15 +02:00
Psychotoxical f2cf8a08df refactor(hooks): move cross-cutting hooks into lib/hooks
The five residual src/hooks/ hooks (useConnectionStatus, useCardGridMetrics,
useTracklistColumns, useNavidromeAdminRole, useAnalysisPerfListener) are all
domain-agnostic — none imports @/features — so they join the other shared hooks
in src/lib/hooks/ (with their two colocated tests). Consumers repointed;
relative-up imports in the moved files become the @/ alias. src/hooks/ is removed.

Pure move + import updates, no behavior change. The layering baseline gains five
lib->store entries (the three hooks that read authStore/devOfflineBrowseStore are
only now caught under lib/) — same documented debt class as the api move.
2026-07-01 14:38:23 +02:00
Psychotoxical f4fa766b20 refactor(api): collapse src/api into src/lib/api
The seven remaining src/api/ modules (analysis, azuracast, bandsintown,
coverCache, migration, network, runtimeLogs) were the last IPC-layer files
outside src/lib/api/, where the rest of the FE IPC clients already live. Move
them (+ the colocated coverCache test) into lib/api and repoint every consumer;
relative-up imports in the moved files become the depth-independent @/ alias.

Pure move + import updates — no behavior change. The layering baseline is
regenerated in the same commit: the moved files' pre-existing store/cover edges
are only now caught under lib/, and the cover<->coverCache cycles are the same
edges re-keyed to the new path (E4 shrinks the allowlist later).
2026-07-01 14:17:56 +02:00
Psychotoxical 47f2883ca2 test(arch): layering + cycle guard (dependency-cruiser) with current-violation allowlist
Encode the feature-folder layering contract as a CI gate: lib is the floor,
store/ui must not import features/app, cross-feature only via the barrel, no
cycles. dependency-cruiser resolves the @/ alias via tsconfig; tests excluded.

Land as a ratchet: the 738 current violations are seeded into
.dependency-cruiser-known-violations.json and ignored via --ignore-known, so
HEAD is green and any NEW violation fails CI. Regenerate the baseline as the
drain removes an exception; the count is the tracked residual debt.

Wired via `npm run dep:check` into a new dependency-cruiser job in eslint.yml
and the ci-ok required-check aggregate.
2026-07-01 11:14:48 +02:00