Commit graph

168 commits

Author SHA1 Message Date
Dallas Groot
b4d2a5ce92 Merge ; commit '07d125da3c29035a8bca6a992229655d2ff446a0' 2026-04-11 02:22:29 -07:00
Dallas Groot
a9acd65001 quick fix 2026-04-11 02:20:54 -07:00
Dallas Groot
07d125da3c Ignored IDs persisted in UserDefaults
Active tab — all unignored issues, swipe left → “Ignore” (grey)
	•	Ignored tab — all ignored issues shown dimmed, swipe left →
“Restore” (pink) to bring them back
	•	Fix buttons hidden on ignored issues
	•	Ignored IDs persisted in @AppStorage so they survive app restarts
	•	Tab labels show live counts: Active (1) | Ignored (31)
2026-04-11 02:13:06 -07:00
Dallas Groot
d3434f1911 quick fix 2026-04-11 01:59:36 -07:00
Dallas Groot
12dab4cc37 quick fix 2026-04-11 01:52:16 -07:00
Dallas Groot
01baf8792f quick fix 2026-04-11 01:47:30 -07:00
Dallas Groot
9bbe7bafe4 quick fix 2026-04-11 01:44:36 -07:00
Dallas Groot
ef7116d0bf quick fix 2026-04-11 01:41:58 -07:00
Dallas Groot
aae53a17d8 quick fix 2026-04-11 01:39:31 -07:00
Dallas Groot
db9d79f023 safeguards to id3 tagging and mismatch info 2026-04-11 01:36:13 -07:00
Dallas Groot
ffcddc86e2 quick fix 2026-04-11 01:14:38 -07:00
Dallas Groot
15ed38e13b Musicbrainz api add on
The MusicBrainz feature adds:
	•	Magnifying glass in the toolbar — searches by current title + artist
	•	A picker sheet showing up to 10 results with album, year, country,
label, track number
	•	Blue suggestion pills appear below each field that differs from the
MB match
	•	Tap a pill to accept it — auto-checks the field for saving
	•	Green magnifying glass once a match is selected, tap again to change
2026-04-11 01:08:24 -07:00
Dallas Groot
d37dc8fb44 quick fixes 2026-04-11 00:59:53 -07:00
Dallas Groot
f761f65e87 edit-metadata endpoint
iOS — 6 fixes across 5 files:
Models.swift — Song, Album, AlbumWithSongs all now have albumArtist:
String?. CompanionSong.toSong() passes albumArtist.
CompanionAlbum.toAlbum() passes albumArtist to the new field.
TrackEditorView.swift — Album Artist field now initialises from
song.albumArtist ?? song.artist instead of just song.artist.
fetchCompanionDetails no longer requires companion: prefix — it
fetches for all songs using the album name, decodes properly using
CompanionLibraryResponse, and matches by relative_path.
BatchAlbumEditorSheet.swift — initialises from album.albumArtist ??
album.artist.
MultiAlbumEditorSheet.swift — pre-fills from first.albumArtist ??
first.artist.
AlbumDetailView.swift — buildAlbumWithSongs now passes albumArtist
from the companion songs.
Companion — 2 fixes:
apply_tags — now does full FLAC cleanup (removes all Picard legacy
variants) before writing, same as apply_tags_dict already did.
edit-metadata endpoint — no longer calls restructure_file. File
renaming only happens via /bulk-fix. This was the root cause of the
500 errors on compilation tracks with disc numbers.
2026-04-11 00:50:37 -07:00
Dallas Groot
55820fdb38 my music view fix 2026-04-10 20:44:23 -07:00
Dallas Groot
228b186569 updated readme 2026-04-10 20:05:45 -07:00
Dallas Groot
0e6f4852e5 visualizer fix 2026-04-10 19:44:55 -07:00
Dallas Groot
f43fe73769 quick final fix (fingers crossed this time) 2026-04-10 19:29:42 -07:00
Dallas Groot
454d169a11 pause fix on visualizer 2026-04-10 19:20:27 -07:00
Dallas Groot
188a46d49c quickfix build error 2026-04-10 19:09:12 -07:00
Dallas Groot
a4103c8250 bug fixes and ready to upload to testflight 2026-04-10 19:05:45 -07:00
Dallas Groot
ea50bd4537 pip fixes and improvements
•	Group toggles — iPhone / Watch / Companion / Audio, all persistent
via @AppStorage so your filter state survives app restarts
	•	Level toggles — ERROR / WARN / INFO / DEBUG in a single scrollable
