Commit Graph

15 Commits

Author SHA1 Message Date
nk
69682268f3 feat(app): кнопка «Распознать трек» (Shazam) + история распознанных
- кнопка распознавания в плеере: видна только на музыкальных станциях без
  метаданных эфира (track == null), показывает спиннер и результат через Toast
- распознанный трек отображается в плеере и пишется в ОТДЕЛЬНУЮ историю
  распознанных (не дублируется в историю эфирных треков — гейт по ключу)
- экран Истории: переключатель «Треки эфира | Распознанные», два списка
- Room: таблица recognized_track (миграция 7→8), DAO/репозиторий
- ShazamRepository → POST /shazam/recognize/{stationId}, маппинг 503/400 в текст
- MusicGenres.isMusicStation — клиентский гейт (синхронизирован с бэкендом)
- bump backend submodule (модуль shazam)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 18:38:17 +03:00
nk
e736c2393f feat(eq): настоящий эквалайзер + улучшайзеры звука (audiofx)
Раньше пресет эквалайзера в настройках был косметикой (лежал в DataStore, к звуку
не подключён). Теперь — реальные системные эффекты на фикс. аудиосессии плеера:
- AudioEffectsController: графический Equalizer (полосы устройства), BassBoost,
  Virtualizer (объём), LoudnessEnhancer (громкость тихих, до +12 дБ). Привязка к
  generateAudioSessionId() в PlayerController, переживает смену станций. Применение
  в реальном времени, сохранение в DataStore (commit на отпускании слайдера).
- Отдельный экран EqualizerScreen (Настройки → ЗВУК → Эквалайзер): тумблер,
  системные пресеты + «Свой», слайдеры полос (±дБ), bass/virtualizer/loudness.
- Эффекты best-effort: при отсутствии поддержки блок недоступен (null), UI скрывает.
- Убран фейковый чип-пресет Flat/Rock/Pop/Jazz/Bass.
2026-06-06 21:14:38 +03:00
nk
ed926e0a9d feat(theme): выбор цветовой темы (8 палитр) в настройках
8 тёмных палитр (Лес/Океан/Закат/Аметист/Неон/Янтарь/Лёд/Роза) в Palettes.kt.
RadiolaColors теперь несёт все токены + градиент; RadiolaTheme(palette) строит из
неё и RadiolaColors, и Material ColorScheme — всё приложение берёт цвета через
RadiolaTheme.colors, поэтому смена палитры перекрашивает мгновенно. Бренд-марка
(AppMark/Wordmark) тоже следует теме. Выбор в DataStore (theme_palette, дефолт
forest), читается в MainActivity и подаётся в тему. Секция «ТЕМА ОФОРМЛЕНИЯ» в
настройках — горизонтальный ряд свотчей с превью (фон+акцент+градиент).
2026-06-06 19:11:33 +03:00
nk
1e00287486 feat(player): 4 стиля визуализатора + выбор в настройках
Добавлены стили анимации воспроизведения: столбики от центра, столбики
снизу (спектр), плавная волна, радиальный — все от реального спектра звука
(Visualizer.kt). Пользователь выбирает стиль в Настройках → «Анимация
воспроизведения» (живые превью каждого стиля, тап выбирает). Сохраняется
пер-юзер (DataStore visualizer_style). Плеер рисует выбранный стиль
(радиальный — повыше). Превью и пауза — мягкая «дышащая» анимация.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 18:18:55 +03:00
nk
147b3ac81d feat(covers): приоритет играющего трека + троттл 0.8с
Обложки наливались общей очередью (1.5с) — играющий трек ждал свою очередь.
Добавлена приоритетная дорожка: трек, который слушают сейчас, обогащается
первым (PlayerViewModel → NowPlayingRepository.enrichCoverNow). Троттл общей
очереди ускорен 1.5с→0.8с. Дедуп разнесён на enqueued/processed, чтобы
дорожки не дублировали работу.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 17:11:44 +03:00
nk
8d2c53c441 feat(stations): скрывать украинские станции (ROKS, Kiss FM) для РФ
Radio ROKS и Kiss FM (TavR Media, хосты radioroks.ua / kissfm.ua) недоступны
с российских IP без VPN. Теперь для пользователей из РФ они полностью скрыты
— и сами станции (везде, где используется список), и их чипы-категории.

