From 4004cee2799a5f1a82cf250cc8e86fb46379cc96 Mon Sep 17 00:00:00 2001 From: eliotcougar Date: Thu, 10 Sep 2026 06:34:20 +0300 Subject: [PATCH] UI/UX: Preserve asset-editor drafts during recompose (#6193) * Preserve asset-editor drafts and handle the keyboard Keep the asset name, URL, and delete-confirmation visibility in saveable Compose state so activity recreation does not discard an unfinished edit. Key the state by asset identity and initial field values. Make the form vertically scrollable, consume the Scaffold padding, and apply IME padding so its fields remain reachable when the keyboard reduces the available height. Extract these presentation changes from local/talkback-all-10 without changing accessibility labels, deletion wording, or asset-save validation order. * Resize the asset editor when the keyboard opens Declare stateUnchanged|adjustResize for UserAssetUrlActivity, matching the other editor activities. Without an explicit resize policy, opening the IME in landscape pans the entire window and moves the toolbar Save action off-screen despite the scrollable Compose form. Verified on Android 13 Pixel 6a: rotate with an unsaved draft, reopen the landscape keyboard, scroll between fields, edit the first field, save without hiding the keyboard, and reopen persisted values. Portrait keyboard and Save also pass. Debug assembly succeeded. --- V2rayNG/app/src/main/AndroidManifest.xml | 1 + .../ang/ui/userasset/UserAssetUrlActivity.kt | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/V2rayNG/app/src/main/AndroidManifest.xml b/V2rayNG/app/src/main/AndroidManifest.xml index c8304c4c6..7b2a0d633 100644 --- a/V2rayNG/app/src/main/AndroidManifest.xml +++ b/V2rayNG/app/src/main/AndroidManifest.xml @@ -153,6 +153,7 @@ android:exported="false" /> Boolean, onDelete: () -> Unit ) { - var remarks by remember { mutableStateOf(initialRemarks) } - var url by remember { mutableStateOf(initialUrl) } - var showDeleteConfirm by remember { mutableStateOf(false) } + var remarks by rememberSaveable(editAssetId, initialRemarks) { mutableStateOf(initialRemarks) } + var url by rememberSaveable(editAssetId, initialUrl) { mutableStateOf(initialUrl) } + var showDeleteConfirm by rememberSaveable(editAssetId) { mutableStateOf(false) } Scaffold( contentWindowInsets = WindowInsets(0), @@ -171,6 +175,9 @@ fun UserAssetUrlScreen( modifier = Modifier .fillMaxSize() .padding(innerPadding) + .consumeWindowInsets(innerPadding) + .imePadding() + .verticalScroll(rememberScrollState()) .padding(vertical = 8.dp) ) { FormTextField(