Skip to content

Commit 7398fc0

Browse files
committed
自动提交代码
1 parent 4964a2b commit 7398fc0

File tree

258 files changed

+12272
-1743
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

258 files changed

+12272
-1743
lines changed

Monica for Android/app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ dependencies {
9191
implementation libs.androidx.core.ktx
9292
implementation libs.androidx.core.splashscreen // 添加splashscreen依赖
9393
implementation libs.androidx.lifecycle.runtime.ktx
94+
implementation "androidx.lifecycle:lifecycle-process:2.6.1"
9495
implementation libs.androidx.activity.compose
9596

9697
// Compose

Monica for Android/app/src/main/java/takagi/ru/monica/MainActivity.kt

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ import androidx.fragment.app.FragmentActivity
5252
import androidx.lifecycle.viewmodel.compose.viewModel
5353
import androidx.lifecycle.Lifecycle
5454
import androidx.lifecycle.LifecycleEventObserver
55-
import androidx.compose.ui.platform.LocalLifecycleOwner
55+
import androidx.lifecycle.compose.LocalLifecycleOwner
5656
import androidx.navigation.NavHostController
5757
import androidx.navigation.NavOptionsBuilder
5858
import androidx.navigation.NavType
@@ -369,12 +369,19 @@ fun MonicaApp(
369369
val isFirstTime = runCatching {
370370
!viewModel.isMasterPasswordSet()
371371
}.getOrDefault(false)
372+
val canRestoreSession = runCatching {
373+
SessionManager.canSkipVerification(context)
374+
}.getOrDefault(false)
372375
StartupAuthState(
373376
disablePasswordVerification = disablePasswordVerification,
374-
isFirstTime = isFirstTime
377+
isFirstTime = isFirstTime,
378+
canRestoreSession = canRestoreSession
375379
)
376380
}
377-
if (loadedState.disablePasswordVerification && !loadedState.isFirstTime) {
381+
if (
382+
(loadedState.disablePasswordVerification && !loadedState.isFirstTime) ||
383+
loadedState.canRestoreSession
384+
) {
378385
viewModel.markAuthenticatedForBypass()
379386
}
380387
startupAuthState = loadedState
@@ -445,7 +452,8 @@ fun MonicaApp(
445452

446453
private data class StartupAuthState(
447454
val disablePasswordVerification: Boolean,
448-
val isFirstTime: Boolean
455+
val isFirstTime: Boolean,
456+
val canRestoreSession: Boolean
449457
)
450458

451459
@Composable
@@ -470,6 +478,7 @@ fun MonicaContent(
470478
initialIsFirstTime: Boolean = false,
471479
onPermissionRequested: (String, (Boolean) -> Unit) -> Unit
472480
) {
481+
val context = LocalContext.current
473482
val isAuthenticated by viewModel.isAuthenticated.collectAsState()
474483
val settings by settingsViewModel.settings.collectAsState()
475484
val lifecycleOwner = LocalLifecycleOwner.current
@@ -482,31 +491,24 @@ fun MonicaContent(
482491
val currentSettings by rememberUpdatedState(settings)
483492
val currentIsFirstTime by rememberUpdatedState(isFirstTime)
484493

485-
// Auto-lock logic: only use lifecycleOwner as key to prevent observer recreation
486-
// The settings and auth state are captured by closure and always reflect latest values
494+
// Auto-lock logic: measure actual background duration and lock only when timeout is exceeded.
487495
DisposableEffect(lifecycleOwner) {
488496
val observer = LifecycleEventObserver { _, event ->
489497
when (event) {
490498
Lifecycle.Event.ON_STOP -> {
491-
// Only record timestamp when user is authenticated
492-
// 使用 currentIsAuthenticated 确保访问最新值
493499
if (currentIsAuthenticated) {
494500
lastBackgroundTimestamp = System.currentTimeMillis()
495501
}
496502
}
497503
Lifecycle.Event.ON_START -> {
498-
// 如果已禁用密码验证,跳过自动锁定
499-
// 使用 currentSettings 和 currentIsFirstTime 确保访问最新值
500-
if (currentSettings.disablePasswordVerification && !currentIsFirstTime) {
501-
viewModel.refreshKeePassFromSourceForCurrentContext()
502-
lastBackgroundTimestamp = null
503-
return@LifecycleEventObserver
504+
if (!currentIsAuthenticated && SessionManager.canSkipVerification(context)) {
505+
viewModel.restoreAuthenticatedSession()
504506
}
505-
507+
506508
val minutes = currentSettings.autoLockMinutes
507509
val timeoutMs = when {
508-
minutes == -1 -> null // Never auto-lock
509-
minutes <= 0 -> 0L // Immediate lock after background
510+
minutes == -1 -> null
511+
minutes <= 0 -> 0L
510512
else -> minutes.toLong() * 60_000L
511513
}
512514

@@ -526,9 +528,19 @@ fun MonicaContent(
526528
} else if (timeoutMs == null) {
527529
lastBackgroundTimestamp = null
528530
}
531+
529532
if (currentIsAuthenticated || (currentSettings.disablePasswordVerification && !currentIsFirstTime)) {
530533
viewModel.refreshKeePassFromSourceForCurrentContext()
531534
}
535+
if (!currentIsAuthenticated &&
536+
!SessionManager.canSkipVerification(context) &&
537+
!(currentSettings.disablePasswordVerification && !currentIsFirstTime)
538+
) {
539+
navController.navigate(Screen.Login.route) {
540+
launchSingleTop = true
541+
popUpTo(0) { inclusive = true }
542+
}
543+
}
532544
}
533545
else -> Unit
534546
}
@@ -556,6 +568,21 @@ fun MonicaContent(
556568
popUpTo(Screen.Login.route) { inclusive = true }
557569
}
558570
}
571+
} else if (!(settings.disablePasswordVerification && !isFirstTime)) {
572+
if (SessionManager.canSkipVerification(context)) {
573+
viewModel.restoreAuthenticatedSession()
574+
return@LaunchedEffect
575+
}
576+
if (!lifecycleOwner.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
577+
return@LaunchedEffect
578+
}
579+
val currentRoute = navController.currentDestination?.route
580+
if (currentRoute != Screen.Login.route) {
581+
navController.navigate(Screen.Login.route) {
582+
launchSingleTop = true
583+
popUpTo(0) { inclusive = true }
584+
}
585+
}
559586
}
560587
}
561588

Monica for Android/app/src/main/java/takagi/ru/monica/autofill_ng/AutofillPickerActivityV2.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,18 @@ class AutofillPickerActivityV2 : BaseMonicaActivity() {
320320
val securityManager = SecurityManager(applicationContext)
321321
// settingsManager 已由 BaseMonicaActivity 初始化
322322
val localSettingsManager = settingsManager
323+
324+
runCatching {
325+
val autoLockMinutes = runBlocking {
326+
localSettingsManager.settingsFlow.first().autoLockMinutes
327+
}
328+
SessionManager.updateAutoLockTimeout(autoLockMinutes)
329+
}.onFailure { error ->
330+
AutofillLogger.w(
331+
"PICKER",
332+
"Failed to sync auto-lock timeout before verification: ${error.message}"
333+
)
334+
}
323335

324336
// 检查是否可以跳过验证(基于会话管理器的安全窗规则)
325337
val canSkipAuth = canSkipVerification()

Monica for Android/app/src/main/java/takagi/ru/monica/autofill_ng/builder/FillResponseBuilderNg.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ class FillResponseBuilderNg(
195195
val menuPresentation = if (filledData.isVaultLocked) {
196196
AutofillDatasetBuilder.RemoteViewsFactory.createUnlockPrompt(
197197
context = context,
198-
message = context.getString(R.string.unlock)
198+
message = context.getString(R.string.autofill_manual_entry_title)
199199
)
200200
} else {
201201
AutofillDatasetBuilder.RemoteViewsFactory.createManualSelection(

Monica for Android/app/src/main/java/takagi/ru/monica/autofill_ng/builder/FilledDataBuilderNg.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import takagi.ru.monica.autofill_ng.AutofillSecretResolver
1414
import takagi.ru.monica.data.PasswordEntry
1515
import takagi.ru.monica.security.SecurityManager
1616
import takagi.ru.monica.security.SessionManager
17+
import takagi.ru.monica.utils.SettingsManager
18+
import kotlinx.coroutines.flow.first
19+
import kotlinx.coroutines.runBlocking
1720

1821
private const val MAX_FILLED_PARTITIONS_COUNT = 20
1922
private const val MAX_INLINE_SUGGESTION_COUNT = 5
@@ -23,10 +26,26 @@ class FilledDataBuilderNg(
2326
private val securityManager: SecurityManager,
2427
) {
2528

29+
private fun syncAutoLockTimeoutForAutofill() {
30+
runCatching {
31+
val settingsManager = SettingsManager(context.applicationContext)
32+
val autoLockMinutes = runBlocking {
33+
settingsManager.settingsFlow.first().autoLockMinutes
34+
}
35+
SessionManager.updateAutoLockTimeout(autoLockMinutes)
36+
}.onFailure { error ->
37+
android.util.Log.w(
38+
"FilledDataBuilderNg",
39+
"Failed to sync auto-lock timeout for autofill: ${error.message}"
40+
)
41+
}
42+
}
43+
2644
fun build(
2745
request: AutofillRequest.Fillable,
2846
passwords: List<PasswordEntry>,
2947
): FilledData {
48+
syncAutoLockTimeoutForAutofill()
3049
val isVaultLocked = !SessionManager.canSkipVerification(context)
3150
val maxCipherInlineSuggestionsCount = (request.maxInlineSuggestionsCount - 1)
3251
.coerceAtMost(MAX_INLINE_SUGGESTION_COUNT)

0 commit comments

Comments
 (0)