feat(data): add repository implementations
This commit is contained in:
@@ -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
|
||||
)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 }
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user