Skip to content

Commit

Permalink
change how repeated requests work and added fallback client
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed Apr 15, 2024
1 parent e7ca488 commit 8d7ca78
Show file tree
Hide file tree
Showing 17 changed files with 296 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import dev.datlag.aniflow.anilist.model.Medium
import dev.datlag.aniflow.anilist.type.AiringSort
import dev.datlag.aniflow.firebase.FirebaseFactory
import dev.datlag.aniflow.model.CatchResult
import dev.datlag.aniflow.model.mapError
import dev.datlag.aniflow.model.saveFirstOrNull
import dev.datlag.tooling.async.suspendCatching
import dev.datlag.tooling.safeSubList
import kotlinx.coroutines.ExperimentalCoroutinesApi
Expand All @@ -19,6 +21,7 @@ import kotlin.time.Duration.Companion.hours
@OptIn(ExperimentalCoroutinesApi::class)
class AiringTodayStateMachine(
private val client: ApolloClient,
private val fallbackClient: ApolloClient,
private val crashlytics: FirebaseFactory.Crashlytics?
) : FlowReduxStateMachine<AiringTodayStateMachine.State, AiringTodayStateMachine.Action>(
initialState = currentState
Expand All @@ -35,8 +38,14 @@ class AiringTodayStateMachine(
return@onEnter state.override { State.Success(query, it) }
}

val response = CatchResult.result {
client.query(state.snapshot.query).execute().dataOrThrow()
val response = CatchResult.repeat(times = 2) {
val query = client.query(state.snapshot.query)

query.execute().data ?: query.toFlow().saveFirstOrNull()?.dataOrThrow()
}.mapError {
val query = fallbackClient.query(state.snapshot.query)

query.execute().data ?: query.toFlow().saveFirstOrNull()?.dataOrThrow()
}.mapSuccess<State> {
val wantedContent = if (!state.snapshot.adultContent) {
val content = it.Page?.airingSchedulesFilterNotNull() ?: emptyList()
Expand Down Expand Up @@ -68,15 +77,7 @@ class AiringTodayStateMachine(
response.asSuccess {
crashlytics?.log(it)

if (retry <= 3) {
State.Loading(
query,
adultContent,
retry + 1
)
} else {
State.Error(query, adultContent)
}
State.Error(query, adultContent)
}
}
}
Expand Down Expand Up @@ -104,8 +105,7 @@ class AiringTodayStateMachine(
sealed interface State {
data class Loading(
internal val query: AiringQuery,
val adultContent: Boolean = false,
internal val retry: Int = 0
val adultContent: Boolean = false
) : State {
constructor(
page: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ import com.freeletics.flowredux.dsl.FlowReduxStateMachine
import dev.datlag.aniflow.anilist.model.Medium
import dev.datlag.aniflow.firebase.FirebaseFactory
import dev.datlag.aniflow.model.CatchResult
import dev.datlag.aniflow.model.mapError
import dev.datlag.aniflow.model.saveFirstOrNull
import dev.datlag.tooling.async.suspendCatching
import kotlinx.coroutines.ExperimentalCoroutinesApi

@OptIn(ExperimentalCoroutinesApi::class)
class MediumStateMachine(
private val client: ApolloClient,
private val fallbackClient: ApolloClient,
private val crashlytics: FirebaseFactory.Crashlytics?,
private val id: Int
) : FlowReduxStateMachine<MediumStateMachine.State, MediumStateMachine.Action>(
Expand All @@ -28,8 +31,14 @@ class MediumStateMachine(
currentState = it
}
onEnter { state ->
val response = CatchResult.result {
client.query(state.snapshot.query).execute().dataOrThrow()
val response = CatchResult.repeat(times = 2) {
val query = client.query(state.snapshot.query)

query.execute().data ?: query.toFlow().saveFirstOrNull()?.dataOrThrow()
}.mapError {
val query = fallbackClient.query(state.snapshot.query)

query.execute().data ?: query.toFlow().saveFirstOrNull()?.dataOrThrow()
}.mapSuccess<State> {
it.Media?.let { data ->
State.Success(state.snapshot.query, Medium.Full(data))
Expand All @@ -45,11 +54,7 @@ class MediumStateMachine(
if (cached != null) {
State.Success(query, cached)
} else {
if (retry <= 3) {
State.Loading(query, retry + 1)
} else {
State.Error(query)
}
State.Error(query)
}
}
}
Expand All @@ -76,8 +81,7 @@ class MediumStateMachine(

sealed interface State {
data class Loading(
internal val query: MediumQuery,
internal val retry: Int = 0
internal val query: MediumQuery
) : State {
constructor(id: Int) : this(
MediumQuery(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ import dev.datlag.aniflow.anilist.state.SeasonAction
import dev.datlag.aniflow.anilist.state.SeasonState
import dev.datlag.aniflow.firebase.FirebaseFactory
import dev.datlag.aniflow.model.CatchResult
import dev.datlag.aniflow.model.mapError
import dev.datlag.aniflow.model.saveFirstOrNull
import dev.datlag.tooling.async.suspendCatching
import kotlinx.coroutines.ExperimentalCoroutinesApi

@OptIn(ExperimentalCoroutinesApi::class)
class PopularNextSeasonStateMachine(
private val client: ApolloClient,
private val fallbackClient: ApolloClient,
private val crashlytics: FirebaseFactory.Crashlytics?
) : FlowReduxStateMachine<SeasonState, SeasonAction>(
initialState = currentState
Expand All @@ -28,8 +31,14 @@ class PopularNextSeasonStateMachine(
return@onEnter state.override { SeasonState.Success(query, it) }
}

val response = CatchResult.result {
client.query(state.snapshot.query).execute().dataOrThrow()
val response = CatchResult.repeat(times = 2) {
val query = client.query(state.snapshot.query)

query.execute().data ?: query.toFlow().saveFirstOrNull()?.dataOrThrow()
}.mapError {
val query = fallbackClient.query(state.snapshot.query)

query.execute().data ?: query.toFlow().saveFirstOrNull()?.dataOrThrow()
}.mapSuccess<SeasonState> {
SeasonState.Success(state.snapshot.query, it)
}
Expand All @@ -38,11 +47,7 @@ class PopularNextSeasonStateMachine(
response.asSuccess {
crashlytics?.log(it)

if (state.snapshot.retry <= 3) {
SeasonState.Loading(state.snapshot.query, state.snapshot.retry + 1)
} else {
SeasonState.Error(query)
}
SeasonState.Error(query)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import dev.datlag.aniflow.anilist.type.MediaSort
import dev.datlag.aniflow.anilist.type.MediaType
import dev.datlag.aniflow.firebase.FirebaseFactory
import dev.datlag.aniflow.model.CatchResult
import dev.datlag.aniflow.model.mapError
import dev.datlag.aniflow.model.saveFirstOrNull
import dev.datlag.tooling.async.suspendCatching
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.datetime.Clock
Expand All @@ -23,6 +25,7 @@ import kotlinx.datetime.toLocalDateTime
@OptIn(ExperimentalCoroutinesApi::class)
class PopularSeasonStateMachine(
private val client: ApolloClient,
private val fallbackClient: ApolloClient,
private val crashlytics: FirebaseFactory.Crashlytics?
) : FlowReduxStateMachine<SeasonState, SeasonAction>(
initialState = currentState
Expand All @@ -39,8 +42,14 @@ class PopularSeasonStateMachine(
return@onEnter state.override { SeasonState.Success(query, it) }
}

val response = CatchResult.result {
client.query(state.snapshot.query).execute().dataOrThrow()
val response = CatchResult.repeat(times = 2) {
val query = client.query(state.snapshot.query)

query.execute().data ?: query.toFlow().saveFirstOrNull()?.dataOrThrow()
}.mapError {
val query = fallbackClient.query(state.snapshot.query)

query.execute().data ?: query.toFlow().saveFirstOrNull()?.dataOrThrow()
}.mapSuccess<SeasonState> {
SeasonState.Success(state.snapshot.query, it)
}
Expand All @@ -49,11 +58,7 @@ class PopularSeasonStateMachine(
response.asSuccess {
crashlytics?.log(it)

if (retry <= 3) {
SeasonState.Loading(query, retry + 1)
} else {
SeasonState.Error(query)
}
SeasonState.Error(query)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import com.freeletics.flowredux.dsl.FlowReduxStateMachine
import dev.datlag.aniflow.anilist.type.MediaSort
import dev.datlag.aniflow.anilist.type.MediaType
import dev.datlag.aniflow.firebase.FirebaseFactory
import dev.datlag.aniflow.model.CatchResult
import dev.datlag.aniflow.model.*
import dev.datlag.tooling.async.suspendCatching
import kotlinx.coroutines.ExperimentalCoroutinesApi

@OptIn(ExperimentalCoroutinesApi::class, ApolloExperimental::class)
class TrendingAnimeStateMachine(
private val client: ApolloClient,
private val fallbackClient: ApolloClient,
private val crashlytics: FirebaseFactory.Crashlytics?
) : FlowReduxStateMachine<TrendingAnimeStateMachine.State, TrendingAnimeStateMachine.Action>(
initialState = currentState
Expand All @@ -31,8 +32,14 @@ class TrendingAnimeStateMachine(
return@onEnter state.override { State.Success(query, it) }
}

val response = CatchResult.result {
client.query(state.snapshot.query).execute().dataOrThrow()
val response = CatchResult.repeat(2) {
val query = client.query(state.snapshot.query)

query.execute().data ?: query.toFlow().saveFirstOrNull()?.dataOrThrow()
}.mapError {
val query = fallbackClient.query(state.snapshot.query)

query.execute().data ?: query.toFlow().saveFirstOrNull()?.dataOrThrow()
}.mapSuccess<State> {
State.Success(state.snapshot.query, it)
}
Expand All @@ -41,11 +48,7 @@ class TrendingAnimeStateMachine(
response.asSuccess {
crashlytics?.log(it)

if (retry <= 3) {
State.Loading(query, retry + 1)
} else {
State.Error(query)
}
State.Error(query)
}
}
}
Expand Down Expand Up @@ -73,8 +76,7 @@ class TrendingAnimeStateMachine(

sealed interface State {
data class Loading(
internal val query: TrendingQuery,
internal val retry: Int = 0
internal val query: TrendingQuery
) : State {
constructor(
page: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ import kotlinx.datetime.Instant

sealed interface SeasonState {
data class Loading(
internal val query: SeasonQuery,
internal val retry: Int = 0
internal val query: SeasonQuery
) : SeasonState {
constructor(
page: Int,
Expand Down
14 changes: 13 additions & 1 deletion composeApp/src/androidMain/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
Expand Down Expand Up @@ -46,6 +47,17 @@
</intent-filter>
</activity>

<!-- Trigger Google Play services to install the backported photo picker module. -->
<service android:name="com.google.android.gms.metadata.ModuleDependencies"
android:enabled="false"
android:exported="false"
tools:ignore="MissingClass">
<intent-filter>
<action android:name="com.google.android.gms.metadata.MODULE_DEPENDENCIES" />
</intent-filter>
<meta-data android:name="photopicker_activity:0:required" android:value="" />
</service>

<meta-data
android:name="instantapps.clients.allowed"
android:value="true"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.calculateEndPadding
import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.geometry.Offset
Expand Down Expand Up @@ -146,3 +146,26 @@ fun Modifier.shimmer(shape: Shape = RectangleShape): Modifier = composed {
fun shimmerPainter(): BrushPainter {
return BrushPainter(shimmerBrush())
}


@Composable
fun LazyListState.isScrollingUp(): Boolean {
var previousIndex by remember(this) {
mutableStateOf(firstVisibleItemIndex)
}
var previousScrollOffset by remember(this) {
mutableStateOf(firstVisibleItemScrollOffset)
}
return remember(this) {
derivedStateOf {
if (previousIndex != firstVisibleItemIndex) {
previousIndex > firstVisibleItemIndex
} else {
previousScrollOffset >= firstVisibleItemScrollOffset
}.also {
previousIndex = firstVisibleItemIndex
previousScrollOffset = firstVisibleItemScrollOffset
}
}
}.value
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,27 +85,37 @@ data object NetworkModule {
})
.build()
}
bindSingleton<ApolloClient>(Constants.AniList.FALLBACK_APOLLO_CLIENT) {
ApolloClient.Builder()
.dispatcher(ioDispatcher())
.serverUrl(Constants.AniList.SERVER_URL)
.build()
}
bindProvider<TrendingAnimeStateMachine> {
TrendingAnimeStateMachine(
client = instance(Constants.AniList.APOLLO_CLIENT),
fallbackClient = instance(Constants.AniList.FALLBACK_APOLLO_CLIENT),
crashlytics = nullableFirebaseInstance()?.crashlytics
)
}
bindProvider<AiringTodayStateMachine> {
AiringTodayStateMachine(
client = instance(Constants.AniList.APOLLO_CLIENT),
fallbackClient = instance(Constants.AniList.FALLBACK_APOLLO_CLIENT),
crashlytics = nullableFirebaseInstance()?.crashlytics
)
}
bindProvider<PopularSeasonStateMachine> {
PopularSeasonStateMachine(
client = instance(Constants.AniList.APOLLO_CLIENT),
fallbackClient = instance(Constants.AniList.FALLBACK_APOLLO_CLIENT),
crashlytics = nullableFirebaseInstance()?.crashlytics
)
}
bindProvider<PopularNextSeasonStateMachine> {
PopularNextSeasonStateMachine(
client = instance(Constants.AniList.APOLLO_CLIENT),
fallbackClient = instance(Constants.AniList.FALLBACK_APOLLO_CLIENT),
crashlytics = nullableFirebaseInstance()?.crashlytics
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ data object Constants {
data object AniList {
const val SERVER_URL = "https://graphql.anilist.co/"
const val APOLLO_CLIENT = "AniListApolloClient"
const val FALLBACK_APOLLO_CLIENT = "FallbackAniListApolloClient"

data object Auth {
const val BASE_URL = "https://anilist.co/api/v2/oauth/"
Expand Down
Loading

0 comments on commit 8d7ca78

Please sign in to comment.