row next to the group toggles, color coded red/yellow/cyan/gray
	•	Delta timestamps — each row shows +42ms between it and the previous
entry, so you can see timing without mental math
	•	Pause/Resume — bottom bar button snapshots the current log so you
can read it without it scrolling, while still capturing in background
	•	Auto background/foreground markers — ── Background ── / ──
Foreground ── lines are auto-inserted by NotificationCenter, making
crash correlation much easier
	•	PiP button in toolbar sets logger.isPiP = true, which MainTabView’s
.onChange picks up and activates the existing floating PiP window
MainTabView.swift — minimal changes:
	•	Added .onChange(of: debugLogger.isPiP) to sync the console’s PiP
button to the existing debugPipMode state
	•	Updated debugLogRow to show level dot + marker support, consistent
with the full console
2026-04-10 18:50:31 -07:00
Dallas Groot
9a613ff2ab final cpu fix 2026-04-10 18:23:58 -07:00
Dallas Groot
16fd347b44 fixes hopefully 2026-04-10 18:05:10 -07:00
Dallas Groot
3cfcf026d7 fixes 2026-04-10 17:50:26 -07:00
Dallas Groot
80b6835dc7 squashed a cpu hogging bug 2026-04-10 17:39:46 -07:00
Dallas Groot
0f8d47fb2a bug fix 2026-04-10 17:30:29 -07:00
Dallas Groot
5b71feebfd bug fixes 2026-04-10 17:17:12 -07:00
Dallas Groot
ef6124e72e bug fixes 2026-04-10 17:08:15 -07:00
Dallas Groot
7d448e79de bug fixes 2026-04-10 17:05:12 -07:00
Dallas Groot
caea96547a bug fixes 2026-04-10 17:02:17 -07:00
Dallas Groot
2bdac607b4 bug fixes
Songs Tab (SearchView.swift)
Default state now loads all songs alphabetically from the library via
getAlbumList2 → per-album song fetch, cached under "all_songs_sorted"
so subsequent opens are instant. The Download All banner shows song
count + already-downloaded count and queues only non-downloaded songs.
Every row uses .contextMenu (the long-press menu) with Play Now, Play
Next, Add to Queue, Download/Remove, Send to Watch, and Add to
Playlist — same pattern as Favourites. Watch and download badges
appear on each row. Searching ≥2 chars runs the server search and
shows artists/albums/songs in sections, then clears back to the full
list when the field is empty.
Keyboard Done Button
A single keyboardDoneButton() View extension in AsyncCoverArt.swift
calls UIApplication.shared.sendAction(resignFirstResponder:...)
globally — no @FocusState needed. Applied to: LoginView (all 4
fields), CompanionSettingsView (host/port), TrackEditorView
(checkField helper covers all tag fields), BatchAlbumEditorSheet
(editField helper), RadioView (name/URL), PlaylistsView (name fields),
MyMusicView (search), SearchView (via @FocusState + toolbar directly).
ShazamKit MTAudioProcessingTap
Primary path: MTAudioProcessingTap installed on AVPlayerItem.audioMix
— works for HLS, radio, and any AVPlayer stream without touching the
microphone. The prepare callback captures the source format and builds
an AVAudioConverter to 16kHz mono. The C-style shazamTapProcess free
function (required by the API) calls
MTAudioProcessingTapGetSourceAudio then dispatches to a serial
analysisQueue — the render thread is never blocked. convertAndMatch
wraps the raw AudioBufferList in an AVAudioPCMBuffer, converts it, and
feeds SHSession.matchStreamingBuffer. Fallback to microphone
(AVAudioEngine) is kept for the local engine path where no
AVPlayerItem exists. NSMicrophoneUsageDescription is only needed if
the mic fallback is ever hit.
2026-04-10 16:55:09 -07:00
Dallas Groot
00ffd7970e Performance Improvements
Phase 1 — VisualizerStorageManager.swift
VisFrameBuffer is a flat ContiguousArray<Float> with frameCount and
pointsPerFrame. All frame data for a track lives in one contiguous
allocation rather than a [[Float]] array-of-arrays. loadCache now uses
Data(contentsOf:options:.alwaysMapped) — the OS maps the file into
virtual memory and faults pages in on demand rather than reading the
whole file into heap. copyFrame(at:into:) copies a frame slice
directly into _audioLevels using initialize(from:) — no intermediate
[Float] created.
Phase 2 — MitsuhaVisualizerView.swift + AudioPlayer.swift
VisualizerLevelBox now pre-allocates targetLevels, displayLevels,
idleLevels, and the full 16-slot history ring on first use via
resizeIfNeeded. This only triggers when numberOfPoints changes (rare —
settings slider). updateDisplayLevels writes directly into
box.targetLevels throughout — no var targetLevels = [Float](), no map,
no append. The history ring buffer now copies in-place into
pre-allocated slots, eliminating the COW trigger on every frame.
drawIdleState uses box.idleLevels — no Array(repeating:). The Canvas
body no longer falls back to Array(repeating:) since displayLevels is
always pre-allocated. The timer in AudioPlayer now calls
buf.copyFrame(at:into:&_audioLevels) directly — no intermediate
[Float] copy.
Phase 3 — View invalidation + drawBars fix
fillColors hoisted out of the drawBars per-bar loop — it was
allocating a new [Color] array count times per frame (8–24 allocations
per draw call at 60fps). Now computed once before the loop.
@ObservedObject var settings and @StateObject private var box are
correct — box has zero @Published properties so it never triggers
parent redraws. The Canvas closure only captures tickDate which
changes every tick, ensuring per-tick re-execution without touching
SwiftUI’s diffing engine.
2026-04-10 16:25:49 -07:00
Dallas Groot
fde3df0d26 fixed library management 2026-04-10 16:22:49 -07:00
Dallas Groot
5b319ad643 updated companion api 2026-04-10 15:23:43 -07:00
Dallas Groot
9b1d6a74e0 Merge branch 'main' of http://dallasgroot@100.96.12.50:3000/dallasgroot/NavidromeApp.git 2026-04-10 13:16:20 -07:00
Dallas Groot
1bee53531c quick fix for visualizer heating up device 2026-04-10 13:16:12 -07:00
ee34a52f1c quick fix 2026-04-10 13:08:17 -07:00
Dallas Groot
fdd3a098a8 changes
TrackEditorView — added Disc # field, album artist now auto-populates
from the Companion DB on sheet open (fetches /library/song/{id}), live
path preview shows exactly where the file will end up as you type,
success message now says “File moved to new path”.
CompanionSettingsView — “Fix Library Structure” button added under
Server Actions in orange with the warning “Only run once all tags are
correct”. It won’t do damage right now since touching it just
restructures based on whatever tags exist, but the warning makes it
clear it’s a final-step tool.
2026-04-10 13:00:45 -07:00
Dallas Groot
36d5151cdb loop error message
The loop was companionLibraryChanged → debounce → lastSyncTimestamp = 0
→ syncIfNeeded() → bootstrap → syncCompanion() → broadcasts
companionLibraryChanged → repeat forever. Removed it from the trigger
list — companionLibraryChanged is now purely a UI refresh signal, not
a sync trigger.
2026-04-10 11:36:32 -07:00
Dallas Groot
99e4f3bd3a updates to companion from ios to server
Models.swift — CompanionSong, CompanionAlbum, CompanionArtist,
CompanionLibraryResponse. Each has a toSong()/toAlbum() converter.
Song.id = navidrome_id (streaming still works), Song.coverArt =
"companion:{id}" (routes cover art to Companion), Album.id =
"companion:{name}|{artist}" (detected by AlbumDetailView).
CompanionAPIService.swift — fetchAllSongs, fetchAlbumSongs,
fetchAllAlbums, fetchAllArtists, searchLibrary are all nonisolated
where needed. coverArtURL/artistPhotoURL are nonisolated so views can
call them synchronously. Push handler now fires
companionCoverArtUpdated and companionArtistPhotoUpdated events and
clears ImageCache immediately on receipt.
LibraryCache.swift — cacheCompanionAlbums/loadCompanionAlbums,
cacheCompanionAlbumSongs/loadCompanionAlbumSongs for local persistence
of companion data between launches.
SyncEngine.swift — syncCompanion() runs after every Navidrome sync
(bootstrap and delta) when Companion is enabled. It fetches albums
from /library/albums, converts them to Album objects, and overwrites
"all_albums" cache — so MyMusicView’s album grid immediately shows
Companion-sorted data. companionLibraryChanged notification triggers
reactive UI updates.
AsyncCoverArt.swift — Detects "companion:{id}" prefix and routes to
CompanionAPIService().coverArtURL(companionId:) instead of Navidrome.
All existing non-companion cover art paths are unchanged.
AlbumDetailView.swift — Detects albumId.hasPrefix("companion:"),
parses "companion:{name}|{artist}", calls
/library/songs?album=...&album_artist=... on Companion, and builds a
synthetic AlbumWithSongs locally. Caches results so the next tap is
instant. Falls back to the existing Navidrome path for all
non-companion album IDs.
2026-04-10 11:14:41 -07:00
Dallas Groot
9c93be200e fixed docker compose
The fix uses a single ./companion_data:/app/data bind mount instead.
The server’s init_db() already calls os.makedirs for cover_art and
artist_photos subdirectories on startup, so they’ll be created
automatically inside ./companion_data/ on first run.
2026-04-10 08:46:08 -07:00
Dallas Groot
99e849b262 companionapi now will be the main library 2026-04-10 08:36:06 -07:00
Dallas Groot
25a96c6a5d watchos info.plist fix 2026-04-10 07:52:45 -07:00
Dallas Groot
7b94844e38 renamed label
•	Smart DJ & Visualizer row label → Crossfade & Visualizer Analyzer
(and removed the misplaced style value from that row)
	•	Visualizer Appearance row now shows the active style (e.g. “Wave”)
