* feat: add sleep timer to player bar
- Add sleep timer button in player bar right controls
- Preset options: End of song, 5/10/15/30/45 min, 1 hr, 2 hrs
- Custom timer with HH:MM:SS input fields
- Timer only counts down while music is playing
- Timer pauses playback when it expires
- End-of-song mode pauses at the next track change
- Uses theme-aware styling (--theme-colors-surface)
- Add sleepTimer/sleepTimerOff icons (LuTimer/LuTimerOff)
- Add i18n strings for sleep timer UI
---------
Co-authored-by: York <york@BonecharMac.local>
Co-authored-by: jeffvli <jeffvictorli@gmail.com>
The CommandPalette component was being rendered twice when in mobile view:
1. In ResponsiveLayout via LayoutHotkeys (which handles all layouts)
2. In MobileLayout directly
This caused two overlapping command menus to open when pressing Ctrl+K
in mobile view, with keyboard input going to the background menu.
The fix removes the duplicate CommandPalette from MobileLayout since
LayoutHotkeys already provides it for all layouts (both desktop and mobile).
Fixes#1666
Co-authored-by: Kai Gritun <kai@kaigritun.com>
- Add `handleScrobbleFromRepeat` callback to reset scrobble state and send 'start' event when player repeats a song, ensuring accurate scrobbling in repeat mode.
- Fix typo in `web.vite.config.ts` by correcting '@tanstack_react-query-persist-client' to '@tanstack/react-query-persist-client' for proper package reference.
* implement theme
* refactor theme stylesheets to load inline to simplify vite bundling
* add missing css module scope name for web build
---------
Co-authored-by: jeffvli <jeffvictorli@gmail.com>
* Prevent double fetching when force refreshing paginated views
* remove await from infinite list loader query invalidation
* add mutation and loading state to list refresh
* add non-suspense query to list genre filters to add loading state
* remove list count data set on random queries
---------
Co-authored-by: jeffvli <jeffvictorli@gmail.com>