feat: auth screen with auto-redirect, sync favorites/history with backend

This commit is contained in:
nk
2026-06-02 19:12:07 +03:00
parent d4adb1e7be
commit a83672b455
2934 changed files with 97351 additions and 163 deletions

View File

@@ -0,0 +1,74 @@
package com.radiola.data.local
import android.content.Context
import com.radiola.data.local.dto.LocalGroupDto
import com.radiola.data.local.dto.LocalStationsResponse
import com.radiola.domain.model.Station
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.serialization.json.Json
import java.io.BufferedReader
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class LocalStationDataSource @Inject constructor(
@ApplicationContext private val context: Context,
private val json: Json
) {
private var cachedResponse: LocalStationsResponse? = null
fun loadStations(): List<Station> {
android.util.Log.d("LocalStationDS", "loadStations() called")
val response = getResponse()
android.util.Log.d("LocalStationDS", "Parsed: ${response.stations.size} stations, ${response.groups.size} groups")
val groupMap = response.groups.associateBy { it.id }
return response.stations
.filter { it.enabled && !it.notWorked && it.stream != null }
.map { dto ->
val group = groupMap[dto.groupId]
val prefix = generatePrefix(dto.name)
Station(
id = dto.id,
name = dto.name,
prefix = prefix,
streamUrl = dto.stream!!,
coverUrl = group?.let { generateCoverUrl(it.name, dto.name) } ?: "",
genre = group?.name ?: "",
tags = listOfNotNull(group?.name?.takeIf { it.isNotBlank() }),
sortOrder = dto.id,
source = "local"
)
}
}
fun loadGroups(): List<LocalGroupDto> {
return getResponse().groups.filter { it.name.isNotBlank() }
}
fun getGroupNames(): List<String> {
return loadGroups().map { it.name }
}
private fun getResponse(): LocalStationsResponse {
android.util.Log.d("LocalStationDS", "getResponse() called")
cachedResponse?.let { return it }
val text = context.assets.open("stations.json").bufferedReader().use(BufferedReader::readText)
val parsed = json.decodeFromString(LocalStationsResponse.serializer(), text)
cachedResponse = parsed
return parsed
}
private fun generatePrefix(name: String): String {
return name.lowercase()
.replace(Regex("[^a-z0-9а-яё]+"), "_")
.trim('_')
.take(30)
}
private fun generateCoverUrl(groupName: String, stationName: String): String {
// Placeholder: return empty for now; Record API will override with real covers when available
return ""
}
}