Don't flash previous app content when resuming app & auto sign-in is off (#585)

## Description
When the app is put into the background with auto sign-in disabled, it
will remove the current page and show a loading indicator. This way when
the app is resumed, the previous content won't flash on screen for a
split second.

The above should technically fix #584 on its own, but as additional safe
guide, this PR also makes sure the `ApiClient` is configured before
trying to create image URLs.

### Related issues
Fixes #584
This commit is contained in:
Ray 2025-12-27 15:13:45 -05:00 committed by GitHub
parent 494ff07b72
commit 639ce0de71
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 38 additions and 12 deletions

View file

@ -13,13 +13,16 @@ import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.datastore.core.DataStore import androidx.datastore.core.DataStore
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.compose.LifecycleStartEffect
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
@ -208,13 +211,35 @@ class MainActivity : AppCompatActivity() {
remember(appPreferences) { remember(appPreferences) {
UserPreferences(appPreferences) UserPreferences(appPreferences)
} }
ApplicationContent( var showContent by remember {
user = current.user, mutableStateOf(true)
server = current.server, }
navigationManager = navigationManager, if (!preferences.appPreferences.signInAutomatically) {
preferences = preferences, LifecycleStartEffect(Unit) {
modifier = Modifier.fillMaxSize(), onStopOrDispose {
) showContent = false
}
}
}
if (showContent) {
ApplicationContent(
user = current.user,
server = current.server,
navigationManager = navigationManager,
preferences = preferences,
modifier = Modifier.fillMaxSize(),
)
} else {
Box(
modifier = Modifier.size(200.dp),
contentAlignment = Alignment.Center,
) {
CircularProgressIndicator(
color = MaterialTheme.colorScheme.border,
modifier = Modifier.align(Alignment.Center),
)
}
}
} }
} }
} }

View file

@ -242,7 +242,6 @@ class ServerRepository
} }
suspend fun switchServerOrUser() { suspend fun switchServerOrUser() {
apiClient.update(baseUrl = null, accessToken = null)
userPreferencesDataStore.updateData { userPreferencesDataStore.updateData {
it it
.toBuilder() .toBuilder()

View file

@ -31,7 +31,7 @@ class ImageUrlService
imageType: ImageType, imageType: ImageType,
fillWidth: Int? = null, fillWidth: Int? = null,
fillHeight: Int? = null, fillHeight: Int? = null,
): String = ): String? =
when (imageType) { when (imageType) {
ImageType.BACKDROP, ImageType.BACKDROP,
ImageType.LOGO, ImageType.LOGO,
@ -124,8 +124,9 @@ class ImageUrlService
backgroundColor: String? = null, backgroundColor: String? = null,
foregroundLayer: String? = null, foregroundLayer: String? = null,
imageIndex: Int? = null, imageIndex: Int? = null,
): String = ): String? {
api.imageApi.getItemImageUrl( if (api.baseUrl.isNullOrBlank()) return null
return api.imageApi.getItemImageUrl(
itemId = itemId, itemId = itemId,
imageType = imageType, imageType = imageType,
maxWidth = maxWidth, maxWidth = maxWidth,
@ -144,6 +145,7 @@ class ImageUrlService
foregroundLayer = foregroundLayer, foregroundLayer = foregroundLayer,
imageIndex = imageIndex, imageIndex = imageIndex,
) )
}
fun getUserImageUrl(userId: UUID) = api.imageApi.getUserImageUrl(userId) fun getUserImageUrl(userId: UUID) = api.imageApi.getUserImageUrl(userId)

View file

@ -103,7 +103,7 @@ class GenreViewModel
loading.value = LoadingState.Success loading.value = LoadingState.Success
} }
// val excludeItemIds = mutableSetOf<UUID>() // val excludeItemIds = mutableSetOf<UUID>()
val genreToUrl = ConcurrentHashMap<UUID, String>() val genreToUrl = ConcurrentHashMap<UUID, String?>()
val semaphore = Semaphore(4) val semaphore = Semaphore(4)
genres genres
.map { genre -> .map { genre ->