From 6400d33b87fe97753d064847549579c4a83cae89 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 a25d41d7..e5f7e330 100644 --- a/V2rayNG/app/src/main/AndroidManifest.xml +++ b/V2rayNG/app/src/main/AndroidManifest.xml @@ -157,6 +157,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(