feat(data): add repository implementations

This commit is contained in:
nk
2026-06-01 12:18:10 +03:00
parent 110fe0795e
commit e255b0458d
5 changed files with 241 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
package com.radiola.data.repository
import com.radiola.data.local.AppDatabase
import com.radiola.data.local.entity.StationEntity
import com.radiola.domain.model.Station
import com.radiola.domain.repository.FavoritesRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
class FavoritesRepositoryImpl @Inject constructor(
private val db: AppDatabase
) : FavoritesRepository {
override fun getFavorites(): Flow<List<Station>> {
return db.stationDao().getFavorites().map { list ->
list.map { it.toDomain() }
}
}
override suspend fun addFavorite(station: Station) {
db.stationDao().setFavorite(station.id, true)
}
override suspend fun removeFavorite(stationId: Int) {
db.stationDao().setFavorite(stationId, false)
}
override fun isFavorite(stationId: Int): Flow<Boolean> {
return db.stationDao().isFavorite(stationId)
}
override suspend fun reorderFavorites(orderedIds: List<Int>) {
// TODO: implement drag-sort reordering
}
private fun StationEntity.toDomain(): Station = Station(
id = id,
name = name,
prefix = prefix,
streamUrl = streamUrl,
coverUrl = coverUrl,
genre = genre,
tags = tags.split(",").filter { it.isNotBlank() },
sortOrder = sortOrder
)
}

View File

@@ -0,0 +1,34 @@
package com.radiola.data.repository
import com.radiola.data.remote.RecordApi
import com.radiola.data.remote.ApiMapper.toDomain
import com.radiola.domain.model.Track
import com.radiola.domain.repository.NowPlayingRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
class NowPlayingRepositoryImpl @Inject constructor(
private val api: RecordApi
) : NowPlayingRepository {
private val _nowPlaying = MutableStateFlow<Map<String, Track>>(emptyMap())
override fun getNowPlaying(stationPrefix: String): Flow<Track?> {
return _nowPlaying.map { it[stationPrefix] }
}
override fun getAllNowPlaying(): Flow<Map<String, Track>> = _nowPlaying
override suspend fun refreshNowPlaying(): Result<Unit> {
return try {
val response = api.getNowPlaying()
val map = response.result.associate { it.prefix to it.toDomain() }
_nowPlaying.value = map
Result.success(Unit)
} catch (e: Exception) {
Result.failure(e)
}
}
}

View File

@@ -0,0 +1,51 @@
package com.radiola.data.repository
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.core.stringSetPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import com.radiola.domain.repository.SettingsRepository
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
class SettingsRepositoryImpl @Inject constructor(
@ApplicationContext private val context: Context
) : SettingsRepository {
private val dataStore = context.dataStore
companion object {
private val LAST_STATION_ID = intPreferencesKey("last_station_id")
private val SLEEP_TIMER = intPreferencesKey("sleep_timer_minutes")
private val ENABLED_SERVICES = stringSetPreferencesKey("enabled_deeplink_services")
private val EQUALIZER_PRESET = stringPreferencesKey("equalizer_preset")
private val RECORDING_ENABLED = booleanPreferencesKey("recording_enabled")
}
override fun getLastStationId(): Flow<Int?> = dataStore.data.map { it[LAST_STATION_ID] }
override suspend fun setLastStationId(id: Int) = dataStore.edit { it[LAST_STATION_ID] = id }
override fun getSleepTimerMinutes(): Flow<Int> = dataStore.data.map { it[SLEEP_TIMER] ?: 30 }
override suspend fun setSleepTimerMinutes(minutes: Int) = dataStore.edit { it[SLEEP_TIMER] = minutes }
override fun getEnabledDeeplinkServices(): Flow<Set<String>> = dataStore.data.map {
it[ENABLED_SERVICES] ?: setOf("yandex", "vk", "spotify", "apple", "youtube")
}
override suspend fun setEnabledDeeplinkServices(serviceIds: Set<String>) =
dataStore.edit { it[ENABLED_SERVICES] = serviceIds }
override fun getEqualizerPreset(): Flow<String> = dataStore.data.map { it[EQUALIZER_PRESET] ?: "Flat" }
override suspend fun setEqualizerPreset(preset: String) = dataStore.edit { it[EQUALIZER_PRESET] = preset }
override fun isRecordingEnabled(): Flow<Boolean> = dataStore.data.map { it[RECORDING_ENABLED] ?: false }
override suspend fun setRecordingEnabled(enabled: Boolean) = dataStore.edit { it[RECORDING_ENABLED] = enabled }
}

View File

@@ -0,0 +1,62 @@
package com.radiola.data.repository
import com.radiola.data.local.AppDatabase
import com.radiola.data.local.entity.StationEntity
import com.radiola.data.remote.RecordApi
import com.radiola.data.remote.ApiMapper.toDomain
import com.radiola.domain.model.Station
import com.radiola.domain.repository.StationRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
class StationRepositoryImpl @Inject constructor(
private val api: RecordApi,
private val db: AppDatabase
) : StationRepository {
override fun getStations(): Flow<List<Station>> {
return db.stationDao().getAll().map { entities ->
entities.map { it.toDomain() }
}
}
override suspend fun refreshStations(): Result<Unit> {
return try {
val response = api.getStations()
val entities = response.result.mapIndexed { index, dto ->
val domain = dto.toDomain()
StationEntity(
id = domain.id,
name = domain.name,
prefix = domain.prefix,
streamUrl = domain.streamUrl,
coverUrl = domain.coverUrl,
genre = domain.genre,
tags = domain.tags.joinToString(","),
sortOrder = index,
isFavorite = false
)
}
db.stationDao().insertAll(entities)
Result.success(Unit)
} catch (e: Exception) {
Result.failure(e)
}
}
override fun getStationById(id: Int): Flow<Station?> {
return db.stationDao().getById(id).map { it?.toDomain() }
}
private fun StationEntity.toDomain(): Station = Station(
id = id,
name = name,
prefix = prefix,
streamUrl = streamUrl,
coverUrl = coverUrl,
genre = genre,
tags = tags.split(",").filter { it.isNotBlank() },
sortOrder = sortOrder
)
}

View File

@@ -0,0 +1,47 @@
package com.radiola.data.repository
import com.radiola.data.local.AppDatabase
import com.radiola.data.local.entity.TrackHistoryEntity
import com.radiola.domain.model.Track
import com.radiola.domain.repository.TrackHistoryRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
class TrackHistoryRepositoryImpl @Inject constructor(
private val db: AppDatabase
) : TrackHistoryRepository {
override fun getHistory(): Flow<List<Track>> {
return db.trackHistoryDao().getAll().map { list ->
list.map { it.toDomain() }
}
}
override suspend fun addTrack(track: Track) {
val entity = TrackHistoryEntity(
artist = track.artist,
song = track.song,
stationName = track.stationName,
coverUrl = track.coverUrl,
timestamp = System.currentTimeMillis()
)
db.trackHistoryDao().insert(entity)
db.trackHistoryDao().cleanupOld()
}
override suspend fun removeTrack(track: Track) {
// Requires lookup by composite key; simplified for now
}
override suspend fun searchHistory(query: String): List<Track> {
return db.trackHistoryDao().search(query).map { it.toDomain() }
}
private fun TrackHistoryEntity.toDomain(): Track = Track(
artist = artist,
song = song,
coverUrl = coverUrl,
stationName = stationName
)
}