as the trailing label, which is where it belongs
	•	Navigation title inside the subview updated to match
2026-04-10 07:41:31 -07:00
Dallas Groot
c8360419c3 miniplayer fix
Two fixes:
Snap-back on seek end: Previously isScrubbing = false was set
immediately after seekToPercent(pct). AVPlayer.seek is asynchronous —
currentTime doesn’t update instantly. So displayProgress switched from
scrubPosition back to the old playbackTime / playbackDuration for up
to 250ms until the timer polled again, causing a visible snap-back.
Now scrubPosition is held at pct and isScrubbing clears after a 150ms
delay — enough time for AVPlayer to confirm the seek position before
the bar resumes tracking currentTime.
Stale timer poller removed: playbackTime and playbackDuration were
@State vars updated by a Timer.publish every 0.25s. Since currentTime
and duration are already @Published on AudioPlayer, the timer was just
adding lag and a secondary update cycle. They’re now computed
properties reading directly from audioPlayer.currentTime and
audioPlayer.duration — updates arrive instantly via SwiftUI’s
observation, same as the full Now Playing view.
2026-04-10 07:33:14 -07:00
Dallas Groot
58be99b40b remove UIRequiresFullScreen
just remove UIRequiresFullScreen. The UILaunchScreen empty dict alone
is sufficient on iOS 26 to satisfy the launch screen requirement.
2026-04-10 07:20:20 -07:00
Dallas Groot
84a41432c5 ui fixes 2026-04-10 07:15:49 -07:00
Dallas Groot
507ae52e9c fixed UI scaling with new info.plist 2026-04-10 07:09:57 -07:00
Dallas Groot
311cfdb3d4 Merge ; commit '619e922a278c9179e1af7d0bc55d0efc69a3ed80' 2026-04-10 07:02:43 -07:00