Skip to content

Commit

Permalink
improve flow performance
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed May 10, 2024
1 parent 9f9f2e6 commit de0e775
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.apollographql.apollo3.ApolloClient
import com.apollographql.apollo3.api.Optional
import dev.datlag.aniflow.anilist.model.Medium
import dev.datlag.aniflow.anilist.type.AiringSort
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
import kotlinx.datetime.Clock
import kotlinx.serialization.Serializable
Expand All @@ -23,12 +24,16 @@ class AiringTodayRepository(
)
}.distinctUntilChanged()

private val airingPreFilter = query.transform {
return@transform emitAll(apolloClient.query(it.toGraphQL()).toFlow())
@OptIn(ExperimentalCoroutinesApi::class)
private val airingPreFilter = query.transformLatest {
return@transformLatest emitAll(apolloClient.query(it.toGraphQL()).toFlow())
}
private val fallbackPreFilter = query.transform {
return@transform emitAll(fallbackClient.query(it.toGraphQL()).toFlow())

@OptIn(ExperimentalCoroutinesApi::class)
private val fallbackPreFilter = query.transformLatest {
return@transformLatest emitAll(fallbackClient.query(it.toGraphQL()).toFlow())
}

private val fallbackQuery = combine(fallbackPreFilter, nsfw.distinctUntilChanged()) { q, n ->
val data = q.data
if (data == null) {
Expand All @@ -42,6 +47,7 @@ class AiringTodayRepository(
}
}.filterNotNull()

@OptIn(ExperimentalCoroutinesApi::class)
val airing = combine(airingPreFilter, nsfw.distinctUntilChanged()) { q, n ->
val data = q.data
if (data == null) {
Expand All @@ -53,8 +59,8 @@ class AiringTodayRepository(
} else {
State.fromGraphQL(data, n)
}
}.filterNotNull().transform {
return@transform if (it is State.Error) {
}.filterNotNull().transformLatest {
return@transformLatest if (it is State.Error) {
emitAll(fallbackQuery)
} else {
emit(it)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import dev.datlag.aniflow.anilist.state.CollectionState
import dev.datlag.aniflow.anilist.type.MediaSeason
import dev.datlag.aniflow.anilist.type.MediaSort
import dev.datlag.aniflow.anilist.type.MediaType
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
import kotlinx.datetime.Clock

Expand All @@ -17,6 +18,7 @@ class PopularNextSeasonRepository(
) {

private val page = MutableStateFlow(0)

private val query = combine(page, nsfw.distinctUntilChanged()) { p, n ->
val (season, year) = Clock.System.now().nextSeason

Expand All @@ -27,8 +29,10 @@ class PopularNextSeasonRepository(
year = year
)
}.distinctUntilChanged()
private val fallbackQuery = query.transform {
return@transform emitAll(fallbackClient.query(it.toGraphQL()).toFlow())

@OptIn(ExperimentalCoroutinesApi::class)
private val fallbackQuery = query.transformLatest {
return@transformLatest emitAll(fallbackClient.query(it.toGraphQL()).toFlow())
}.mapNotNull {
val data = it.data
if (data == null) {
Expand All @@ -42,8 +46,9 @@ class PopularNextSeasonRepository(
}
}

val popularNextSeason = query.transform {
return@transform emitAll(apolloClient.query(it.toGraphQL()).toFlow())
@OptIn(ExperimentalCoroutinesApi::class)
val popularNextSeason = query.transformLatest {
return@transformLatest emitAll(apolloClient.query(it.toGraphQL()).toFlow())
}.mapNotNull {
val data = it.data
if (data == null) {
Expand All @@ -55,8 +60,8 @@ class PopularNextSeasonRepository(
} else {
CollectionState.fromSeasonGraphQL(data)
}
}.transform {
return@transform if (it.isError) {
}.transformLatest {
return@transformLatest if (it.isError) {
emitAll(fallbackQuery)
} else {
emit(it)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.apollographql.apollo3.api.Optional
import dev.datlag.aniflow.anilist.state.CollectionState
import dev.datlag.aniflow.anilist.type.MediaSort
import dev.datlag.aniflow.anilist.type.MediaType
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*

class PopularSeasonRepository(
Expand All @@ -15,23 +16,28 @@ class PopularSeasonRepository(
) {

private val page = MutableStateFlow(0)
private val type = viewManga.distinctUntilChanged().map {

@OptIn(ExperimentalCoroutinesApi::class)
private val type = viewManga.distinctUntilChanged().mapLatest {
page.update { 0 }
if (it) {
MediaType.MANGA
} else {
MediaType.ANIME
}
}

private val query = combine(page, type, nsfw.distinctUntilChanged()) { p, t, n ->
Query(
page = p,
type = t,
nsfw = n
)
}.distinctUntilChanged()
private val fallbackQuery = query.transform {
return@transform emitAll(fallbackClient.query(it.toGraphQL()).toFlow())

@OptIn(ExperimentalCoroutinesApi::class)
private val fallbackQuery = query.transformLatest {
return@transformLatest emitAll(fallbackClient.query(it.toGraphQL()).toFlow())
}.mapNotNull {
val data = it.data
if (data == null) {
Expand All @@ -45,8 +51,9 @@ class PopularSeasonRepository(
}
}

val popularThisSeason = query.transform {
return@transform emitAll(apolloClient.query(it.toGraphQL()).toFlow())
@OptIn(ExperimentalCoroutinesApi::class)
val popularThisSeason = query.transformLatest {
return@transformLatest emitAll(apolloClient.query(it.toGraphQL()).toFlow())
}.mapNotNull {
val data = it.data
if (data == null) {
Expand All @@ -58,8 +65,8 @@ class PopularSeasonRepository(
} else {
CollectionState.fromSeasonGraphQL(data)
}
}.transform {
return@transform if (it.isError) {
}.transformLatest {
return@transformLatest if (it.isError) {
emitAll(fallbackQuery)
} else {
emit(it)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import dev.datlag.aniflow.anilist.model.Medium
import dev.datlag.aniflow.anilist.state.CollectionState
import dev.datlag.aniflow.anilist.type.MediaSort
import dev.datlag.aniflow.anilist.type.MediaType
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
import kotlinx.serialization.Serializable

Expand All @@ -17,23 +18,28 @@ class TrendingRepository(
) {

private val page = MutableStateFlow(0)
private val type = viewManga.distinctUntilChanged().map {

@OptIn(ExperimentalCoroutinesApi::class)
private val type = viewManga.distinctUntilChanged().mapLatest {
page.update { 0 }
if (it) {
MediaType.MANGA
} else {
MediaType.ANIME
}
}

private val query = combine(page, type, nsfw.distinctUntilChanged()) { p, t, n ->
Query(
page = p,
type = t,
nsfw = n
)
}.distinctUntilChanged()
private val fallbackQuery = query.transform {
return@transform emitAll(fallbackClient.query(it.toGraphQL()).toFlow())

@OptIn(ExperimentalCoroutinesApi::class)
private val fallbackQuery = query.transformLatest {
return@transformLatest emitAll(fallbackClient.query(it.toGraphQL()).toFlow())
}.mapNotNull {
val data = it.data
if (data == null) {
Expand All @@ -47,8 +53,9 @@ class TrendingRepository(
}
}

val trending = query.transform {
return@transform emitAll(apolloClient.query(it.toGraphQL()).toFlow())
@OptIn(ExperimentalCoroutinesApi::class)
val trending = query.transformLatest {
return@transformLatest emitAll(apolloClient.query(it.toGraphQL()).toFlow())
}.mapNotNull {
val data = it.data
if (data == null) {
Expand All @@ -60,8 +67,8 @@ class TrendingRepository(
} else {
CollectionState.fromTrendingGraphQL(data)
}
}.transform {
return@transform if (it.isError) {
}.transformLatest {
return@transformLatest if (it.isError) {
emitAll(fallbackQuery)
} else {
emit(it)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import dev.datlag.tooling.compose.withIOContext
import dev.datlag.tooling.compose.withMainContext
import io.github.aakira.napier.Napier
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking
Expand All @@ -43,8 +44,8 @@ class UserHelper(
val isLoggedIn: Flow<Boolean> = userSettings.isAniListLoggedIn.flowOn(ioDispatcher()).distinctUntilChanged()
val loginUrl: String = "https://anilist.co/api/v2/oauth/authorize?client_id=$clientId&response_type=token"

@OptIn(DelicateCoroutinesApi::class)
private val updatableUser = isLoggedIn.transform { loggedIn ->
@OptIn(DelicateCoroutinesApi::class, ExperimentalCoroutinesApi::class)
private val updatableUser = isLoggedIn.transformLatest { loggedIn ->
if (loggedIn) {
emitAll(
client.query(ViewerQuery()).fetchPolicy(FetchPolicy.NetworkFirst).toFlow().map {
Expand All @@ -59,7 +60,8 @@ class UserHelper(
initialValue = null
)

val user = updatableUser.map { user ->
@OptIn(ExperimentalCoroutinesApi::class)
val user = updatableUser.mapLatest { user ->
user?.also {
appSettings.setData(
adultContent = it.displayAdultContent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.MenuBook
import androidx.compose.material.icons.automirrored.rounded.MenuBook
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.PlayCircleFilled
import androidx.compose.material3.*
Expand Down Expand Up @@ -158,7 +159,7 @@ fun CollapsingToolbar(
enabled = !isManga
) {
Icon(
imageVector = Icons.AutoMirrored.Default.MenuBook,
imageVector = Icons.AutoMirrored.Rounded.MenuBook,
contentDescription = null,
tint = if (isManga) {
MaterialTheme.colorScheme.primary
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package dev.datlag.aniflow.ui.navigation.screen.nekos

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
import androidx.compose.foundation.lazy.staggeredgrid.items
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBackIos
import androidx.compose.material.icons.rounded.ArrowBackIos
import androidx.compose.material.icons.rounded.FilterList
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalUriHandler
Expand Down Expand Up @@ -142,8 +142,30 @@ fun NekosScreen(component: NekosComponent) {
val state by component.state.collectAsStateWithLifecycle(NekosRepository.State.None)

when (val current = state) {
is NekosRepository.State.None -> Text(text = "Loading")
is NekosRepository.State.Error -> Text(text = "Error")
is NekosRepository.State.None -> {
Box(
modifier = Modifier.fillMaxSize().padding(padding),
contentAlignment = Alignment.Center
) {
LinearProgressIndicator(
modifier = Modifier.fillMaxWidth(0.2F).clip(CircleShape)
)
}
}
is NekosRepository.State.Error -> {
Box(
modifier = Modifier.fillMaxSize().padding(padding),
contentAlignment = Alignment.Center
) {
Button(
onClick = {
component.back()
}
) {
Text(text = stringResource(SharedRes.strings.back))
}
}
}
is NekosRepository.State.Success -> {
val uriHandler = LocalUriHandler.current

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package dev.datlag.aniflow.nekos
import dev.datlag.aniflow.model.CatchResult
import dev.datlag.aniflow.nekos.model.ImagesResponse
import dev.datlag.aniflow.nekos.model.Rating
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
import kotlinx.serialization.Serializable

Expand All @@ -11,17 +12,16 @@ class NekosRepository(
private val nsfw: Flow<Boolean> = flowOf(false),
) {

private val offset = MutableStateFlow<Int?>(null)
val rating = MutableStateFlow<Rating>(Rating.Safe)

private val result = combine(offset, rating) { o, r ->
@OptIn(ExperimentalCoroutinesApi::class)
private val result = rating.mapLatest {
CatchResult.repeat(2) {
nekos.images(
rating = r.query,
offset = o,
rating = it.query
)
}
}.map {
}.mapLatest {
State.fromResponse(it.asNullableSuccess())
}
val response = combine(nsfw.distinctUntilChanged(), result, rating) { n, q, r ->
Expand All @@ -46,17 +46,8 @@ class NekosRepository(
}
}

fun offset(value: Int) {
offset.update { value }
}

fun rating(value: Rating) {
rating.update {
if (it != value) {
offset.update { null }
}
value
}
rating.update { value }
}

@Serializable
Expand Down
Loading

0 comments on commit de0e775

Please sign in to comment.