From cfa9fe2ffddb17ae8a8e4a12d62bd0b95641cbcf Mon Sep 17 00:00:00 2001 From: b-dev-mobile Date: Thu, 9 Jul 2026 02:50:57 +0000 Subject: [PATCH] =?UTF-8?q?security:=20FLAG=5FSECURE=20=D0=BD=D0=B0=20?= =?UTF-8?q?=D1=8D=D0=BA=D1=80=D0=B0=D0=BD=D0=B0=D1=85=20=D0=B2=D1=85=D0=BE?= =?UTF-8?q?=D0=B4=D0=B0=20=D0=B8=20PIN=20(=D0=B0=D1=83=D0=B4=D0=B8=D1=82?= =?UTF-8?q?=20=D0=BF.3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Новый эффект F7SecureScreen(): пока экран на виду — окно с FLAG_SECURE (нет в скриншотах/recents/записи экрана), снимается при уходе. Повешен на LoginScreen (ввод пароля), AppLockUnlockScreen (разблокировка PIN) и AppLockSetupDialog (создание PIN). Закрывает хвост Этапа 0 п.3. --- .../forbion/f7cloud/mobile/ui/AppLockGate.kt | 3 +++ .../forbion/f7cloud/mobile/ui/AppScaffold.kt | 2 ++ .../core/designsystem/F7SecureScreen.kt | 24 +++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 core/designsystem/src/main/java/ru/forbion/f7cloud/core/designsystem/F7SecureScreen.kt diff --git a/app/src/main/java/ru/forbion/f7cloud/mobile/ui/AppLockGate.kt b/app/src/main/java/ru/forbion/f7cloud/mobile/ui/AppLockGate.kt index bf8dcaf..050023a 100644 --- a/app/src/main/java/ru/forbion/f7cloud/mobile/ui/AppLockGate.kt +++ b/app/src/main/java/ru/forbion/f7cloud/mobile/ui/AppLockGate.kt @@ -53,6 +53,7 @@ import androidx.lifecycle.ProcessLifecycleOwner import ru.forbion.f7cloud.core.auth.AppLockStore import ru.forbion.f7cloud.core.designsystem.F7Colors import ru.forbion.f7cloud.core.designsystem.F7PrimaryButton +import ru.forbion.f7cloud.core.designsystem.F7SecureScreen import ru.forbion.f7cloud.core.designsystem.F7TextButton import ru.forbion.f7cloud.mobile.R @@ -145,6 +146,7 @@ fun AppLockSetupDialog( onLockConfigured: () -> Unit = {}, ) { if (!visible) return + F7SecureScreen() // создание/подтверждение PIN — не в скриншотах/recents val context = LocalContext.current val activity = context.findFragmentActivity() @@ -534,6 +536,7 @@ private fun AppLockUnlockScreen( lockSession: Int, onUnlocked: () -> Unit, ) { + F7SecureScreen() // экран разблокировки (PIN) — не в скриншотах/recents val context = LocalContext.current val activity = context.findFragmentActivity() var pin by remember { mutableStateOf("") } diff --git a/app/src/main/java/ru/forbion/f7cloud/mobile/ui/AppScaffold.kt b/app/src/main/java/ru/forbion/f7cloud/mobile/ui/AppScaffold.kt index 398e979..8ceec2a 100644 --- a/app/src/main/java/ru/forbion/f7cloud/mobile/ui/AppScaffold.kt +++ b/app/src/main/java/ru/forbion/f7cloud/mobile/ui/AppScaffold.kt @@ -81,6 +81,7 @@ import ru.forbion.f7cloud.core.push.F7PushEventHub import ru.forbion.f7cloud.core.push.F7PushRegistrar import ru.forbion.f7cloud.core.designsystem.F7OverlayNavigationProvider import ru.forbion.f7cloud.core.designsystem.F7AppMenuSheet +import ru.forbion.f7cloud.core.designsystem.F7SecureScreen import ru.forbion.f7cloud.core.designsystem.F7AppScaffold import ru.forbion.f7cloud.core.designsystem.F7AutoHideBottomBar import ru.forbion.f7cloud.core.designsystem.F7BottomBarActions @@ -689,6 +690,7 @@ fun AppScaffold( private const val PERMISSIONS_PROMPTED_KEY = "runtime_permissions_prompted_v2" @Composable private fun LoginScreen(onLogin: (AuthSession) -> Unit) { + F7SecureScreen() // ввод пароля — не в скриншотах/recents val context = LocalContext.current val scope = rememberCoroutineScope() val keyboardController = LocalSoftwareKeyboardController.current diff --git a/core/designsystem/src/main/java/ru/forbion/f7cloud/core/designsystem/F7SecureScreen.kt b/core/designsystem/src/main/java/ru/forbion/f7cloud/core/designsystem/F7SecureScreen.kt new file mode 100644 index 0000000..8262022 --- /dev/null +++ b/core/designsystem/src/main/java/ru/forbion/f7cloud/core/designsystem/F7SecureScreen.kt @@ -0,0 +1,24 @@ +package ru.forbion.f7cloud.core.designsystem + +import android.app.Activity +import android.view.WindowManager +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.ui.platform.LocalContext + +/** + * Пока этот экран на виду — окно помечено FLAG_SECURE: содержимое не попадает + * в скриншоты, превью в «недавних» и запись экрана. Вешать на чувствительные + * экраны (ввод пароля/PIN). Флаг снимается при уходе с экрана. + */ +@Composable +fun F7SecureScreen() { + val context = LocalContext.current + DisposableEffect(Unit) { + val window = (context as? Activity)?.window + window?.addFlags(WindowManager.LayoutParams.FLAG_SECURE) + onDispose { + window?.clearFlags(WindowManager.LayoutParams.FLAG_SECURE) + } + } +}