Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refresh #130

Closed
wants to merge 48 commits into from
Closed
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
53f9f27
Use `CacheFirst`
imashnake0 Mar 28, 2024
7f33fad
`CacheFirst` is the default
imashnake0 Mar 28, 2024
fa0cbca
Fix media selector animations
imashnake0 Mar 28, 2024
ee51ec3
Cleanup
imashnake0 Mar 28, 2024
51851cd
Revert "Cleanup"
imashnake0 Mar 28, 2024
1a3915b
Revert "Fix media selector animations"
imashnake0 Mar 28, 2024
2dd085d
Clear cache
imashnake0 Apr 7, 2024
2e297fc
Merge branch 'main' into use-cache
imashnake0 May 6, 2024
d03a029
Refresh once
imashnake0 May 13, 2024
23dad82
Refresh multiple times
imashnake0 May 13, 2024
fb52444
Cleanup
imashnake0 May 13, 2024
12b3a04
Use pull to refresh
imashnake0 May 13, 2024
4fc2022
Fix alignment
imashnake0 May 13, 2024
64e3e5e
Scale is true
imashnake0 May 13, 2024
66e6ff0
Attempt to use `MutableSharedFlow`
imashnake0 May 13, 2024
8b69611
Fix alignment
imashnake0 May 13, 2024
8dab951
Scale is true
imashnake0 May 13, 2024
01706f4
Created `Refreshing` state
imashnake0 Jun 8, 2024
bd8bc3b
Use `StateFlow` and `onEach`
imashnake0 Jun 8, 2024
5b70c64
Cleanup
imashnake0 Jun 8, 2024
23bd1a5
Detekt
imashnake0 Jun 8, 2024
548cf7e
Removed redundant `asSharedFlow()`
imashnake0 Jun 8, 2024
fa08512
`Refreshing` is like `Loading`
imashnake0 Jun 8, 2024
d385dfc
Added proper `loading` UI state
imashnake0 Jun 8, 2024
8c64006
Yoink
imashnake0 Jun 8, 2024
410df74
Cleanup
imashnake0 Jun 8, 2024
f33a15b
Show exclusively for refreshing
imashnake0 Jun 8, 2024
6e08041
Undo "Cleanup"
imashnake0 Jun 8, 2024
32a5c2c
Added delay
imashnake0 Jun 8, 2024
fd8a1ca
Oh
imashnake0 Jun 8, 2024
f39cb8b
Set `_useNetwork` to `false` finally
imashnake0 Jun 9, 2024
bd6ee33
Fixed order
imashnake0 Jun 9, 2024
78636e0
Reduced buffer
imashnake0 Jun 9, 2024
76b136b
Merge pull request #133 from imashnake0/mutable-shared-flow
imashnake0 Jun 9, 2024
e6324fa
Cleanup
imashnake0 Jun 9, 2024
54d5ba6
Re: Cleanup
imashnake0 Jun 9, 2024
5136064
Fix alignment
imashnake0 Jun 9, 2024
d6e4945
Moved `FlowExt`
imashnake0 Jun 9, 2024
53e93df
Created a reusable `RefreshableFlow`
imashnake0 Jun 9, 2024
b39ba18
Added Kdoc
imashnake0 Jun 9, 2024
93636a7
Added default params
imashnake0 Jun 9, 2024
55a629c
Made `HomeScreen` refreshable
imashnake0 Jun 9, 2024
49d487c
Removed default param
imashnake0 Jun 9, 2024
98ca868
Changed `useNetwork` to var
imashnake0 Jun 9, 2024
9d51e9e
Updated Kdoc
imashnake0 Jun 9, 2024
4a38975
Reorder params
imashnake0 Jun 9, 2024
4d16a75
Animate height of `AboutUser`
imashnake0 Jun 9, 2024
9daa812
Removed `coldToHot`
imashnake0 Jun 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package com.imashnake.animite.api.anilist

