From fa141adc60300d5866270566f98fcc7304811b85 Mon Sep 17 00:00:00 2001
From: damontecres <154766448+damontecres@users.noreply.github.com>
Date: Sun, 7 Dec 2025 17:48:46 -0500
Subject: [PATCH 1/4] Ignore auto sign in if user has PIN (#392)
If the current user has a PIN, the sign in automatically setting is
ignored if the app is put in the background or restarted.
Follow up to #356 &
https://github.com/damontecres/Wholphin/issues/321#issuecomment-3621312496
I think the PIN protection needs some more thought overall.
---
.../main/java/com/github/damontecres/wholphin/MainActivity.kt | 4 ++--
.../com/github/damontecres/wholphin/data/ServerRepository.kt | 4 +++-
.../github/damontecres/wholphin/data/model/JellyfinServer.kt | 2 ++
3 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt b/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt
index dd3312c8..484e1ed4 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt
@@ -179,7 +179,7 @@ class MainActivity : AppCompatActivity() {
} else {
DisposableEffect(Unit) {
onDispose {
- if (!appPreferences.signInAutomatically) {
+ if (!appPreferences.signInAutomatically || current?.user?.hasPin == true) {
serverRepository.closeSession()
}
}
@@ -252,7 +252,7 @@ class MainActivity : AppCompatActivity() {
val signInAutomatically =
runBlocking { userPreferencesDataStore.data.firstOrNull()?.signInAutomatically } ?: true
Timber.i("onRestart: signInAutomatically=$signInAutomatically")
- if (!signInAutomatically) {
+ if (!signInAutomatically || serverRepository.currentUser.value?.hasPin == true) {
serverRepository.closeSession()
}
}
diff --git a/app/src/main/java/com/github/damontecres/wholphin/data/ServerRepository.kt b/app/src/main/java/com/github/damontecres/wholphin/data/ServerRepository.kt
index eed4422f..5fc98724 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/data/ServerRepository.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/data/ServerRepository.kt
@@ -109,6 +109,8 @@ class ServerRepository
/**
* Restores a session for the given server & user such as when the app reopens
+ *
+ * If user has a PIN, this returns false
*/
suspend fun restoreSession(
serverId: UUID?,
@@ -124,7 +126,7 @@ class ServerRepository
}
if (serverAndUsers != null) {
val user = serverAndUsers.users.firstOrNull { it.id == userId }
- if (user != null) {
+ if (user != null && !user.hasPin) {
changeUser(serverAndUsers.server, user)
return true
}
diff --git a/app/src/main/java/com/github/damontecres/wholphin/data/model/JellyfinServer.kt b/app/src/main/java/com/github/damontecres/wholphin/data/model/JellyfinServer.kt
index 0b8a3302..d8e40779 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/data/model/JellyfinServer.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/data/model/JellyfinServer.kt
@@ -52,6 +52,8 @@ data class JellyfinUser(
val accessToken: String?,
val pin: String? = null,
) {
+ val hasPin: Boolean get() = pin.isNotNullOrBlank()
+
override fun toString(): String =
"JellyfinUser(rowId=$rowId, id=$id, name=$name, serverId=$serverId, accessToken?=${accessToken.isNotNullOrBlank()}, pin?=${pin.isNotNullOrBlank()})"
}
From 82927d196838e1161086cc6dece74b29b0c6a45f Mon Sep 17 00:00:00 2001
From: damontecres <154766448+damontecres@users.noreply.github.com>
Date: Mon, 8 Dec 2025 10:13:51 -0500
Subject: [PATCH 2/4] Remove PIN & sign-in auto settings (#397)
Unfortunately, I think the PIN and automatic sign-in features require
more thought before it should be rolled out as a stable feature.
This PR disables the two settings and removes them from the UI.
See discussions in #321 and will reopen #268
---
.../damontecres/wholphin/MainActivity.kt | 79 +++++++++----------
.../wholphin/preferences/AppPreference.kt | 6 +-
.../wholphin/ui/setup/SwitchUserContent.kt | 12 +--
3 files changed, 50 insertions(+), 47 deletions(-)
diff --git a/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt b/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt
index 484e1ed4..ef90f38a 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt
@@ -1,7 +1,6 @@
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
@@ -10,7 +9,6 @@ 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
@@ -45,7 +43,6 @@ 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
@@ -53,8 +50,6 @@ 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
@@ -146,16 +141,17 @@ class MainActivity : AppCompatActivity() {
) {
var isRestoringSession by remember { mutableStateOf(true) }
LaunchedEffect(Unit) {
- if (appPreferences.signInAutomatically) {
- try {
- serverRepository.restoreSession(
- appPreferences.currentServerId?.toUUIDOrNull(),
- appPreferences.currentUserId?.toUUIDOrNull(),
- )
- } catch (ex: Exception) {
- Timber.e(ex, "Exception restoring session")
- }
+ // TODO PIN-related
+// if (appPreferences.signInAutomatically) {
+ try {
+ serverRepository.restoreSession(
+ appPreferences.currentServerId?.toUUIDOrNull(),
+ appPreferences.currentUserId?.toUUIDOrNull(),
+ )
+ } catch (ex: Exception) {
+ Timber.e(ex, "Exception restoring session")
}
+// }
isRestoringSession = false
}
val current by serverRepository.current.observeAsState()
@@ -177,32 +173,34 @@ class MainActivity : AppCompatActivity() {
)
}
} else {
- DisposableEffect(Unit) {
- onDispose {
- if (!appPreferences.signInAutomatically || current?.user?.hasPin == true) {
- serverRepository.closeSession()
- }
- }
- }
+ // TODO PIN-related
+// DisposableEffect(Unit) {
+// onDispose {
+// if (!appPreferences.signInAutomatically || current?.user?.hasPin == true) {
+// 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 {
- window?.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
- }
- }
+ // TODO PIN-related
+// 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 {
+// window?.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
+// }
+// }
val initialDestination =
when {
current != null -> Destination.Home()
- !appPreferences.signInAutomatically -> Destination.ServerList
+ // TODO PIN-related
+ // !appPreferences.signInAutomatically -> Destination.ServerList
- // TODO user list?
else -> Destination.ServerList
}
val backStack = rememberNavBackStack(initialDestination)
@@ -249,11 +247,12 @@ class MainActivity : AppCompatActivity() {
override fun onRestart() {
super.onRestart()
- val signInAutomatically =
- runBlocking { userPreferencesDataStore.data.firstOrNull()?.signInAutomatically } ?: true
- Timber.i("onRestart: signInAutomatically=$signInAutomatically")
- if (!signInAutomatically || serverRepository.currentUser.value?.hasPin == true) {
- serverRepository.closeSession()
- }
+ // TODO PIN-related
+// val signInAutomatically =
+// runBlocking { userPreferencesDataStore.data.firstOrNull()?.signInAutomatically } ?: true
+// Timber.i("onRestart: signInAutomatically=$signInAutomatically")
+// if (!signInAutomatically || serverRepository.currentUser.value?.hasPin == true) {
+// serverRepository.closeSession()
+// }
}
}
diff --git a/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt b/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt
index 4e182e0c..9a196d6b 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt
@@ -793,7 +793,8 @@ val basicPreferences =
title = R.string.ui_interface,
preferences =
listOf(
- AppPreference.SignInAuto,
+ // TODO PIN-related
+ // AppPreference.SignInAuto,
AppPreference.HomePageItems,
AppPreference.CombineContinueNext,
AppPreference.RewatchNextUp,
@@ -826,7 +827,8 @@ val basicPreferences =
title = R.string.profile_specific_settings,
preferences =
listOf(
- AppPreference.RequireProfilePin,
+ // TODO PIN-related
+ // AppPreference.RequireProfilePin,
AppPreference.UserPinnedNavDrawerItems,
),
),
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserContent.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserContent.kt
index e0aeb5a1..df0b79ee 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserContent.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserContent.kt
@@ -119,11 +119,13 @@ fun SwitchUserContent(
users = users,
currentUser = currentUser,
onSwitchUser = { user ->
- if (user.pin.isNotNullOrBlank()) {
- switchUserWithPin = user
- } else {
- viewModel.switchUser(user)
- }
+ // TODO PIN-related
+// if (user.pin.isNotNullOrBlank()) {
+// switchUserWithPin = user
+// } else {
+// viewModel.switchUser(user)
+// }
+ viewModel.switchUser(user)
},
onAddUser = { showAddUser = true },
onRemoveUser = { user ->
From 2cc3de6eff0d655454e3f224947321d3cc32e269 Mon Sep 17 00:00:00 2001
From: Damontecres