feat(charts): раздел «Чарты» (клиент) + детальная страница трека с графиком
- вкладка «Чарты» в навигации; экран: периоды (День/Неделя/Месяц/Всё), ранжированный список треков (ранг, обложка, проигрывания, тренд) - детальная карточка трека: метрики, график популярности (Canvas), лайк, кнопки музыкальных сервисов, кнопка «Текст песни» (ссылка на лицензированный Musixmatch — полный текст не встраиваем, авторское право) - ChartsRepository/LyricsRepository + эндпоинты charts/* в RadiolaApi (DTO) - превью-данные пока бэкенд не отдаёт charts (помечено TODO)
This commit is contained in:
@@ -2,9 +2,11 @@ package com.radiola.data.remote
|
||||
|
||||
import com.radiola.data.remote.dto.AuthResponseDto
|
||||
import com.radiola.data.remote.dto.BackendStationDto
|
||||
import com.radiola.data.remote.dto.ChartsResponseDto
|
||||
import com.radiola.data.remote.dto.HistoryResponseDto
|
||||
import com.radiola.data.remote.dto.MagicLinkRequestDto
|
||||
import com.radiola.data.remote.dto.MagicLinkVerifyDto
|
||||
import com.radiola.data.remote.dto.TrackStatsDto
|
||||
import com.radiola.data.remote.dto.UserSettingsDto
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import retrofit2.http.Body
|
||||
@@ -13,6 +15,7 @@ import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.PATCH
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
|
||||
interface RadiolaApi {
|
||||
|
||||
@@ -45,4 +48,21 @@ interface RadiolaApi {
|
||||
|
||||
@POST("users/me/history/{stationId}")
|
||||
suspend fun addHistory(@Path("stationId") stationId: String): JsonObject
|
||||
|
||||
// --- Чарты ---
|
||||
|
||||
@GET("charts/tracks")
|
||||
suspend fun getCharts(
|
||||
@Query("period") period: String,
|
||||
@Query("limit") limit: Int = 100
|
||||
): ChartsResponseDto
|
||||
|
||||
@GET("charts/tracks/{trackId}")
|
||||
suspend fun getTrackStats(@Path("trackId") trackId: String): TrackStatsDto
|
||||
|
||||
@POST("charts/tracks/{trackId}/like")
|
||||
suspend fun likeTrack(@Path("trackId") trackId: String): JsonObject
|
||||
|
||||
@DELETE("charts/tracks/{trackId}/like")
|
||||
suspend fun unlikeTrack(@Path("trackId") trackId: String): JsonObject
|
||||
}
|
||||
|
||||
60
app/src/main/java/com/radiola/data/remote/dto/ChartsDto.kt
Normal file
60
app/src/main/java/com/radiola/data/remote/dto/ChartsDto.kt
Normal file
@@ -0,0 +1,60 @@
|
||||
package com.radiola.data.remote.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/** DTO ответа чартов — список позиций. */
|
||||
@Serializable
|
||||
data class ChartsResponseDto(
|
||||
val items: List<ChartEntryDto> = emptyList()
|
||||
)
|
||||
|
||||
/** Одна позиция в чарте. */
|
||||
@Serializable
|
||||
data class ChartEntryDto(
|
||||
val rank: Int,
|
||||
val trackId: String,
|
||||
val artist: String,
|
||||
val song: String,
|
||||
val coverUrl: String? = null,
|
||||
val plays: Int = 0,
|
||||
val stationsCount: Int = 0,
|
||||
val likes: Int = 0,
|
||||
val prevRank: Int? = null,
|
||||
/** Направление: up | down | new | same */
|
||||
val trend: String = "same"
|
||||
)
|
||||
|
||||
/** Подробная статистика трека. */
|
||||
@Serializable
|
||||
data class TrackStatsDto(
|
||||
val trackId: String,
|
||||
val artist: String,
|
||||
val song: String,
|
||||
val album: String? = null,
|
||||
val coverUrl: String? = null,
|
||||
val releaseDate: String? = null,
|
||||
val firstSeen: String? = null,
|
||||
val totalPlays: Int = 0,
|
||||
val totalLikes: Int = 0,
|
||||
val isLiked: Boolean = false,
|
||||
val currentRank: Int? = null,
|
||||
val peakRank: Int? = null,
|
||||
val stations: List<StationPlaysDto> = emptyList(),
|
||||
val playsTimeline: List<PointDto> = emptyList(),
|
||||
val likesTimeline: List<PointDto> = emptyList()
|
||||
)
|
||||
|
||||
/** Проигрывания на конкретной станции. */
|
||||
@Serializable
|
||||
data class StationPlaysDto(
|
||||
val stationId: Int,
|
||||
val name: String,
|
||||
val plays: Int
|
||||
)
|
||||
|
||||
/** Одна точка тайм-лайна. */
|
||||
@Serializable
|
||||
data class PointDto(
|
||||
val date: String,
|
||||
val value: Int
|
||||
)
|
||||
Reference in New Issue
Block a user