mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
Add setting to protect a user profile with a PIN (#356)
Allows for setting a per-user profile PIN that must be entered to switch to the user. The PIN is a sequence of directional buttons, ie D-Pad left/right/up/down. This PIN is per device per user per server. The PIN is stored locally and not sent nor shared with the server. If you forget your PIN, can still access the app using server credentials which also removes the PIN. Additionally, there is another setting to disable automatically sign in. When enabled (default) the last user is automatically restored, even if there is a PIN. If disabled, a server & user must always be selected when opening the app. Closes #268 Closes #321
This commit is contained in:
parent
a294661520
commit
8ea84b3efe
20 changed files with 845 additions and 30 deletions
|
|
@ -1,6 +1,7 @@
|
|||
package com.github.damontecres.wholphin
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.WindowManager
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.foundation.background
|
||||
|
|
@ -9,6 +10,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
|
|
@ -42,6 +44,7 @@ import com.github.damontecres.wholphin.services.UpdateChecker
|
|||
import com.github.damontecres.wholphin.services.hilt.AuthOkHttpClient
|
||||
import com.github.damontecres.wholphin.ui.CoilConfig
|
||||
import com.github.damontecres.wholphin.ui.LocalImageUrlService
|
||||
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
||||
import com.github.damontecres.wholphin.ui.launchIO
|
||||
import com.github.damontecres.wholphin.ui.nav.ApplicationContent
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
|
|
@ -49,6 +52,8 @@ import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
|||
import com.github.damontecres.wholphin.util.DebugLogTree
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.OkHttpClient
|
||||
import org.jellyfin.sdk.model.serializer.toUUIDOrNull
|
||||
|
|
@ -129,13 +134,15 @@ class MainActivity : AppCompatActivity() {
|
|||
) {
|
||||
var isRestoringSession by remember { mutableStateOf(true) }
|
||||
LaunchedEffect(Unit) {
|
||||
try {
|
||||
serverRepository.restoreSession(
|
||||
appPreferences.currentServerId?.toUUIDOrNull(),
|
||||
appPreferences.currentUserId?.toUUIDOrNull(),
|
||||
)
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex, "Exception restoring session")
|
||||
if (appPreferences.signInAutomatically) {
|
||||
try {
|
||||
serverRepository.restoreSession(
|
||||
appPreferences.currentServerId?.toUUIDOrNull(),
|
||||
appPreferences.currentUserId?.toUUIDOrNull(),
|
||||
)
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex, "Exception restoring session")
|
||||
}
|
||||
}
|
||||
isRestoringSession = false
|
||||
}
|
||||
|
|
@ -158,12 +165,30 @@ class MainActivity : AppCompatActivity() {
|
|||
)
|
||||
}
|
||||
} else {
|
||||
key(current) {
|
||||
val initialDestination =
|
||||
if (current != null) {
|
||||
Destination.Home()
|
||||
DisposableEffect(Unit) {
|
||||
onDispose {
|
||||
if (!appPreferences.signInAutomatically) {
|
||||
serverRepository.closeSession()
|
||||
}
|
||||
}
|
||||
}
|
||||
key(current?.server?.id, current?.user?.id) {
|
||||
LaunchedEffect(current?.user?.pin) {
|
||||
if (current?.user?.pin?.isNotNullOrBlank() == true) {
|
||||
// If user has a pin, then obscure the window in previews
|
||||
window?.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_SECURE,
|
||||
WindowManager.LayoutParams.FLAG_SECURE,
|
||||
)
|
||||
} else {
|
||||
Destination.ServerList
|
||||
window?.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||
}
|
||||
}
|
||||
val initialDestination =
|
||||
when {
|
||||
current != null -> Destination.Home()
|
||||
!appPreferences.signInAutomatically -> Destination.ServerList // TODO user list?
|
||||
else -> Destination.ServerList
|
||||
}
|
||||
val backStack = rememberNavBackStack(initialDestination)
|
||||
navigationManager.backStack = backStack
|
||||
|
|
@ -206,4 +231,14 @@ class MainActivity : AppCompatActivity() {
|
|||
appUpgradeHandler.run()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRestart() {
|
||||
super.onRestart()
|
||||
val signInAutomatically =
|
||||
runBlocking { userPreferencesDataStore.data.firstOrNull()?.signInAutomatically } ?: true
|
||||
Timber.i("onRestart: signInAutomatically=$signInAutomatically")
|
||||
if (!signInAutomatically) {
|
||||
serverRepository.closeSession()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue