Add backup/restore, library sort, and PWA auto-update features - #41
Open
EnesYilmazcode wants to merge 9 commits into
Open
Add backup/restore, library sort, and PWA auto-update features#41EnesYilmazcode wants to merge 9 commits into
EnesYilmazcode wants to merge 9 commits into
Conversation
The app is configured with registerType:'autoUpdate', but on iOS a standalone PWA is frozen and resumed rather than reloaded, so Safari's built-in update check rarely fires and the app looks stale until it's removed and re-added from the home screen. That workaround is also risky: imported songs/playlists live in IndexedDB, which iOS can drop when the home-screen icon is deleted. - Register the service worker via virtual:pwa-register and call registration.update() on a timer and on every foreground resume, so a resumed iOS app picks up new builds without a reinstall. - Request persistent storage at startup (not just on import) so the library is far less likely to be evicted while the app sits unused. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBLkqNYmSgVYiTwUDcdogL
Long-press anywhere on the tab bar to peek at which deploy is running (short commit hash + build timestamp, stamped at build time via a Vite define). The pill auto-hides after 5s and never appears in normal use, so the UI stays clean while still making it possible to confirm that the PWA's in-place auto-update actually landed a new build. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBLkqNYmSgVYiTwUDcdogL
Research fleet -> sequential implementers -> slop-check fleet -> fresh review -> fix/re-verify loop, parameterized by a task batch. Improves the shared team format: batch tasks with shared research and one combined review, self-contained reviewer, and repo-idiom-beats-house- style as the standing rule. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBLkqNYmSgVYiTwUDcdogL
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBLkqNYmSgVYiTwUDcdogL
…ring and an always-on summary Filter the picked list down to audio files (by MIME type or the accept-list extensions) before the quota pre-flight and the remaining counter, since iOS Select-All sweeps in the a-Shell folder's .json sidecars and the accept attr is advisory only. Count added tracks explicitly (the out-of-space break exits early, so deriving it from lengths would be wrong) and always set a summary notice after a non-empty pick: "N added", skipped/failed parts when present, and "No new songs" when nothing changed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBLkqNYmSgVYiTwUDcdogL
Adds exportBackup/importBackup to db.js: a backup is the catalog + playlists as plain JSON (no audio bytes, no lyrics). Restore merges tracks by id keeping live catalog metadata and combining user state, and merges playlists by name with fresh auto-increment ids. Restored rows keep their original id and srcType so re-importing the same audio file hits addLocalTrack's dedup match, which now reattaches the bytes to the existing row when its blob is missing, keeping playlists and stars intact (issue #40). The Playlists tab gains quiet Export backup / Restore pills with an inline importnote status, and the README documents updating and data safety, replacing the now-unsafe remove-and-re-add-the-icon advice. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBLkqNYmSgVYiTwUDcdogL
UI polish pass over issue #39: - format.js gains formatTotalDuration ('2 hr 51 min' / '48 min' / '42 sec', '' for empty) so views can append durations to song counts; summarize and formatTime are untouched. - Library gets a Recent / Most played / A-Z sort segmented control persisted in localStorage (melody:librarySort, try/catch for private-mode Safari, pure lazy initializer for StrictMode), a song-count + duration meta line under the title, and a centered empty state with an icon and a second ImportButton CTA (only mounted while the library is empty, so the test harnesses' strict file-input locator still resolves on seeded dev). - Playlist cards render a 2x2 artwork mosaic (Artwork's gradient fallback covers empty cells) plus a resolved song count and total duration, filtering dangling track ids the same way PlaylistDetail does. - New toast in UIProvider/App replaces both inline importnote renderings (import summaries and backup-restore status) with a transient pill absolutely positioned inside the dock, keyed by id so repeat messages restart the 4s timer; the unused .importnote css rule is removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBLkqNYmSgVYiTwUDcdogL
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBLkqNYmSgVYiTwUDcdogL
- summarize() now says "songs" and delegates to formatTotalDuration; Library header, playlist cards, and playlist detail all share it, so the count/duration vocabulary can't drift again - formatTotalDuration: drop the unreachable NaN check and round to minutes before splitting off hours, so 3599 s renders "1 hr", not "60 min" - importBackup: reject backups with a schema newer than 3; drop the dead starred default that the spread always overwrote - ImportButton: picking only sidecar files now says "No audio files in that selection" instead of claiming the songs were already imported - PlaylistsView: export failures surface a toast instead of vanishing Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBLkqNYmSgVYiTwUDcdogL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds three major features to Melody: backup/restore functionality for playlists and library metadata, persistent sort preferences in the Library view, and improved PWA auto-update detection for iOS. It also includes a hidden build readout accessible via long-press on the tab bar for debugging deployment state.
Key Changes
Backup & Restore
exportBackup()andimportBackup()functions to serialize/merge catalog and playlist data as JSONaddLocalTrackLibrary Sorting
PWA Auto-Update & Build Readout
registerServiceWorker()in newsrc/lib/pwa.jsthat explicitly checks for updates on a 1-hour interval and whenever the app returns to foreground (critical for iOS where PWA is frozen/resumed rather than reloaded)Supporting Changes
summarize()in format.js to use "songs" terminology and addedformatTotalDuration()for human-readable duration formatting (e.g., "2 hr 51 min").importnoteCSS in favor of app-wide toast patternWorkflow Infrastructure
.claude/workflows/ship.js: a multi-phase pipeline for shipping code changes (research fleet → sequential implementers → slop-check fleet → fresh review → fix loop).claude/commands/ship.mddocumentation for the ship workflowNotable Implementation Details
addLocalTracknow distinguishes between restored rows (no blob) and duplicates (blob exists), allowing re-import to reattach bytes without counting as a duplicatehttps://claude.ai/code/session_01NBLkqNYmSgVYiTwUDcdogL