funkwhale-app-android/app/src/main/java/audio/funkwhale/ffa/repositories/Repository.kt

91 lines
2.4 KiB
Kotlin
Raw Normal View History

package audio.funkwhale.ffa.repositories
2019-08-19 16:50:33 +02:00
import android.content.Context
import audio.funkwhale.ffa.model.CacheItem
2021-09-09 09:56:15 +02:00
import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.utils.FFACache
import kotlinx.coroutines.CoroutineScope
2019-08-19 16:50:33 +02:00
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Job
2021-09-09 09:56:15 +02:00
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
2019-08-19 16:50:33 +02:00
import java.io.BufferedReader
import kotlin.math.ceil
2019-08-19 16:50:33 +02:00
interface Upstream<D> {
2019-10-31 16:17:37 +01:00
fun fetch(size: Int = 0): Flow<Repository.Response<D>>
2019-08-19 16:50:33 +02:00
}
abstract class Repository<D : Any, C : CacheItem<D>> {
protected val scope: CoroutineScope = CoroutineScope(Job() + IO)
2019-08-19 16:50:33 +02:00
enum class Origin(val origin: Int) {
Cache(0b01),
Network(0b10)
}
data class Response<D>(val origin: Origin, val data: List<D>, val page: Int, val hasMore: Boolean)
2019-08-19 16:50:33 +02:00
abstract val context: Context?
abstract val cacheId: String?
abstract val upstream: Upstream<D>
open fun cache(data: List<D>): C? = null
protected open fun uncache(json: String): C? = null
2019-08-19 16:50:33 +02:00
fun fetch(
upstreams: Int = Origin.Cache.origin and Origin.Network.origin,
size: Int = 0
): Flow<Response<D>> = flow {
2019-10-31 16:17:37 +01:00
if (Origin.Cache.origin and upstreams == upstreams) fromCache().collect { emit(it) }
if (Origin.Network.origin and upstreams == upstreams) fromNetwork(size).collect { emit(it) }
2019-08-19 16:50:33 +02:00
}
2019-10-31 16:17:37 +01:00
private fun fromCache() = flow {
cacheId?.let { cacheId ->
FFACache.getLine(context, cacheId)?.let { line ->
uncache(line)?.let { cache ->
return@flow emit(
Response(
Origin.Cache,
cache.data,
ceil(cache.data.size / AppContext.PAGE_SIZE.toDouble()).toInt(),
false
)
)
2019-08-19 16:50:33 +02:00
}
}
return@flow emit(Response(Origin.Cache, listOf(), 1, false))
2019-08-19 16:50:33 +02:00
}
2019-10-31 16:17:37 +01:00
}.flowOn(IO)
2019-08-19 16:50:33 +02:00
2021-09-09 09:56:15 +02:00
private fun fromNetwork(size: Int): Flow<Response<D>> = flow {
2019-10-31 16:17:37 +01:00
upstream
.fetch(size)
.map { response ->
Response(
Origin.Network,
onDataFetched(response.data),
response.page,
response.hasMore
)
}
.collect { response ->
emit(
Response(
Origin.Network,
response.data,
response.page,
response.hasMore
)
)
}
2019-08-19 16:50:33 +02:00
}
protected open fun onDataFetched(data: List<D>) = data
}