GET /app/clients now returns up to 8 Gitea releases per OS so users can download older installers while they still exist after prune.
Co-authored-by: Cursor <cursoragent@cursor.com>
Search hits omit album covers and artist images. The worker now reads the full song and artist, stores the description, and leaves Genius image URLs unchanged on mobile.
Co-authored-by: Cursor <cursoragent@cursor.com>
Serve desktop and Android builds from the latest Gitea release on /download, and fix the desktop compile and CI flakes that blocked v1.3.0.
Co-authored-by: Cursor <cursoragent@cursor.com>
Labels that wrapped to two lines pushed their inputs down, the storage
select had its own label style, and the checkbox sat in the middle of its
cell. The section now lays label, input and hint rows out with subgrid, and
the select no longer stretches past its column.
Also add a web-fake launch config that runs the web app on the fake API.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The web check only accepted FLAC and WAV, so AIFF files were flagged
"needs attention" although the server already counts them as lossless.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Introduced a new warning for users uploading non-FLAC or WAV formats, indicating that these formats should only be used as a last resort.
- Added functionality to highlight files needing format attention in the upload queue.
- Updated the UI to provide clearer guidance on acceptable audio formats during uploads.
- Improved documentation to reflect changes in upload requirements and user interface updates.
Reviewing the upload queue is now a per-user flag (reviews_uploads), not part
of the admin role: several people can hold it, a moderator can have it, and an
admin may not. Only admins grant or revoke it; existing admins keep it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Quality upgrades, batch covers, staging preview, and resume after reload are in the queue. Loudness and crossfade work on web and Android, and the documented checks now have suites.
Co-authored-by: Cursor <cursoragent@cursor.com>
- POST /admin/users/{id}/reset-recommendations clears the taste profile
(onboarding, CF vector, bandit), play stats and wave impressions; likes,
dislikes and history stay, wave sessions stay so a playing wave keeps going
- moderators may reset plain users, admins anyone including themselves;
the reset is written to the audit log
- users panel gets the menu action with a confirmation; docs updated
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- appearance settings get "collapse search" (off keeps the field always open)
and separate switches for the activity and mood pickers on the home page;
stored in ui_prefs (search_collapse, home_activities, home_moods)
- Collection and Admin headers in the sidebar fold their items; the state is
remembered in the browser, a folded Admin shows the review queue badge;
icon-only and phone layouts always show every item
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On an Android 16 emulator the release APK crashed at launch with
"Cannot read property 'NativeModule' of undefined": libexpo-modules-core.so
was missing for the ABI the device picked. Two build defects:
- librnskia.so was linked with 4 KB segment alignment (Skia 2.0.0-next.4
lacks ANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES), so 16 KB page devices cannot
load it; a pnpm patch adds the flag
- the APK carried incomplete x86, x86_64 and armeabi-v7a folders from the
React Native libraries; an Expo config plugin keeps only arm64-v8a, the ABI
the native modules are built for (the APK also halves in size)
scripts/check-apk.mjs now fails the release on another ABI, a missing core
library or a library not aligned to 16 KB.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Leaving the field scheduled a close 120 ms later; coming back and typing
within that window let the old timer hide the fresh suggestions. Focus now
cancels the pending close. This also made the search box test flaky.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- settings get a search position (left, center by default, right); the top bar
is three zones and the suggestions open towards the free space
- buttons, chips, tabs, menu items and the home screen controls are not
text-selectable, so clicks and double clicks no longer highlight labels
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- /android is a public page with the latest APK, the server address to copy
and three install steps; linked from the sign-in screen and the profile menu
- failed audio analysis can be retried from the library page, which also shows
the most common error; the analyzer no longer burns attempts on files that
are missing because the disk is not mounted
- the top bar search folds into a round button and slides open on click, "/"
or Ctrl+K
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every shell child got the same z-index, so the page painted over the search
suggestions and the profile menu and swallowed their clicks: suggestions could
not be picked, and the language switch and settings item did nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Primary buttons, selected segments and context chips use accent-fill, as on
the web, so their labels meet WCAG AA contrast.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An axe-core audit of every screen in both themes found low contrast on white
text over the accent and on caption text, track rows using row roles without
cells, and unlabelled progress bars. Accent fills now use a darker token,
caption text meets 4.5:1, track lists are lists and progress bars are labelled.
The queue drawer slides in from the right as designed, takes focus, closes on
Escape and notes that the wave never ends.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The library page compares listen-through, early-skip and like rates per
impression model version, so v1 and the trained ranker can be compared online.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- GET /onboarding offers the library's top artists (with album covers)
and genres and says whether to show it (not done and < 10 plays);
PUT /me/onboarding stores the choice or a skip (migration 00009).
- The recommender seeds the taste from it while the user has fewer than
30 scored tracks: chosen artists' tracks +1, chosen genres +0.5.
- Web: onboarding replaces the wave on the home page until done or
skipped; artist grid with covers, genre chips, at least 3 artists.
- e2e journey and the recommender DB test cover it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Changing the activity or mood used to keep the current track playing
and only replace the upcoming ones, so nothing seemed to happen. Now the
first track of the new batch starts immediately (web and Android). The
interrupted track is not reported to the wave as a skip and is recorded
in history only if it played for at least 30 s, so a context change does
not teach the recommender a false dislike.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Ambient background in the app shell: three drifting blurred blobs,
the third one tinted with the current track's cover; can be turned off
in settings and stays still with reduced motion.
- Island player variant (floating glass panel) next to the bar, chosen
in settings; player source line ("Album · …", "My Wave"), reactions
around the transport controls, queue drawer.
- Sidebar: like / dislike counters, pending uploads badge on Queue,
admin Settings page holding the upload queue limits.
- Collection: header tile with kicker, underline tabs, time / number
lead column with an equalizer for the current track, album column,
dimmed dislikes with undo, Play all / Shuffle pills.
- Album: cover-tinted header and Play / Shuffle; artist: artist wave,
Play and popular tracks (new GET /artists/{id}/top-tracks).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Suggest tracks: drag-and-drop of files and folders with relative
paths, streaming SHA-256 in a Web Worker (hash-wasm), duplicate
precheck, batch reservation and tus-js-client upload (8 MB chunks,
4 in parallel, token refresh on 401, resume of failed files).
- My uploads: statuses, rejection reasons, withdraw, quota meter.
- Upload queue (admin): status tabs, possible-duplicate filter, batches,
metadata and storage editing, bulk approve / reject with a reason,
import retry, and the queue settings form.
- Sidebar section for moderators and admins; ru / en strings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- storage-agent: POST /internal/files copies a staged file into a source
(temp file, fsync, SHA-256 check, hard link so nothing is overwritten,
" (2)" suffix on conflict, owner PIPU_FILE_UID/GID) and
POST /internal/files/test. NFS sources that accept uploads are mounted
rw in an agent-only /library-rw and bind-mounted read-only for others;
local sources are written through /library-host-rw.
- meta: write templates ({track:02}, {disc:1-}, [optional]) with name
sanitising and length limits, suggestion from the source's regexes
and a reversibility check against 50 catalogue tracks.
- API and admin UI: accepts_uploads / write_template on sources,
write-template suggest and check endpoints, write test result.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- My Wave is rendered with react-native-skia on the UI thread; physics
and colour helpers moved to @pipu/core (wave-anim) and shared with web.
- Full-screen player honours ui_prefs.mobile_player (cover / wave).
- Theme switching (dark / light / system) via a theme context and
useColors() across all screens.
- Profile: theme, wave variant, player view, sound quality sheet
(Wi-Fi / mobile / downloads), recent-tracks cache clearing on next
cold start, and a change-password sheet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Likes and dislikes without a network are kept in a pending_reactions
table (last reaction per track wins) and sent when the connection
returns, instead of being rolled back. Downloaded track DTOs pick up the
new reaction so the offline wave and Downloads reflect it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>