* improve album artist favorite performance and search
* adjust top songs / favorite songs sections
---------
Co-authored-by: jeffvli <jeffvictorli@gmail.com>
- this query in some cases can return a very large amount of data, depending on the size of the user's library
- increasing the cacheTime reduces the frequency of fetches while disabling structuralSharing reduces the need for react-query to do a deep equality comparison for the cache
* 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>