chore: Flow version of firstOrNull

This commit is contained in:
Ahmad Ansori Palembani 2024-12-04 12:05:19 +07:00
parent 19ea7cbebd
commit 106737371f
Signed by: null2264
GPG key ID: BA64F8B60AF3EFB6
6 changed files with 47 additions and 0 deletions

View file

@ -30,6 +30,9 @@ class MangaRepositoryImpl(private val handler: DatabaseHandler) : MangaRepositor
override fun getMangaListAsFlow(): Flow<List<Manga>> =
handler.subscribeToList { mangasQueries.findAll(Manga::mapper) }
override fun getMangaByUrlAndSourceAsFlow(url: String, source: Long): Flow<Manga?> =
handler.subscribeToFirstOrNull { mangasQueries.findByUrlAndSource(url, source, Manga::mapper) }
override suspend fun getLibraryManga(): List<LibraryManga> =
handler.awaitList { library_viewQueries.findAll(LibraryManga::mapper) }

View file

@ -9,6 +9,7 @@ import yokai.domain.manga.models.MangaUpdate
interface MangaRepository {
suspend fun getMangaList(): List<Manga>
suspend fun getMangaByUrlAndSource(url: String, source: Long): Manga?
fun getMangaByUrlAndSourceAsFlow(url: String, source: Long): Flow<Manga?>
suspend fun getMangaById(id: Long): Manga?
suspend fun getFavorites(): List<Manga>
suspend fun getReadNotFavorites(): List<Manga>

View file

@ -7,6 +7,7 @@ class GetManga (
) {
suspend fun awaitAll() = mangaRepository.getMangaList()
fun subscribeAll() = mangaRepository.getMangaListAsFlow()
fun subscribeByUrlAndSource(url: String, source: Long) = mangaRepository.getMangaByUrlAndSourceAsFlow(url, source)
suspend fun awaitByUrlAndSource(url: String, source: Long) = mangaRepository.getMangaByUrlAndSource(url, source)
suspend fun awaitById(id: Long) = mangaRepository.getMangaById(id)

View file

@ -12,6 +12,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.withContext
import yokai.data.util.executeAsFirstOrNull
import yokai.data.util.mapToFirstOrNull
class AndroidDatabaseHandler(
val db: Database,
@ -80,6 +81,10 @@ class AndroidDatabaseHandler(
return block(db).asFlow().mapToOneOrNull(queryDispatcher)
}
override fun <T : Any> subscribeToFirstOrNull(block: Database.() -> Query<T>): Flow<T?> {
return block(db).asFlow().mapToFirstOrNull(queryDispatcher)
}
/*
override fun <T : Any> subscribeToPagingSource(
countQuery: Database.() -> Query<Long>,

View file

@ -43,6 +43,8 @@ interface DatabaseHandler {
fun <T : Any> subscribeToOneOrNull(block: Database.() -> Query<T>): Flow<T?>
fun <T : Any> subscribeToFirstOrNull(block: Database.() -> Query<T>): Flow<T?>
/*
fun <T : Any> subscribeToPagingSource(
countQuery: Database.() -> Query<Long>,

View file

@ -1,7 +1,12 @@
package yokai.data.util
import app.cash.sqldelight.ExecutableQuery
import app.cash.sqldelight.Query
import app.cash.sqldelight.db.QueryResult
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
fun <T : Any> ExecutableQuery<T>.executeAsFirst(): T {
return executeAsFirstOrNull() ?: throw NullPointerException("ResultSet returned null for $this")
@ -11,3 +16,33 @@ fun <T : Any> ExecutableQuery<T>.executeAsFirstOrNull(): T? = execute { cursor -
if (!cursor.next().value) return@execute QueryResult.Value(null)
QueryResult.Value(mapper(cursor))
}.value
suspend fun <T : Any> ExecutableQuery<T>.awaitAsFirst(): T {
return awaitAsFirstOrNull()
?: throw NullPointerException("ResultSet returned null for $this")
}
suspend fun <T : Any> ExecutableQuery<T>.awaitAsFirstOrNull(): T? = execute { cursor ->
// If the cursor isn't async, we want to preserve the blocking semantics and execute it synchronously
when (val next = cursor.next()) {
is QueryResult.AsyncValue -> {
QueryResult.AsyncValue {
if (!next.await()) return@AsyncValue null
mapper(cursor)
}
}
is QueryResult.Value -> {
if (!next.value) return@execute QueryResult.Value(null)
QueryResult.Value(mapper(cursor))
}
}
}.await()
fun <T : Any> Flow<Query<T>>.mapToFirstOrNull(
context: CoroutineContext,
): Flow<T?> = map {
withContext(context) {
it.awaitAsFirstOrNull()
}
}