Страна определяется по IP (api.country.is → ipapi.co; при VPN вернёт страну
выходного узла, тогда станции доступны и НЕ скрываются), с фолбэком на страну
SIM/сети/локали устройства, если IP-сервис недоступен (в РФ часто заблокирован).
Код страны кэшируется (DataStore). Фильтр в GetStationsUseCase (combine со
страной) + чипы в StationsViewModel. id 741 «Радио РОКС» (stream.roks.com) —
российская, под правило не попадает.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 14:46:42 +03:00
nk
5ffaf9a924 feat(player): переключатель качества звука на экране воспроизведения
Перепроверены все 594 рабочие станции на наличие битрейт-вариантов
потока (скрипт-пробер). У 71 станции найдено по 2–4 качества
(Record-флагманы 96/64/32, zaycev 256/128/48, ВГТРК 192/128/64,
НАШЕ/Орфей/Шансон HQ и др.) — записаны в поле qualities в stations.json.
HLS (EMG) и Love (UID-привязка) корректно пропущены.

Клиент: модель StreamQuality, хранение в Room (миграция v5),
предпочтение битрейта в настройках. На экране плеера — чип текущего
качества (виден только если вариантов ≥2) и шторка «Качество звука»
со ступенями; переключение на лету без сброса now-playing, выбор
запоминается между станциями.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 12:36:47 +03:00
nk
1ef60b6053 fix(now-playing): матч текущего трека по id станции, а не по имени
Станции с одинаковым именем в разных сетях (напр. «Deep» у Record и DFM)
показывали один и тот же трек — матч был по lowercase-имени. Каталожный id
(== station.id) уникален и совпадает со stationId в /now-playing, поэтому
матчим по id. Убран весь by-name путь (репозиторий, плеер, карточки).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 15:54:24 +03:00
nk
72ecbae866 fix(player): матч now-playing по имени станции (обложки DFM в плеере)
Плеер искал now-playing по числовому id станции, а у локальных станций (DFM)
id не совпадает с каталожным → API-путь с обложкой не срабатывал, плеер падал
на ICY из потока (без обложки). Теперь getNowPlaying матчит по id, затем по
имени станции (как карточки). DFM-обложки появляются и в плеере.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 14:36:39 +03:00
nk
99503fc77a feat(charts): фильтр по жанру + жанр/стиль/лейбл/год на детальной трека
Подтягиваем обогащённые данные с бэкенда (Discogs): genre/styles/label/year
в чартах и детальной странице.

- ChartEntry/TrackStats + DTO: добавлены genre/styles/label/year
- RadiolaApi: getCharts(?genre=), новый getGenres()
- ChartsViewModel: состояние выбранного жанра + список жанров, перезагрузка
- ChartsScreen: ряд чипов-фильтров по жанру (Все + жанры),
  жанр/стили чипами и «Лейбл · Год» на детальной
- убран демо-fallback (SAMPLE_CHARTS) — бэкенд живой

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 13:55:35 +03:00
nk
ee689ce380 feat(stations): обложка текущего трека на карточке станции + подпись
Для станций без своей обложки (и для Radio Record — единый стиль) карточка
показывает обложку играющего трека с тёмным градиентом и подписью трек/исполнитель.
Источник — /now-playing (теперь с name станции), матч по имени, обновление 20с.
Приоритет: трек -> логотип станции -> фирменная плитка.
2026-06-03 12:18:19 +03:00
nk
ba32973beb feat(lyrics): тексты песен внутри приложения через LRCLIB
- LrcLibApi (api/get + api/search, User-Agent), DI @Named(lrclib) Retrofit
- LyricsRepository.fetchLyrics -> LyricsResult (plain/synced/instrumental)
- LyricsViewModel + LyricsSheet (загрузка/инструментал/найдено/не найдено),
  прокрутка + атрибуция LRCLIB
- кнопка «Текст песни» открывает встроенный экран (плеер + деталь трека чартов),
  вместо ссылки в браузере
2026-06-03 11:47:00 +03:00
nk
d0e5f4e8c5 feat(charts): раздел «Чарты» (клиент) + детальная страница трека с графиком
- вкладка «Чарты» в навигации; экран: периоды (День/Неделя/Месяц/Всё),
  ранжированный список треков (ранг, обложка, проигрывания, тренд)
- детальная карточка трека: метрики, график популярности (Canvas), лайк,
  кнопки музыкальных сервисов, кнопка «Текст песни» (ссылка на лицензированный
  Musixmatch — полный текст не встраиваем, авторское право)
- ChartsRepository/LyricsRepository + эндпоинты charts/* в RadiolaApi (DTO)
- превью-данные пока бэкенд не отдаёт charts (помечено TODO)
2026-06-02 23:24:42 +03:00
nk
a83672b455 feat: auth screen with auto-redirect, sync favorites/history with backend 2026-06-02 19:12:07 +03:00
nk
aad1361043 feat(domain): add repository interfaces 2026-06-01 12:07:29 +03:00