Skip to content

Commit df142c7

Browse files
committed
save changes
1 parent 6fbce53 commit df142c7

30 files changed

+3187
-852
lines changed

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

Lines changed: 129 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.app.Application
44
import android.content.Context
55
import android.content.Intent
66
import android.net.Uri
7+
import android.os.Build
78
import android.os.Bundle
89
import android.util.Log
910
import android.view.Gravity
@@ -12,6 +13,9 @@ import android.view.ViewGroup
1213
import android.widget.TextView
1314
import android.widget.Toast
1415
import androidx.activity.ComponentActivity
16+
import androidx.activity.BackEventCompat
17+
import androidx.activity.compose.BackHandler
18+
import androidx.activity.compose.PredictiveBackHandler
1519
import androidx.activity.compose.setContent
1620
import androidx.activity.result.ActivityResultLauncher
1721
import androidx.activity.result.contract.ActivityResultContracts
@@ -29,15 +33,19 @@ import androidx.compose.runtime.Composable
2933
import androidx.compose.runtime.DisposableEffect
3034
import androidx.compose.runtime.LaunchedEffect
3135
import androidx.compose.runtime.getValue
36+
import androidx.compose.runtime.mutableFloatStateOf
3237
import androidx.compose.runtime.mutableStateOf
3338
import androidx.compose.runtime.remember
3439
import androidx.compose.runtime.rememberUpdatedState
3540
import androidx.compose.runtime.rememberCoroutineScope
3641
import androidx.compose.runtime.setValue
3742
import androidx.compose.ui.Alignment
3843
import androidx.compose.ui.Modifier
44+
import androidx.compose.ui.graphics.TransformOrigin
45+
import androidx.compose.ui.graphics.graphicsLayer
3946
import androidx.compose.ui.platform.LocalContext
4047
import androidx.compose.ui.platform.LocalView
48+
import androidx.compose.ui.unit.dp
4149
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
4250
import androidx.core.view.WindowCompat
4351
import androidx.fragment.app.FragmentActivity
@@ -53,10 +61,12 @@ import androidx.navigation.compose.composable
5361
import androidx.navigation.compose.rememberNavController
5462
import androidx.navigation.navArgument
5563
import kotlinx.coroutines.flow.first
64+
import kotlinx.coroutines.flow.collect
5665
import kotlinx.coroutines.flow.map
5766
import kotlinx.coroutines.flow.distinctUntilChanged
5867
import kotlinx.coroutines.Dispatchers
5968
import androidx.lifecycle.lifecycleScope
69+
import kotlinx.coroutines.CancellationException
6070
import kotlinx.coroutines.delay
6171
import kotlinx.coroutines.launch
6272
import kotlinx.coroutines.withContext
@@ -657,6 +667,9 @@ fun MonicaContent(
657667
onNavigateToExtensions = {
658668
navController.navigate(Screen.Extensions.route)
659669
},
670+
onNavigateToCommonAccountTemplates = {
671+
navController.navigate(Screen.CommonAccountTemplates.route)
672+
},
660673
onNavigateToPageCustomization = {
661674
navController.navigate(Screen.PageAdjustmentCustomization.route)
662675
},
@@ -727,16 +740,28 @@ fun MonicaContent(
727740
popExitTransition = { rightSlidePopExitTransition() }
728741
) { backStackEntry ->
729742
val passwordId = backStackEntry.arguments?.getString("passwordId")?.toLongOrNull() ?: -1L
730-
AddEditPasswordScreen(
731-
viewModel = viewModel,
732-
totpViewModel = totpViewModel,
733-
bankCardViewModel = bankCardViewModel,
734-
localKeePassViewModel = localKeePassViewModel,
735-
passwordId = if (passwordId == -1L) null else passwordId,
736-
onNavigateBack = {
737-
navController.popBackStack()
743+
val navigateBackFromAddEditPassword = {
744+
val popped = navController.popBackStack()
745+
if (!popped) {
746+
navController.navigate(Screen.Main.createRoute()) {
747+
popUpTo(0) { inclusive = true }
748+
launchSingleTop = true
749+
}
738750
}
739-
)
751+
}
752+
PredictiveBackPageContainer(
753+
enabled = settings.predictiveBackForPageNavigationEnabled,
754+
onNavigateBack = navigateBackFromAddEditPassword
755+
) {
756+
AddEditPasswordScreen(
757+
viewModel = viewModel,
758+
totpViewModel = totpViewModel,
759+
bankCardViewModel = bankCardViewModel,
760+
localKeePassViewModel = localKeePassViewModel,
761+
passwordId = if (passwordId == -1L) null else passwordId,
762+
onNavigateBack = navigateBackFromAddEditPassword
763+
)
764+
}
740765
}
741766

742767
composable(
@@ -1017,33 +1042,39 @@ fun MonicaContent(
10171042
val passwordId = backStackEntry.arguments?.getString("passwordId")?.toLongOrNull() ?: -1L
10181043

10191044
if (passwordId > 0) {
1045+
val navigateBackFromPasswordDetail = {
1046+
val popped = navController.popBackStack()
1047+
if (!popped) {
1048+
navController.navigate(Screen.Main.createRoute()) {
1049+
popUpTo(0) { inclusive = true }
1050+
launchSingleTop = true
1051+
}
1052+
}
1053+
}
10201054
androidx.compose.runtime.CompositionLocalProvider(
10211055
takagi.ru.monica.ui.LocalAnimatedVisibilityScope provides this
10221056
) {
1023-
takagi.ru.monica.ui.screens.PasswordDetailScreen(
1024-
viewModel = viewModel,
1025-
passkeyViewModel = passkeyViewModel,
1026-
passwordId = passwordId,
1027-
disablePasswordVerification = settings.disablePasswordVerification,
1028-
biometricEnabled = settings.biometricEnabled,
1029-
iconCardsEnabled = settings.iconCardsEnabled && settings.passwordPageIconEnabled,
1030-
unmatchedIconHandlingStrategy = settings.unmatchedIconHandlingStrategy,
1031-
enableSharedBounds = false,
1032-
onNavigateBack = {
1033-
val popped = navController.popBackStack()
1034-
if (!popped) {
1035-
navController.navigate(Screen.Main.createRoute()) {
1036-
popUpTo(0) { inclusive = true }
1057+
PredictiveBackPageContainer(
1058+
enabled = settings.predictiveBackForPageNavigationEnabled,
1059+
onNavigateBack = navigateBackFromPasswordDetail
1060+
) {
1061+
takagi.ru.monica.ui.screens.PasswordDetailScreen(
1062+
viewModel = viewModel,
1063+
passkeyViewModel = passkeyViewModel,
1064+
passwordId = passwordId,
1065+
disablePasswordVerification = settings.disablePasswordVerification,
1066+
biometricEnabled = settings.biometricEnabled,
1067+
iconCardsEnabled = settings.iconCardsEnabled && settings.passwordPageIconEnabled,
1068+
unmatchedIconHandlingStrategy = settings.unmatchedIconHandlingStrategy,
1069+
enableSharedBounds = false,
1070+
onNavigateBack = navigateBackFromPasswordDetail,
1071+
onEditPassword = { id ->
1072+
navController.navigate(Screen.AddEditPassword.createRoute(id)) {
10371073
launchSingleTop = true
10381074
}
10391075
}
1040-
},
1041-
onEditPassword = { id ->
1042-
navController.navigate(Screen.AddEditPassword.createRoute(id)) {
1043-
launchSingleTop = true
1044-
}
1045-
}
1046-
)
1076+
)
1077+
}
10471078
}
10481079
}
10491080
}
@@ -1771,6 +1802,24 @@ fun MonicaContent(
17711802
}
17721803
}
17731804

1805+
composable(
1806+
route = Screen.CommonAccountTemplates.route,
1807+
enterTransition = { rightSlideEnterTransition() },
1808+
exitTransition = { ExitTransition.None },
1809+
popEnterTransition = { EnterTransition.None },
1810+
popExitTransition = { rightSlidePopExitTransition() }
1811+
) {
1812+
androidx.compose.runtime.CompositionLocalProvider(
1813+
takagi.ru.monica.ui.LocalAnimatedVisibilityScope provides this
1814+
) {
1815+
takagi.ru.monica.ui.screens.CommonAccountTemplatesScreen(
1816+
onNavigateBack = {
1817+
navController.popBackStack()
1818+
}
1819+
)
1820+
}
1821+
}
1822+
17741823
composable(
17751824
route = Screen.PageAdjustmentCustomization.route,
17761825
enterTransition = { rightSlideEnterTransition() },
@@ -2125,6 +2174,56 @@ fun MonicaContent(
21252174
}
21262175
}
21272176

2177+
@Composable
2178+
private fun PredictiveBackPageContainer(
2179+
enabled: Boolean,
2180+
onNavigateBack: () -> Unit,
2181+
content: @Composable () -> Unit
2182+
) {
2183+
var progress by remember { mutableFloatStateOf(0f) }
2184+
var swipeEdge by remember { mutableStateOf(BackEventCompat.EDGE_LEFT) }
2185+
2186+
PredictiveBackHandler(enabled = enabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { events ->
2187+
try {
2188+
events.collect { event ->
2189+
swipeEdge = event.swipeEdge
2190+
progress = event.progress.coerceIn(0f, 1f)
2191+
}
2192+
onNavigateBack()
2193+
} catch (_: CancellationException) {
2194+
// Gesture canceled: just reset visual state.
2195+
} finally {
2196+
progress = 0f
2197+
}
2198+
}
2199+
2200+
BackHandler(enabled = enabled && Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
2201+
onNavigateBack()
2202+
}
2203+
2204+
val edgeDirection = if (swipeEdge == BackEventCompat.EDGE_RIGHT) -1f else 1f
2205+
val scale = 1f - (0.08f * progress)
2206+
val alpha = 1f - (0.08f * progress)
2207+
2208+
Box(
2209+
modifier = Modifier
2210+
.fillMaxSize()
2211+
.graphicsLayer {
2212+
val translationPx = 24.dp.toPx() * progress * edgeDirection
2213+
translationX = translationPx
2214+
scaleX = scale
2215+
scaleY = scale
2216+
this.alpha = alpha
2217+
transformOrigin = TransformOrigin(
2218+
pivotFractionX = if (edgeDirection > 0f) 0f else 1f,
2219+
pivotFractionY = 0.5f
2220+
)
2221+
}
2222+
) {
2223+
content()
2224+
}
2225+
}
2226+
21282227
private fun rightSlideEnterTransition() = slideInHorizontally(
21292228
initialOffsetX = { fullWidth -> fullWidth },
21302229
animationSpec = tween(220)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ class AutofillPreferences(private val context: Context) {
268268
}
269269

270270
val isV2RespectAutofillOffEnabled: Flow<Boolean> = context.dataStore.data.map { preferences ->
271-
preferences[KEY_V2_RESPECT_AUTOFILL_OFF] ?: true
271+
preferences[KEY_V2_RESPECT_AUTOFILL_OFF] ?: false
272272
}
273273

274274
suspend fun setV2RespectAutofillOffEnabled(enabled: Boolean) {

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

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -314,14 +314,6 @@ class EnhancedAutofillStructureParserV2 {
314314
hint = InternalHint.OFF,
315315
target = "off",
316316
),
317-
AutofillHintMatcher(
318-
hint = InternalHint.OFF,
319-
target = "no",
320-
),
321-
AutofillHintMatcher(
322-
hint = InternalHint.OFF,
323-
target = "nope",
324-
),
325317
)
326318

327319
fun parse(structure: AssistStructure, respectAutofillOff: Boolean = true): ParsedStructure {

Monica for Android/app/src/main/java/takagi/ru/monica/bitwarden/service/BitwardenAuthService.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -989,8 +989,10 @@ class BitwardenAuthService(
989989
}
990990

991991
private fun isNewDeviceVerificationRequired(errorResponse: TokenResponse?): Boolean {
992-
val message = errorResponse?.errorModel?.message ?: return false
993-
return message.equals("new device verification required", ignoreCase = true)
992+
val modelMessage = errorResponse?.errorModel?.message.orEmpty()
993+
val errorDescription = errorResponse?.errorDescription.orEmpty()
994+
return modelMessage.contains("new device verification required", ignoreCase = true) ||
995+
errorDescription.contains("new device verification required", ignoreCase = true)
994996
}
995997

996998
private fun isCaptchaRequired(errorResponse: TokenResponse?, errorBody: String?): Boolean {

0 commit comments

Comments
 (0)