import com.apollographql.apollo3.ApolloClient
import com.apollographql.apollo3.api.Optional
import com.apollographql.apollo3.cache.normalized.FetchPolicy
import com.apollographql.apollo3.cache.normalized.fetchPolicy
import com.imashnake.animite.api.anilist.sanitize.media.Media
import com.imashnake.animite.api.anilist.type.MediaSeason
import com.imashnake.animite.api.anilist.type.MediaSort
Expand Down Expand Up @@ -42,7 +40,6 @@ class AnilistMediaRepository @Inject constructor(
seasonYear = Optional.presentIfNotNull(seasonYear)
)
)
.fetchPolicy(FetchPolicy.CacheAndNetwork)
.toFlow()
boswelja marked this conversation as resolved.
Show resolved Hide resolved
.asResult {
it.page!!.media.orEmpty().filterNotNull().map { query -> Media.Medium(query) }
Expand All @@ -57,7 +54,6 @@ class AnilistMediaRepository @Inject constructor(
type = Optional.presentIfNotNull(mediaType)
)
)
.fetchPolicy(FetchPolicy.CacheAndNetwork)
.toFlow()
.asResult { Media(it.media!!) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package com.imashnake.animite.api.anilist

import com.apollographql.apollo3.ApolloClient
import com.apollographql.apollo3.api.Optional
import com.apollographql.apollo3.cache.normalized.FetchPolicy
import com.apollographql.apollo3.cache.normalized.fetchPolicy
import com.imashnake.animite.api.anilist.sanitize.search.Search
import com.imashnake.animite.api.anilist.type.MediaType
import kotlinx.coroutines.flow.Flow
Expand Down Expand Up @@ -31,7 +29,6 @@ class AnilistSearchRepository @Inject constructor(
search = Optional.presentIfNotNull(search)
)
)
.fetchPolicy(FetchPolicy.CacheAndNetwork)
.toFlow()
.asResult { it.page!!.media.orEmpty().filterNotNull().map { query -> Search(query) } }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import javax.inject.Inject
class AnilistUserRepository @Inject constructor(
@AuthorizedClient private val apolloClient: ApolloClient
) {
fun fetchViewer(): Flow<Result<ViewerQuery.Viewer>> {
fun fetchViewer(refresh: Boolean): Flow<Result<ViewerQuery.Viewer>> {
return apolloClient
.query(ViewerQuery())
boswelja marked this conversation as resolved.
Show resolved Hide resolved
.fetchPolicy(FetchPolicy.CacheAndNetwork)
.fetchPolicy(if (refresh) FetchPolicy.NetworkFirst else FetchPolicy.CacheFirst)
.toFlow()
imashnake0 marked this conversation as resolved.
Show resolved Hide resolved
.asResult { it.viewer!! }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,17 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PrimaryTabRow
Expand All @@ -33,6 +41,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import coil.compose.AsyncImage
import com.boswelja.markdown.material3.MarkdownDocument
import com.boswelja.markdown.material3.m3TextStyles
import com.imashnake.animite.core.data.Resource
import com.imashnake.animite.core.extensions.animiteBlockQuoteStyle
import com.imashnake.animite.core.extensions.animiteCodeBlockStyle
import com.imashnake.animite.core.extensions.crossfadeModel
Expand All @@ -47,6 +56,7 @@ import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph
import com.imashnake.animite.core.R as coreR

@OptIn(ExperimentalMaterialApi::class)
@Suppress("LongMethod", "UNUSED_PARAMETER")
@Destination(
route = "user",
Expand All @@ -66,17 +76,25 @@ fun ProfileScreen(
expiresIn: Int? = null
) {
accessToken?.let { viewModel.setAccessToken(it) }
viewModel.refreshViewer(false)
imashnake0 marked this conversation as resolved.
Show resolved Hide resolved
val isLoggedIn by viewModel.isLoggedIn.collectAsState(initial = false)
val viewer by viewModel.viewer.collectAsState()

val pullRefreshState = rememberPullRefreshState(
refreshing = viewer is Resource.Loading,
onRefresh = { viewModel.refreshViewer(true) }
)

Box(
contentAlignment = Alignment.Center,
contentAlignment = Alignment.TopCenter,
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.background)
.pullRefresh(pullRefreshState)
.verticalScroll(rememberScrollState())
) {
when {
isLoggedIn -> viewer.data?.run {
isLoggedIn && viewer is Resource.Success -> viewer.data?.run {
BannerLayout(
banner = {
Box {
Expand Down Expand Up @@ -126,6 +144,15 @@ fun ProfileScreen(
}
else -> Login()
}

// TODO: Replace with custom indicator.
PullRefreshIndicator(
refreshing = viewer is Resource.Loading,
state = pullRefreshState,
modifier = Modifier.align(Alignment.TopCenter),
backgroundColor = MaterialTheme.colorScheme.background,
contentColor = MaterialTheme.colorScheme.primary
)
}
}

Expand Down Expand Up @@ -190,7 +217,8 @@ fun UserTabs(modifier: Modifier = Modifier) {
}
Box(
Modifier
.fillMaxSize()
.height(300.dp)
.fillMaxWidth()
.background(
Brush.verticalGradient(
listOf(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.imashnake.animite.profile

import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.imashnake.animite.api.anilist.AnilistUserRepository
Expand All @@ -8,27 +9,40 @@ import com.imashnake.animite.core.data.Resource
import com.imashnake.animite.core.data.Resource.Companion.asResource
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import javax.inject.Inject

@OptIn(ExperimentalCoroutinesApi::class)
@HiltViewModel
class ProfileViewModel @Inject constructor(
userRepository: AnilistUserRepository,
private val preferencesRepository: PreferencesRepository
private val userRepository: AnilistUserRepository,
private val preferencesRepository: PreferencesRepository,
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
private val refresh = savedStateHandle.getStateFlow(REFRESH, false)
boswelja marked this conversation as resolved.
Show resolved Hide resolved

val isLoggedIn = preferencesRepository
.accessToken
.map { !it.isNullOrEmpty() }

val viewer = userRepository
.fetchViewer()
.asResource()
val viewer = refresh
.flatMapLatest { userRepository.fetchViewer(it).asResource() }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(1000), Resource.loading())

fun setAccessToken(accessToken: String?) = viewModelScope.launch(Dispatchers.IO) {
preferencesRepository.setAccessToken(accessToken)
}

fun refreshViewer(refresh: Boolean) {
savedStateHandle[REFRESH] = refresh
}

companion object {
const val REFRESH = "refresh"
}
}
Loading