feat: auth screen with auto-redirect, sync favorites/history with backend
This commit is contained in:
@@ -8,25 +8,26 @@ import com.radiola.domain.model.Track
|
||||
object ApiMapper {
|
||||
|
||||
fun StationDto.toDomain(): Station {
|
||||
val cover = iconPng ?: iconSvg ?: ""
|
||||
val cover = iconFillColored ?: bgImageMobile ?: bgImage ?: ""
|
||||
val stream = stream128 ?: stream320 ?: streamHls ?: "https://air.radiorecord.ru:805/${prefix}_128"
|
||||
return Station(
|
||||
id = id,
|
||||
name = name,
|
||||
prefix = prefix,
|
||||
streamUrl = "https://air.radiorecord.ru:805/${prefix}_128",
|
||||
streamUrl = stream,
|
||||
coverUrl = cover,
|
||||
genre = genre ?: "",
|
||||
tags = emptyList(),
|
||||
sortOrder = id
|
||||
genre = tooltip ?: "",
|
||||
tags = tags.map { it.name },
|
||||
sortOrder = sort
|
||||
)
|
||||
}
|
||||
|
||||
fun NowPlayingItemDto.toDomain(): Track {
|
||||
return Track(
|
||||
artist = artist,
|
||||
song = song,
|
||||
coverUrl = image600 ?: image100,
|
||||
stationName = prefix
|
||||
artist = track.artist,
|
||||
song = track.song,
|
||||
coverUrl = track.image600 ?: track.image100,
|
||||
stationName = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
25
app/src/main/java/com/radiola/data/remote/AuthInterceptor.kt
Normal file
25
app/src/main/java/com/radiola/data/remote/AuthInterceptor.kt
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.radiola.data.remote
|
||||
|
||||
import com.radiola.data.local.TokenDataStore
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
import javax.inject.Inject
|
||||
|
||||
class AuthInterceptor @Inject constructor(
|
||||
private val tokenDataStore: TokenDataStore
|
||||
) : Interceptor {
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
val request = chain.request()
|
||||
val token = tokenDataStore.currentToken
|
||||
|
||||
return if (token != null) {
|
||||
chain.proceed(
|
||||
request.newBuilder()
|
||||
.header("Authorization", "Bearer $token")
|
||||
.build()
|
||||
)
|
||||
} else {
|
||||
chain.proceed(request)
|
||||
}
|
||||
}
|
||||
}
|
||||
48
app/src/main/java/com/radiola/data/remote/RadiolaApi.kt
Normal file
48
app/src/main/java/com/radiola/data/remote/RadiolaApi.kt
Normal file
@@ -0,0 +1,48 @@
|
||||
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.HistoryResponseDto
|
||||
import com.radiola.data.remote.dto.MagicLinkRequestDto
|
||||
import com.radiola.data.remote.dto.MagicLinkVerifyDto
|
||||
import com.radiola.data.remote.dto.UserSettingsDto
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.DELETE
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.PATCH
|
||||
import retrofit2.http.Path
|
||||
|
||||
interface RadiolaApi {
|
||||
|
||||
@POST("auth/magic-link")
|
||||
suspend fun requestMagicLink(@Body dto: MagicLinkRequestDto): JsonObject
|
||||
|
||||
@POST("auth/verify")
|
||||
suspend fun verifyMagicLink(@Body dto: MagicLinkVerifyDto): AuthResponseDto
|
||||
|
||||
@GET("users/me")
|
||||
suspend fun getMe(): JsonObject
|
||||
|
||||
@GET("users/me/settings")
|
||||
suspend fun getSettings(): UserSettingsDto
|
||||
|
||||
@PATCH("users/me/settings")
|
||||
suspend fun updateSettings(@Body dto: UserSettingsDto): UserSettingsDto
|
||||
|
||||
@GET("users/me/favorites")
|
||||
suspend fun getFavorites(): List<BackendStationDto>
|
||||
|
||||
@POST("users/me/favorites/{stationId}")
|
||||
suspend fun addFavorite(@Path("stationId") stationId: String): JsonObject
|
||||
|
||||
@DELETE("users/me/favorites/{stationId}")
|
||||
suspend fun removeFavorite(@Path("stationId") stationId: String): JsonObject
|
||||
|
||||
@GET("users/me/history")
|
||||
suspend fun getHistory(): HistoryResponseDto
|
||||
|
||||
@POST("users/me/history/{stationId}")
|
||||
suspend fun addHistory(@Path("stationId") stationId: String): JsonObject
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.radiola.data.remote.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class AuthResponseDto(
|
||||
val accessToken: String,
|
||||
val user: UserDto
|
||||
)
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.radiola.data.remote.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class BackendStationDto(
|
||||
val id: String,
|
||||
val stationId: Int,
|
||||
val name: String,
|
||||
val prefix: String,
|
||||
val streamUrl: String,
|
||||
val coverUrl: String? = null,
|
||||
val genre: String? = null,
|
||||
val tags: List<String> = emptyList(),
|
||||
val sortOrder: Int = 0,
|
||||
val source: String = "local",
|
||||
val isOnline: Boolean = true
|
||||
)
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.radiola.data.remote.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class FavoritesResponseDto(
|
||||
val favorites: List<BackendStationDto> = emptyList()
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.radiola.data.remote.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class HistoryResponseDto(
|
||||
val items: List<BackendStationDto> = emptyList(),
|
||||
val total: Int = 0,
|
||||
val limit: Int = 50,
|
||||
val offset: Int = 0
|
||||
)
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.radiola.data.remote.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class MagicLinkRequestDto(
|
||||
val email: String
|
||||
)
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.radiola.data.remote.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class MagicLinkVerifyDto(
|
||||
val email: String,
|
||||
val code: String
|
||||
)
|
||||
@@ -4,15 +4,20 @@ import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class NowPlayingItemDto(
|
||||
data class TrackDto(
|
||||
@SerialName("id") val id: Int,
|
||||
@SerialName("prefix") val prefix: String,
|
||||
@SerialName("artist") val artist: String,
|
||||
@SerialName("song") val song: String,
|
||||
@SerialName("image600") val image600: String? = null,
|
||||
@SerialName("image100") val image100: String? = null
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class NowPlayingItemDto(
|
||||
@SerialName("id") val id: Int,
|
||||
@SerialName("track") val track: TrackDto
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class NowPlayingResponse(
|
||||
@SerialName("result") val result: List<NowPlayingItemDto>
|
||||
|
||||
@@ -8,12 +8,30 @@ data class StationDto(
|
||||
@SerialName("id") val id: Int,
|
||||
@SerialName("title") val name: String,
|
||||
@SerialName("prefix") val prefix: String,
|
||||
@SerialName("genre") val genre: String? = null,
|
||||
@SerialName("icon_png") val iconPng: String? = null,
|
||||
@SerialName("icon_svg") val iconSvg: String? = null
|
||||
@SerialName("tooltip") val tooltip: String? = null,
|
||||
@SerialName("sort") val sort: Int = 0,
|
||||
@SerialName("bg_image") val bgImage: String? = null,
|
||||
@SerialName("bg_image_mobile") val bgImageMobile: String? = null,
|
||||
@SerialName("icon_fill_colored") val iconFillColored: String? = null,
|
||||
@SerialName("stream_128") val stream128: String? = null,
|
||||
@SerialName("stream_320") val stream320: String? = null,
|
||||
@SerialName("stream_hls") val streamHls: String? = null,
|
||||
@SerialName("tags") val tags: List<TagDto> = emptyList()
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TagDto(
|
||||
@SerialName("id") val id: Int,
|
||||
@SerialName("name") val name: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StationsResult(
|
||||
@SerialName("stations") val stations: List<StationDto> = emptyList(),
|
||||
@SerialName("tags") val tags: List<TagDto> = emptyList()
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StationsResponse(
|
||||
@SerialName("result") val result: List<StationDto>
|
||||
@SerialName("result") val result: StationsResult
|
||||
)
|
||||
|
||||
10
app/src/main/java/com/radiola/data/remote/dto/UserDto.kt
Normal file
10
app/src/main/java/com/radiola/data/remote/dto/UserDto.kt
Normal file
@@ -0,0 +1,10 @@
|
||||
package com.radiola.data.remote.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class UserDto(
|
||||
val id: String,
|
||||
val email: String,
|
||||
val name: String? = null
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.radiola.data.remote.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class UserSettingsDto(
|
||||
val theme: String? = null,
|
||||
val language: String? = null,
|
||||
val autoPlay: Boolean? = null,
|
||||
val showOffline: Boolean? = null,
|
||||
val sleepTimerMinutes: Int? = null
|
||||
)
|
||||
Reference in New Issue
Block a user