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
2e970317f6 fix(stations): Record — звук на станциях с мёртвым stream_128 (Лето и др.)
У части станций Record поле stream_128 ведёт на мёртвый маунт {prefix}64.aacp
(404) — обложка/трек есть, а поток молчит (Summer Lounge, Beach Party, Reggae,
Mashup, Afro House, Nu Dance, Workout, Gop FM…). Поле stream_320 ({prefix}96.aacp)
живо у всех. Сменён приоритет выбора потока на stream_320.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 21:10:48 +03:00
nk
be6e1acfd8 fix(stations): жанровые чипы Record (Лето и др.) больше не пустые
Record API кладёт категории станции в поле "genre" (массив {id,name}), а
StationDto/ApiMapper читали только "tags" (у станции отсутствует) → у всех
станций Рекорда жанровые теги были пустыми, и чипы вроде «Лето» при клике
показывали пустоту. Добавлено поле genres (@SerialName genre), маплю genre+tags
в Station.tags. Раздел «Лето» теперь наполняется летними станциями Record
(Chill House, Beach Party, Tropical, Summer Lounge, Mashup и др.).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 20:52:21 +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
4a33aa6fb5 feat(covers): клиентское обогащение обложек через iTunes (обход бана сервера)
Серверный IP забанен Apple (iTunes search 429), а Deezer из РФ пуст — обложки
перестали наливаться. Теперь iTunes-поиск делает КЛИЕНТ (его IP не забанен):
для now-playing-треков без обложки ищет арт в iTunes и шлёт ССЫЛКУ на наш
бэкенд (POST /covers/submit), сервер качает её (CDN из РФ доступен) и кладёт
WebP — дальше обложка приходит всем через /now-playing. Дедуп по треку +
троттлинг 1.5с (CoverEnrichmentManager). Сервер: host-whitelist (SSRF),
идемпотентность (first-write-wins).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 16:59:32 +03:00
nk
320cac546b feat(love): воспроизведение Love Radio через сессионный UID + now-playing главного
Потоки Love защищены: клиент берёт UID из их player/config (со своего IP) и
подставляет в n340-поток — играет музыка. LoveStreamResolver + LoveApi. Каталог
переведён на n340. Now-playing главного Love Radio по ICY; саб-каналы трек не
отдают нигде — показываем без трека.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 20:14:52 +03:00
nk
615e3435e3 feat(stations): клиент скрывает оффлайн-станции с бэкенда (системно)
При обновлении каталога тянем GET /stations/offline-ids и удаляем эти станции
из локальной БД. Мёртвые плитки теперь пропадают сами (бэк их метит health-check'ом),
без пересборки приложения. Фолбэк на статичный enabled, если бэк недоступен.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 18:04:35 +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
fc9b23f62c fix(player): now-playing с нашего бэкенда вместо сырого Record-эндпоинта
Record /stations/now использует id now-слотов, не совпадающие с id каталога,
поэтому клиент не находил трек по station.id (трек/обложка не показывались).
Теперь берём GET /now-playing с нашего бэка (корректный маппинг recordSync,
ключ = id станции) -> плеер показывает название трека и обложку.
2026-06-03 10:59:59 +03:00
nk
d0e5f4e8c5 feat(charts): раздел «Чарты» (клиент) + детальная страница трека с графиком
- вкладка «Чарты» в навигации; экран: периоды (День/Неделя/Месяц/Всё),
  ранжированный список треков (ранг, обложка, проигрывания, тренд)
- детальная карточка трека: метрики, график популярности (Canvas), лайк,
  кнопки музыкальных сервисов, кнопка «Текст песни» (ссылка на лицензированный
  Musixmatch — полный текст не встраиваем, авторское право)
- ChartsRepository/LyricsRepository + эндпоинты charts/* в RadiolaApi (DTO)
- превью-данные пока бэкенд не отдаёт charts (помечено TODO)
2026-06-02 23:24:42 +03:00
nk
bcb999ace9 feat: WebSocket now-playing via Socket.IO from backend 2026-06-02 19:52:15 +03:00
nk
a83672b455 feat: auth screen with auto-redirect, sync favorites/history with backend 2026-06-02 19:12:07 +03:00
nk
62674fcc3f feat(data): add Retrofit API, DTOs and mappers 2026-06-01 12:11:15 +03:00