mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-09 16:11:20 +02:00
Add setting to toggle automatic sign in (#538)
## Description The major user facing change in this PR is adding back the setting to toggle automatic sign in on or off. This controls whether to restore the app to where you left off or go the user selection page. If enabled: re-opening the app will restore the previous user's session If disabled: re-opening the app will always start with the user selection page for the most recent server, or if there isn't a recent server, the server selection page This also separate this setting from the PIN protection settings in previous PRs. ### Dev changes This PR refactors the "setup" UI (server & user selection) to be separate from the "app" UI (the actually app content). There is now a `NavDisplay` for the setup flow which ends with displaying the `ApplicationContent`'s `NavDisplay`. Most of the logic is moved out of Compose code and into a `ViewModel`. This means to switch users/server, the `SetupNavigationManager` must be used instead of `NavigationManager`. ### Related issues Closes #396 Fixes #376
This commit is contained in:
parent
20fe5e2626
commit
eb4e9b93be
14 changed files with 302 additions and 198 deletions
|
|
@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.saveable.rememberSerializable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
|
|
@ -24,8 +25,12 @@ import androidx.lifecycle.ViewModel
|
|||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
|
||||
import androidx.navigation3.runtime.NavBackStack
|
||||
import androidx.navigation3.runtime.NavEntry
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
|
||||
import androidx.navigation3.runtime.serialization.NavBackStackSerializer
|
||||
import androidx.navigation3.runtime.serialization.NavKeySerializer
|
||||
import androidx.navigation3.ui.NavDisplay
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import coil3.compose.AsyncImage
|
||||
|
|
@ -62,13 +67,22 @@ class ApplicationContentViewModel
|
|||
*/
|
||||
@Composable
|
||||
fun ApplicationContent(
|
||||
server: JellyfinServer?,
|
||||
user: JellyfinUser?,
|
||||
server: JellyfinServer,
|
||||
user: JellyfinUser,
|
||||
navigationManager: NavigationManager,
|
||||
preferences: UserPreferences,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: ApplicationContentViewModel = hiltViewModel(),
|
||||
) {
|
||||
val backStack: MutableList<NavKey> =
|
||||
rememberSerializable(
|
||||
server,
|
||||
user,
|
||||
serializer = NavBackStackSerializer(elementSerializer = NavKeySerializer()),
|
||||
) {
|
||||
NavBackStack(Destination.Home())
|
||||
}
|
||||
navigationManager.backStack = backStack
|
||||
val backdrop by viewModel.backdropService.backdropFlow.collectAsStateWithLifecycle()
|
||||
val backdropStyle = preferences.appPreferences.interfacePreferences.backdropStyle
|
||||
Box(
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import androidx.navigation3.runtime.NavKey
|
|||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.data.model.GetItemsFilter
|
||||
import com.github.damontecres.wholphin.data.model.ItemPlayback
|
||||
import com.github.damontecres.wholphin.data.model.JellyfinServer
|
||||
import com.github.damontecres.wholphin.ui.data.SortAndDirection
|
||||
import com.github.damontecres.wholphin.ui.detail.series.SeasonEpisode
|
||||
import com.github.damontecres.wholphin.ui.detail.series.SeasonEpisodeIds
|
||||
|
|
@ -28,14 +27,6 @@ import java.util.UUID
|
|||
sealed class Destination(
|
||||
val fullScreen: Boolean = false,
|
||||
) : NavKey {
|
||||
@Serializable
|
||||
data object ServerList : Destination(true)
|
||||
|
||||
@Serializable
|
||||
data class UserList(
|
||||
val server: JellyfinServer,
|
||||
) : Destination(true)
|
||||
|
||||
@Serializable
|
||||
data class Home(
|
||||
val id: Long = 0L,
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@ import com.github.damontecres.wholphin.ui.main.SearchPage
|
|||
import com.github.damontecres.wholphin.ui.playback.PlaybackPage
|
||||
import com.github.damontecres.wholphin.ui.preferences.PreferencesPage
|
||||
import com.github.damontecres.wholphin.ui.setup.InstallUpdatePage
|
||||
import com.github.damontecres.wholphin.ui.setup.SwitchServerContent
|
||||
import com.github.damontecres.wholphin.ui.setup.SwitchUserContent
|
||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||
import org.jellyfin.sdk.model.api.CollectionType
|
||||
import timber.log.Timber
|
||||
|
|
@ -66,14 +64,6 @@ fun DestinationContent(
|
|||
)
|
||||
}
|
||||
|
||||
Destination.ServerList -> {
|
||||
SwitchServerContent(modifier)
|
||||
}
|
||||
|
||||
is Destination.UserList -> {
|
||||
SwitchUserContent(destination.server, modifier)
|
||||
}
|
||||
|
||||
is Destination.Settings -> {
|
||||
PreferencesPage(
|
||||
preferences.appPreferences,
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ import com.github.damontecres.wholphin.preferences.AppThemeColors
|
|||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.services.BackdropService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.services.SetupDestination
|
||||
import com.github.damontecres.wholphin.services.SetupNavigationManager
|
||||
import com.github.damontecres.wholphin.ui.FontAwesome
|
||||
import com.github.damontecres.wholphin.ui.components.TimeDisplay
|
||||
import com.github.damontecres.wholphin.ui.ifElse
|
||||
|
|
@ -106,6 +108,7 @@ class NavDrawerViewModel
|
|||
constructor(
|
||||
private val navDrawerItemRepository: NavDrawerItemRepository,
|
||||
val navigationManager: NavigationManager,
|
||||
val setupNavigationManager: SetupNavigationManager,
|
||||
val backdropService: BackdropService,
|
||||
) : ViewModel() {
|
||||
private var all: List<NavDrawerItem>? = null
|
||||
|
|
@ -361,10 +364,8 @@ fun NavDrawer(
|
|||
drawerOpen = drawerState.isOpen,
|
||||
interactionSource = interactionSource,
|
||||
onClick = {
|
||||
viewModel.navigationManager.navigateToFromDrawer(
|
||||
Destination.UserList(
|
||||
server,
|
||||
),
|
||||
viewModel.setupNavigationManager.navigateTo(
|
||||
SetupDestination.UserList(server),
|
||||
)
|
||||
},
|
||||
modifier = Modifier.padding(start = drawerPadding),
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ import com.github.damontecres.wholphin.R
|
|||
import com.github.damontecres.wholphin.data.JellyfinServerDao
|
||||
import com.github.damontecres.wholphin.data.ServerRepository
|
||||
import com.github.damontecres.wholphin.data.model.JellyfinServer
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.services.SetupDestination
|
||||
import com.github.damontecres.wholphin.services.SetupNavigationManager
|
||||
import com.github.damontecres.wholphin.ui.launchIO
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
import com.github.damontecres.wholphin.ui.setValueOnMain
|
||||
import com.github.damontecres.wholphin.ui.showToast
|
||||
import com.github.damontecres.wholphin.util.LoadingState
|
||||
|
|
@ -41,7 +41,7 @@ class SwitchServerViewModel
|
|||
val jellyfin: Jellyfin,
|
||||
val serverRepository: ServerRepository,
|
||||
val serverDao: JellyfinServerDao,
|
||||
val navigationManager: NavigationManager,
|
||||
val navigationManager: SetupNavigationManager,
|
||||
) : ViewModel() {
|
||||
val servers = MutableLiveData<List<JellyfinServer>>(listOf())
|
||||
val serverStatus = MutableLiveData<Map<UUID, ServerConnectionStatus>>(mapOf())
|
||||
|
|
@ -156,7 +156,7 @@ class SwitchServerViewModel
|
|||
)
|
||||
serverRepository.addAndChangeServer(updatedServer)
|
||||
withContext(Dispatchers.Main) {
|
||||
navigationManager.navigateTo(Destination.UserList(server))
|
||||
navigationManager.navigateTo(SetupDestination.UserList(updatedServer))
|
||||
}
|
||||
} else if (result is ServerConnectionStatus.Error) {
|
||||
showToast(context, "Error connecting: $${result.message}")
|
||||
|
|
@ -201,7 +201,7 @@ class SwitchServerViewModel
|
|||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
addServerState.value = LoadingState.Success
|
||||
navigationManager.navigateTo(Destination.UserList(server))
|
||||
navigationManager.navigateTo(SetupDestination.UserList(server))
|
||||
}
|
||||
} else {
|
||||
withContext(Dispatchers.Main) {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import androidx.tv.material3.Text
|
|||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.model.JellyfinServer
|
||||
import com.github.damontecres.wholphin.data.model.JellyfinUser
|
||||
import com.github.damontecres.wholphin.services.SetupDestination
|
||||
import com.github.damontecres.wholphin.ui.components.BasicDialog
|
||||
import com.github.damontecres.wholphin.ui.components.CircularProgress
|
||||
import com.github.damontecres.wholphin.ui.components.EditTextBox
|
||||
|
|
@ -130,7 +131,9 @@ fun SwitchUserContent(
|
|||
viewModel.removeUser(user)
|
||||
},
|
||||
onSwitchServer = {
|
||||
viewModel.navigationManager.navigateTo(Destination.ServerList)
|
||||
viewModel.setupNavigationManager.navigateTo(
|
||||
SetupDestination.ServerList,
|
||||
)
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import com.github.damontecres.wholphin.data.model.JellyfinServer
|
|||
import com.github.damontecres.wholphin.data.model.JellyfinUser
|
||||
import com.github.damontecres.wholphin.services.ImageUrlService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.services.SetupDestination
|
||||
import com.github.damontecres.wholphin.services.SetupNavigationManager
|
||||
import com.github.damontecres.wholphin.ui.launchIO
|
||||
import com.github.damontecres.wholphin.ui.setValueOnMain
|
||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||
|
|
@ -43,6 +45,7 @@ class SwitchUserViewModel
|
|||
val serverRepository: ServerRepository,
|
||||
val serverDao: JellyfinServerDao,
|
||||
val navigationManager: NavigationManager,
|
||||
val setupNavigationManager: SetupNavigationManager,
|
||||
val imageUrlService: ImageUrlService,
|
||||
@Assisted val server: JellyfinServer,
|
||||
) : ViewModel() {
|
||||
|
|
@ -120,9 +123,11 @@ class SwitchUserViewModel
|
|||
fun switchUser(user: JellyfinUser) {
|
||||
viewModelScope.launchIO {
|
||||
try {
|
||||
serverRepository.changeUser(server, user)
|
||||
withContext(Dispatchers.Main) {
|
||||
navigationManager.goToHome()
|
||||
val current = serverRepository.changeUser(server, user)
|
||||
if (current != null) {
|
||||
withContext(Dispatchers.Main) {
|
||||
setupNavigationManager.navigateTo(SetupDestination.AppContent(current))
|
||||
}
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex, "Error switching user")
|
||||
|
|
@ -144,9 +149,11 @@ class SwitchUserViewModel
|
|||
username = username,
|
||||
password = password,
|
||||
)
|
||||
serverRepository.changeUser(server.url, authenticationResult)
|
||||
withContext(Dispatchers.Main) {
|
||||
navigationManager.goToHome()
|
||||
val current = serverRepository.changeUser(server.url, authenticationResult)
|
||||
if (current != null) {
|
||||
withContext(Dispatchers.Main) {
|
||||
setupNavigationManager.navigateTo(SetupDestination.AppContent(current))
|
||||
}
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex, "Error logging in user")
|
||||
|
|
@ -192,9 +199,13 @@ class SwitchUserViewModel
|
|||
val authenticationResult by api.userApi.authenticateWithQuickConnect(
|
||||
QuickConnectDto(secret = state.secret),
|
||||
)
|
||||
serverRepository.changeUser(server.url, authenticationResult)
|
||||
withContext(Dispatchers.Main) {
|
||||
navigationManager.goToHome()
|
||||
val current = serverRepository.changeUser(server.url, authenticationResult)
|
||||
if (current != null) {
|
||||
withContext(Dispatchers.Main) {
|
||||
setupNavigationManager.navigateTo(
|
||||
SetupDestination.AppContent(current),
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex, "Error during quick connect")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue