feat(settings): wire Playback + Scrobbling panels to the backend

Adds src/api/endpoints/settings.ts (getSettings/updateSettings,
getScrobbling/updateScrobbling) plus AppSettings/ScrobblingConfig types
and a Settings cache tag. Replaces the "coming soon" scaffolds:

- Playback: stream-quality preference (SegmentedControl), server-synced.
- Scrobbling: enable + provider (Last.fm/ListenBrainz) + username +
  write-only session key, with a linked/not-linked badge and save states.

Built with modern-sk (Window/SegmentedControl/TextField/Button/Callout/
Badge) + the shared Loading/Error states; en + ru strings added. Server
state flows through RTK Query hooks only (no fetch in components).

Also drops a pre-existing unused TextField import in LibraryPage that was
failing `tsc --noEmit`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Цвылев Александр Вадимович
2026-07-28 15:16:19 +03:00
parent 205b51ec73
commit 57044dabba
8 changed files with 419 additions and 11 deletions
+35
View File
@@ -358,6 +358,41 @@ const ru: Translations = {
scrobbling: 'Скробблинг',
instance: 'Сервер',
},
common: {
save: 'Сохранить',
saving: 'Сохранение…',
},
playback: {
streamQuality: 'Качество потока',
streamQualityHint:
'Качество звука при стриминге с сервера. «Оригинал» отдаёт файл как есть.',
quality: {
original: 'Оригинал',
high: 'Высокое',
medium: 'Среднее',
low: 'Низкое',
},
},
scrobbling: {
description: 'Отправляйте свои прослушивания в Last.fm или ListenBrainz.',
configured: 'Подключено',
notConfigured: 'Не подключено',
enabled: 'Скробблинг',
on: 'Вкл',
off: 'Выкл',
provider: 'Сервис',
lastfm: 'Last.fm',
listenbrainz: 'ListenBrainz',
username: 'Имя пользователя',
usernamePlaceholder: 'ваш логин',
sessionKey: 'Ключ сессии / токен',
sessionKeyPlaceholder: 'вставьте токен',
sessionKeyKeep: 'оставьте пустым, чтобы сохранить текущий токен',
sessionKeyHint:
'Хранится на сервере в зашифрованном виде и больше не показывается.',
saved: 'Настройки скробблинга сохранены.',
error: 'Не удалось сохранить. Попробуйте ещё раз.',
},
},
admin: {
userDetail: 'Пользователь',