mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
Better restoration for auto sign in (#566)
## Description Improves how the app restores state when auto sign in is enabled. If auto sign in is enabled, the app will restore back to the last page. #538 altered the app start up logic. This caused the app to reset state more often when it goes into the background. ### Related issues Related to #552
This commit is contained in:
parent
bcc7e660ea
commit
b671e14826
6 changed files with 61 additions and 23 deletions
|
|
@ -32,7 +32,6 @@ import androidx.tv.material3.Surface
|
||||||
import com.github.damontecres.wholphin.data.ServerRepository
|
import com.github.damontecres.wholphin.data.ServerRepository
|
||||||
import com.github.damontecres.wholphin.preferences.AppPreference
|
import com.github.damontecres.wholphin.preferences.AppPreference
|
||||||
import com.github.damontecres.wholphin.preferences.AppPreferences
|
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.DefaultUserConfiguration
|
|
||||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||||
import com.github.damontecres.wholphin.services.AppUpgradeHandler
|
import com.github.damontecres.wholphin.services.AppUpgradeHandler
|
||||||
import com.github.damontecres.wholphin.services.BackdropService
|
import com.github.damontecres.wholphin.services.BackdropService
|
||||||
|
|
@ -102,7 +101,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
Timber.i("MainActivity.onCreate")
|
Timber.i("MainActivity.onCreate: savedInstanceState is null=${savedInstanceState == null}")
|
||||||
lifecycle.addObserver(playbackLifecycleObserver)
|
lifecycle.addObserver(playbackLifecycleObserver)
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
appUpgradeHandler.copySubfont(false)
|
appUpgradeHandler.copySubfont(false)
|
||||||
|
|
@ -209,12 +208,8 @@ class MainActivity : AppCompatActivity() {
|
||||||
appPreferences,
|
appPreferences,
|
||||||
)
|
)
|
||||||
val preferences =
|
val preferences =
|
||||||
remember(appPreferences, current) {
|
remember(appPreferences) {
|
||||||
UserPreferences(
|
UserPreferences(appPreferences)
|
||||||
appPreferences,
|
|
||||||
current.userDto.configuration
|
|
||||||
?: DefaultUserConfiguration,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
ApplicationContent(
|
ApplicationContent(
|
||||||
user = current.user,
|
user = current.user,
|
||||||
|
|
@ -238,6 +233,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
Timber.i("onResume")
|
||||||
lifecycleScope.launchIO {
|
lifecycleScope.launchIO {
|
||||||
appUpgradeHandler.run()
|
appUpgradeHandler.run()
|
||||||
}
|
}
|
||||||
|
|
@ -256,6 +252,36 @@ class MainActivity : AppCompatActivity() {
|
||||||
// serverRepository.closeSession()
|
// serverRepository.closeSession()
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// override fun onStop() {
|
||||||
|
// super.onStop()
|
||||||
|
// Timber.i("onStop")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun onPause() {
|
||||||
|
// super.onPause()
|
||||||
|
// Timber.i("onPause")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun onStart() {
|
||||||
|
// super.onStart()
|
||||||
|
// Timber.i("onStart")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
// super.onSaveInstanceState(outState)
|
||||||
|
// Timber.i("onSaveInstanceState")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||||
|
// super.onRestoreInstanceState(savedInstanceState)
|
||||||
|
// Timber.i("onRestoreInstanceState")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun onDestroy() {
|
||||||
|
// super.onDestroy()
|
||||||
|
// Timber.i("onDestroy")
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
|
|
|
||||||
|
|
@ -46,9 +46,11 @@ class ServerRepository
|
||||||
private var _current = EqualityMutableLiveData<CurrentUser?>(null)
|
private var _current = EqualityMutableLiveData<CurrentUser?>(null)
|
||||||
val current: LiveData<CurrentUser?> = _current
|
val current: LiveData<CurrentUser?> = _current
|
||||||
|
|
||||||
|
private var _currentUserDto = EqualityMutableLiveData<UserDto?>(null)
|
||||||
|
val currentUserDto: LiveData<UserDto?> = _currentUserDto
|
||||||
|
|
||||||
val currentServer: LiveData<JellyfinServer?> get() = _current.map { it?.server }
|
val currentServer: LiveData<JellyfinServer?> get() = _current.map { it?.server }
|
||||||
val currentUser: LiveData<JellyfinUser?> get() = _current.map { it?.user }
|
val currentUser: LiveData<JellyfinUser?> get() = _current.map { it?.user }
|
||||||
val currentUserDto: LiveData<UserDto?> get() = _current.map { it?.userDto }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a server to the app database and updated the [ApiClient] to the server's URL
|
* Adds a server to the app database and updated the [ApiClient] to the server's URL
|
||||||
|
|
@ -101,7 +103,8 @@ class ServerRepository
|
||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
_current.value = CurrentUser(updatedServer, updatedUser, userDto)
|
_current.value = CurrentUser(updatedServer, updatedUser)
|
||||||
|
_currentUserDto.value = userDto
|
||||||
}
|
}
|
||||||
sharedPreferences.edit(true) {
|
sharedPreferences.edit(true) {
|
||||||
putString(SERVER_URL_KEY, updatedServer.url)
|
putString(SERVER_URL_KEY, updatedServer.url)
|
||||||
|
|
@ -128,6 +131,15 @@ class ServerRepository
|
||||||
serverDao.getServer(serverId)
|
serverDao.getServer(serverId)
|
||||||
}
|
}
|
||||||
if (serverAndUsers != null) {
|
if (serverAndUsers != null) {
|
||||||
|
val current = _current.value
|
||||||
|
if (current != null && current.server.id == serverId && current.user.id == userId) {
|
||||||
|
Timber.v("Restoring session for current user, so shortcut")
|
||||||
|
apiClient.update(
|
||||||
|
baseUrl = current.server.url,
|
||||||
|
accessToken = current.user.accessToken,
|
||||||
|
)
|
||||||
|
return current
|
||||||
|
} else {
|
||||||
val user = serverAndUsers.users.firstOrNull { it.id == userId }
|
val user = serverAndUsers.users.firstOrNull { it.id == userId }
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
// TODO pin-related
|
// TODO pin-related
|
||||||
|
|
@ -135,6 +147,7 @@ class ServerRepository
|
||||||
return changeUser(serverAndUsers.server, user)
|
return changeUser(serverAndUsers.server, user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -271,5 +284,4 @@ class ServerRepository
|
||||||
data class CurrentUser(
|
data class CurrentUser(
|
||||||
val server: JellyfinServer,
|
val server: JellyfinServer,
|
||||||
val user: JellyfinUser,
|
val user: JellyfinUser,
|
||||||
val userDto: UserDto,
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import org.jellyfin.sdk.model.api.UserConfiguration
|
||||||
*/
|
*/
|
||||||
data class UserPreferences(
|
data class UserPreferences(
|
||||||
val appPreferences: AppPreferences,
|
val appPreferences: AppPreferences,
|
||||||
val userConfig: UserConfiguration,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val DefaultUserConfiguration =
|
val DefaultUserConfiguration =
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import org.jellyfin.sdk.model.api.MediaSourceInfo
|
||||||
import org.jellyfin.sdk.model.api.MediaStream
|
import org.jellyfin.sdk.model.api.MediaStream
|
||||||
import org.jellyfin.sdk.model.api.MediaStreamType
|
import org.jellyfin.sdk.model.api.MediaStreamType
|
||||||
import org.jellyfin.sdk.model.api.SubtitlePlaybackMode
|
import org.jellyfin.sdk.model.api.SubtitlePlaybackMode
|
||||||
|
import org.jellyfin.sdk.model.api.UserConfiguration
|
||||||
import org.jellyfin.sdk.model.serializer.toUUIDOrNull
|
import org.jellyfin.sdk.model.serializer.toUUIDOrNull
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
@ -26,6 +27,8 @@ class StreamChoiceService
|
||||||
private val serverRepository: ServerRepository,
|
private val serverRepository: ServerRepository,
|
||||||
private val playbackLanguageChoiceDao: PlaybackLanguageChoiceDao,
|
private val playbackLanguageChoiceDao: PlaybackLanguageChoiceDao,
|
||||||
) {
|
) {
|
||||||
|
private val userConfig: UserConfiguration? get() = serverRepository.currentUserDto.value?.configuration
|
||||||
|
|
||||||
suspend fun updateAudio(
|
suspend fun updateAudio(
|
||||||
dto: BaseItemDto,
|
dto: BaseItemDto,
|
||||||
audioLang: String,
|
audioLang: String,
|
||||||
|
|
@ -117,7 +120,7 @@ class StreamChoiceService
|
||||||
val seriesLang =
|
val seriesLang =
|
||||||
playbackLanguageChoice?.audioLanguage?.takeIf { it.isNotNullOrBlank() }
|
playbackLanguageChoice?.audioLanguage?.takeIf { it.isNotNullOrBlank() }
|
||||||
// If the user has chosen a different language for the series, prefer that
|
// If the user has chosen a different language for the series, prefer that
|
||||||
val audioLanguage = seriesLang ?: prefs.userConfig.audioLanguagePreference
|
val audioLanguage = seriesLang ?: userConfig?.audioLanguagePreference
|
||||||
|
|
||||||
if (audioLanguage.isNotNullOrBlank()) {
|
if (audioLanguage.isNotNullOrBlank()) {
|
||||||
val sorted =
|
val sorted =
|
||||||
|
|
@ -174,7 +177,7 @@ class StreamChoiceService
|
||||||
val seriesLang =
|
val seriesLang =
|
||||||
playbackLanguageChoice?.subtitleLanguage?.takeIf { it.isNotNullOrBlank() }
|
playbackLanguageChoice?.subtitleLanguage?.takeIf { it.isNotNullOrBlank() }
|
||||||
val subtitleLanguage =
|
val subtitleLanguage =
|
||||||
(seriesLang ?: prefs.userConfig.subtitleLanguagePreference)
|
(seriesLang ?: userConfig?.subtitleLanguagePreference)
|
||||||
?.takeIf { it.isNotNullOrBlank() }
|
?.takeIf { it.isNotNullOrBlank() }
|
||||||
|
|
||||||
val subtitleMode =
|
val subtitleMode =
|
||||||
|
|
@ -192,7 +195,7 @@ class StreamChoiceService
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
// Fallback to the user's preference
|
// Fallback to the user's preference
|
||||||
prefs.userConfig.subtitleMode
|
userConfig?.subtitleMode ?: SubtitlePlaybackMode.DEFAULT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return when (subtitleMode) {
|
return when (subtitleMode) {
|
||||||
|
|
@ -213,7 +216,7 @@ class StreamChoiceService
|
||||||
}
|
}
|
||||||
|
|
||||||
SubtitlePlaybackMode.SMART -> {
|
SubtitlePlaybackMode.SMART -> {
|
||||||
val audioLanguage = prefs.userConfig.audioLanguagePreference
|
val audioLanguage = userConfig?.audioLanguagePreference
|
||||||
val audioStreamLang = audioStream?.language
|
val audioStreamLang = audioStream?.language
|
||||||
if (audioLanguage.isNotNullOrBlank() && audioStreamLang.isNotNullOrBlank() && audioLanguage != audioStreamLang) {
|
if (audioLanguage.isNotNullOrBlank() && audioStreamLang.isNotNullOrBlank() && audioLanguage != audioStreamLang) {
|
||||||
candidates.firstOrNull { it.language == subtitleLanguage }
|
candidates.firstOrNull { it.language == subtitleLanguage }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package com.github.damontecres.wholphin.services
|
||||||
import androidx.datastore.core.DataStore
|
import androidx.datastore.core.DataStore
|
||||||
import com.github.damontecres.wholphin.data.ServerRepository
|
import com.github.damontecres.wholphin.data.ServerRepository
|
||||||
import com.github.damontecres.wholphin.preferences.AppPreferences
|
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.DefaultUserConfiguration
|
|
||||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||||
import kotlinx.coroutines.flow.firstOrNull
|
import kotlinx.coroutines.flow.firstOrNull
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
@ -21,7 +20,6 @@ class UserPreferencesService
|
||||||
val appPrefs = preferencesDataStore.data.firstOrNull() ?: AppPreferences.getDefaultInstance()
|
val appPrefs = preferencesDataStore.data.firstOrNull() ?: AppPreferences.getDefaultInstance()
|
||||||
UserPreferences(
|
UserPreferences(
|
||||||
appPrefs,
|
appPrefs,
|
||||||
userConfig ?: DefaultUserConfiguration,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -302,7 +302,7 @@ fun DebugPage(
|
||||||
color = MaterialTheme.colorScheme.onSurface,
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = "User server settings: ${preferences.userConfig}",
|
text = "User server settings: ${viewModel.serverRepository.currentUserDto.value?.configuration}",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.onSurface,
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue