diff --git a/README.md b/README.md index 2515c06..6c627fa 100644 --- a/README.md +++ b/README.md @@ -9,88 +9,58 @@ Built with Vite + vanilla ES modules (web) and Jetpack Compose + Media3/ExoPlaye ### Music Library - Stream music from your Navidrome / Subsonic library -- Browse artists, albums, playlists, starred tracks, and random picks -- Sort and filter views with chip filters -- Search / filter bar inside playlist detail and favorites (instant, client-side) -- Play count display — optional toggle in Settings +- Browse artists, albums, playlists, starred tracks, genres, and random picks +- Search across songs, albums, and artists - Star and context menu on every song row -- Genre browsing with genre-filtered song lists +- Play count display (optional) ### Lyrics -- Synced (word-by-word highlighted) and plain lyrics via lrclib.net -- Auto-fetched per track — no manual setup needed -- Fallback chain: exact match with duration → exact match without duration (catches version mismatches) → artist+title search → title-only search -- In-memory cache per session — no repeated network requests for the same track -- Android: smooth scroll animation keeps the active line centered +- Synced and plain lyrics via lrclib.net, auto-fetched per track +- Fallback chain: exact match → no-duration match → fuzzy artist+title search → title-only search +- In-memory cache per session ### Artist Pages -- Full-bleed hero card — artist photo as portrait + blurred background (desktop); full-bleed image with name overlay (mobile) -- Bio, similar artists, top songs pulled from Last.fm via Navidrome -- Concert events via Ticketmaster (upcoming shows with venue, date, ticket link) -- Albums cross-referenced against iTunes catalog — shows what's downloaded, partially downloaded, or missing +- Hero card with artist photo and blurred background +- Bio, similar artists, top songs from Last.fm +- Concert events via Ticketmaster +- Albums cross-referenced against iTunes catalog — shows downloaded vs. missing tracks - Artist cards with images in search results -- Quick actions: play top songs, shuffle all, open concerts ### Playback -- Queue management with shuffle, repeat (all / one), and radio mode (endless similar songs) -- Spotify-style shuffle — pre-shuffles the full queue so every song plays exactly once -- Now Playing overlay: synced lyrics, queue view, star, multi-artist links -- Multi-artist support — OpenSubsonic `artists` array shown as individual clickable links -- Gapless-style playback — next track pre-buffered 60 seconds before current track ends -- Lock screen / notification media controls (Android / iOS / desktop) -- Scrobbling to Navidrome (configurable: 15 s / 30 s / ⅓ / ⅔ / end) +- Queue with shuffle, repeat (all / one), and radio mode (endless similar songs) +- Now Playing overlay with synced lyrics, queue view, star, and multi-artist links +- Gapless-style playback — next track pre-buffered before current track ends +- Lock screen / notification media controls +- Scrobbling to Navidrome (configurable delay) -### Discovery (Erkunden tab) -- iTunes / Last.fm integration — charts, global search, 30-second previews, similar artists, recommendations -- Song Importer — paste a Spotify, YouTube, YouTube Music, or SoundCloud link to preview and download tracks +### Discovery +- iTunes / Last.fm — charts, global search, 30-second previews, similar artists +- Song Importer — paste a Spotify, YouTube, YouTube Music, or SoundCloud link to download ### Downloads (yt-dlp backend) -- Download individual tracks, full albums, or entire artists -- Sources: YouTube Music (primary), YouTube, SoundCloud, Spotify (via importer) -- iTunes enrichment — album, year, track number, genre, 1000×1000 cover art -- Duplicate detection — skips tracks already present on the server -- Standard filename: `01 - Artist - Title.ext`, organised into `AlbumArtist/Album/` folders +- Download tracks, albums, or entire artists from YouTube Music / SoundCloud / Spotify +- iTunes metadata enrichment — album art, year, track number, genre +- Duplicate detection, standard folder/filename structure ### Metadata Editor -- Edit title, artist, album artist, album, genre, year, track number, disc number -- Update embedded cover art via URL or file upload -- File renamed and moved automatically on save -- Navidrome rescan triggered after every save +- Edit tags (title, artist, album, genre, year, track, disc, cover art) +- File renamed and moved automatically; Navidrome rescan triggered on save ### Playlists -- Create, edit, and delete playlists -- Add / remove tracks -- Filter/search within a playlist +- Create, edit, delete playlists; add / remove tracks -### Audiobookshelf Integration (Web) -- Browse and stream audiobooks from your Audiobookshelf server -- Chapters list with chapter-by-chapter navigation -- Playback speed control -- Sleep timer -- Progress sync — current position saved back to ABS server - -### Audiobookshelf Integration (Android) -- Browse ABS libraries and audiobook list with covers, author, and runtime -- Tab appears in navigation only when ABS URL + API key are configured in Settings - -### Settings -- Connection status indicators (green / red dot) for ABS server and NovaSonic backend — tested live with a button -- Save button at top and bottom of settings for easy access -- Order matches web: Theme → Bibliothek → Audiobookshelf → Discover APIs → Navidrome Server +### Audiobookshelf Integration +- **Web:** browse libraries, stream audiobooks, chapter navigation, playback speed, sleep timer, progress sync +- **Android:** browse libraries and audiobook list (tab hidden until ABS is configured in Settings) ### App — Web PWA - Installable on Android / iOS / desktop -- Randomized home greetings -- Multiple color themes, dark mode, mobile-first responsive layout -- German UI +- Multiple color themes, German UI -### App — Android (native) -- Native Jetpack Compose app with Material3 design — not a WebView wrapper -- Media3 / ExoPlayer backend for reliable audio playback -- OS notification with skip / play / pause buttons -- Last played song persisted across restarts — shown in mini player bar; tap play to resume -- Audiobookshelf library browser (tab hidden until ABS is configured) -- No login screen flash on startup when credentials are already saved +### App — Android (native Jetpack Compose) +- Media3 / ExoPlayer backend +- OS notification with playback controls +- Last played song shown in mini player bar on restart; tap to resume --- @@ -106,14 +76,14 @@ NovaSonic/ │ │ ├── detail.js # Artist / album detail pages │ │ ├── views.js # Navigation, page loaders, search │ │ ├── events.js # Ticketmaster concert events -│ │ ├── home.js # Home page, artist image cache +│ │ ├── home.js # Home page │ │ ├── search.js # Search, artist/album navigation │ │ ├── playlists.js # Playlist management │ │ ├── spotify.js # Spotify importer │ │ ├── youtube.js # YouTube importer │ │ ├── soundcloud.js # SoundCloud importer │ │ ├── navigation.js # Client-side router -│ │ └── abs.js # Audiobookshelf integration (web) +│ │ └── abs.js # Audiobookshelf integration │ ├── ui/ │ │ ├── ui.js # Modals, sidebar, context menu │ │ ├── components.js # Song rows, cards, shared UI @@ -123,8 +93,8 @@ NovaSonic/ │ │ ├── notify.js # Toast notifications │ │ └── settings.js # Settings page │ ├── state.js # Shared mutable state (S object) -│ ├── utils.js # md5, esc, formatDur, toast -│ ├── api.js # Subsonic API, iTunes API, cover art, romaji display +│ ├── utils.js # Helpers (md5, esc, formatDur, toast) +│ ├── api.js # Subsonic API, iTunes API, cover art │ └── main.js # App init, audio wiring, window globals ├── backend/ │ ├── novasonic-server.js # Express API: downloads, metadata, events proxy, ABS proxy @@ -177,7 +147,7 @@ Edit `.env`: NAVIDROME_URL=https://music.yourdomain.com BACKEND_URL=https://novasonic-api.yourdomain.com -MUSIC_PATH=/srv/navidrome/music # absolute path to your music folder on the host +MUSIC_PATH=/srv/navidrome/music AUDIO_FMT=mp3 # mp3 | flac | opus | best AUDIO_QUALITY=0 # 0 = best (yt-dlp) @@ -195,13 +165,13 @@ TICKETMASTER_API_KEY= # optional — free key from developer.ticketmaster.com docker compose up -d ``` -This starts both the frontend (nginx on port 8080) and the backend (Node.js on port 3700). Route both ports through your reverse proxy. +Frontend on port 8080, backend on port 3700. Route both through your reverse proxy. ### 3. First launch -1. Open the app and enter your Navidrome server URL, username and password -2. Optionally add a Last.fm API key in Settings for recommendations and artist bios -3. Optionally connect Audiobookshelf in Settings to stream audiobooks +1. Enter your Navidrome server URL, username, and password +2. Optionally add a Last.fm API key in Settings for bios and recommendations +3. Optionally connect Audiobookshelf in Settings 4. Optionally add the NovaSonic backend URL in Settings to enable downloads --- @@ -220,13 +190,13 @@ This starts both the frontend (nginx on port 8080) and the backend (Node.js on p | Variable | Default | Description | |---|---|---| | `PORT` | `3700` | Port the backend listens on | -| `MUSIC_PATH` | `/music` | Absolute path to your Navidrome music folder (mounted as volume) | -| `AUDIO_FMT` | `mp3` | Download output format (`mp3`, `flac`, `opus`, `best`) | +| `MUSIC_PATH` | `/music` | Absolute path to your Navidrome music folder | +| `AUDIO_FMT` | `mp3` | Download format (`mp3`, `flac`, `opus`, `best`) | | `AUDIO_QUALITY` | `0` | yt-dlp audio quality (0 = best) | | `MAX_PARALLEL` | `2` | Max concurrent download jobs | -| `DOWNLOAD_BACKEND` | `auto` | `ytdlp` / `squid` / `auto` (tries Qobuz first, falls back to yt-dlp) | +| `DOWNLOAD_BACKEND` | `auto` | `ytdlp` / `squid` / `auto` | | `SQUID_QUALITY` | `mp3` | Qobuz quality: `mp3`, `flac`, `hi-res` | -| `TICKETMASTER_API_KEY` | — | Free API key from [developer.ticketmaster.com](https://developer.ticketmaster.com) — enables concert events on artist pages | +| `TICKETMASTER_API_KEY` | — | Free key from [developer.ticketmaster.com](https://developer.ticketmaster.com) | --- diff --git a/android/app/src/main/kotlin/com/novasonic/app/ui/screen/SettingsScreen.kt b/android/app/src/main/kotlin/com/novasonic/app/ui/screen/SettingsScreen.kt index 58249f8..e3b1f5c 100644 --- a/android/app/src/main/kotlin/com/novasonic/app/ui/screen/SettingsScreen.kt +++ b/android/app/src/main/kotlin/com/novasonic/app/ui/screen/SettingsScreen.kt @@ -203,9 +203,6 @@ fun SettingsScreen() { Spacer(Modifier.height(8.dp)) - // ── Save button (BOTTOM) ───────────────────────────────────────────── - SaveButton(vm, state.isSaving, state.savedOk, state.error) - HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp), color = NsBorder) OutlinedButton(