From c3fccc71533b9ce58c44aab43a6101618f9e60ca Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 28 Jul 2026 17:49:34 +0000 Subject: [PATCH] fix(ime): gate draft-saving editor back handlers behind KeyboardAwareBackHandler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to the chat composer fix. The native post/editor screens install the same pattern that stranded the IME insets: a BackHandler that saves a draft and pops the screen. When the keyboard is up and the user leaves with a predictive back gesture, the pop races (and cancels) the IME close animation, leaving WindowInsets.ime — every imePadding() in the app — stuck at the keyboard height on release builds. Route these through KeyboardAwareBackHandler so the system dismisses the keyboard first (clean animation) and the screen only pops once it is down: - ShortNotePostScreen - LongFormPostScreen - NewProductScreen - GenericCommentPostScreen - NewGoalScreen - NewWorkoutScreen - NewPublicMessageScreen - AwardBadgeScreen Left as plain BackHandler: handlers with no text field (VoiceReplyScreen), and handlers whose back does something other than pop a text-entry screen — WebView history (WebAppScreen, NostrAppScreen), in-browser navigation (GitCodeTab, GitCommitLog), drawer close (AccountSwitcherAndLeftDrawerLayout), and call/PiP (CallScreen, NestActivityContent) — where deferring to keyboard dismissal would change back semantics. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_012dT2RLbPZzan2hULL2cmc6 --- .../ui/note/nip22Comments/GenericCommentPostScreen.kt | 4 ++-- .../ui/screen/loggedIn/badges/award/AwardBadgeScreen.kt | 4 ++-- .../loggedIn/discover/nip23LongForm/LongFormPostScreen.kt | 4 ++-- .../loggedIn/discover/nip99Classifieds/NewProductScreen.kt | 4 ++-- .../amethyst/ui/screen/loggedIn/home/ShortNotePostScreen.kt | 4 ++-- .../ui/screen/loggedIn/home/nip75Goals/NewGoalScreen.kt | 4 ++-- .../notifications/publicMessages/NewPublicMessageScreen.kt | 4 ++-- .../amethyst/ui/screen/loggedIn/workouts/NewWorkoutScreen.kt | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/GenericCommentPostScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/GenericCommentPostScreen.kt index 6baef9f1a2..aec22cb911 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/GenericCommentPostScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/GenericCommentPostScreen.kt @@ -20,7 +20,6 @@ */ package com.vitorpamplona.amethyst.ui.note.nip22Comments -import androidx.activity.compose.BackHandler import androidx.compose.foundation.clickable import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Box @@ -67,6 +66,7 @@ import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia import com.vitorpamplona.amethyst.ui.actions.uploads.TakePictureButton import com.vitorpamplona.amethyst.ui.actions.uploads.TakeVideoButton +import com.vitorpamplona.amethyst.ui.navigation.bottombars.KeyboardAwareBackHandler import com.vitorpamplona.amethyst.ui.navigation.navs.Nav import com.vitorpamplona.amethyst.ui.navigation.topbars.PostingTopBar import com.vitorpamplona.amethyst.ui.note.BaseUserPicture @@ -177,7 +177,7 @@ fun GenericCommentPostScreen( StrippingFailureDialog(postViewModel.strippingFailureConfirmation) - BackHandler { + KeyboardAwareBackHandler { accountViewModel.launchSigner { postViewModel.sendDraftSync() postViewModel.cancel() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/badges/award/AwardBadgeScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/badges/award/AwardBadgeScreen.kt index 2172e18945..bdc768cc3c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/badges/award/AwardBadgeScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/badges/award/AwardBadgeScreen.kt @@ -20,7 +20,6 @@ */ package com.vitorpamplona.amethyst.ui.screen.loggedIn.badges.award -import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -52,6 +51,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.ui.components.Nip05OrPubkeyLine import com.vitorpamplona.amethyst.model.User +import com.vitorpamplona.amethyst.ui.navigation.bottombars.KeyboardAwareBackHandler import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.topbars.SavingTopBar import com.vitorpamplona.amethyst.ui.note.UserPicture @@ -88,7 +88,7 @@ fun AwardBadgeScreen( onDispose { userSuggestions.reset() } } - BackHandler { + KeyboardAwareBackHandler { nav.popBack() } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostScreen.kt index 2465929d40..12cba33c60 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostScreen.kt @@ -20,7 +20,6 @@ */ package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip23LongForm -import androidx.activity.compose.BackHandler import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.border import androidx.compose.foundation.clickable @@ -96,6 +95,7 @@ import com.vitorpamplona.amethyst.ui.actions.uploads.TakeVideoButton import com.vitorpamplona.amethyst.ui.components.MyAsyncImage import com.vitorpamplona.amethyst.ui.components.ThinPaddingTextField import com.vitorpamplona.amethyst.ui.components.markdown.RenderContentAsMarkdown +import com.vitorpamplona.amethyst.ui.navigation.bottombars.KeyboardAwareBackHandler import com.vitorpamplona.amethyst.ui.navigation.navs.Nav import com.vitorpamplona.amethyst.ui.navigation.topbars.PostingTopBar import com.vitorpamplona.amethyst.ui.note.creators.contentWarning.ContentSensitivityExplainer @@ -149,7 +149,7 @@ fun LongFormPostScreen( StrippingFailureDialog(postViewModel.strippingFailureConfirmation) - BackHandler { + KeyboardAwareBackHandler { accountViewModel.launchSigner { postViewModel.sendDraftSync() postViewModel.cancel() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductScreen.kt index 2e95142599..8cd67d7b46 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductScreen.kt @@ -20,7 +20,6 @@ */ package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip99Classifieds -import androidx.activity.compose.BackHandler import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -53,6 +52,7 @@ import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia import com.vitorpamplona.amethyst.ui.actions.uploads.TakePictureButton import com.vitorpamplona.amethyst.ui.actions.uploads.TakeVideoButton +import com.vitorpamplona.amethyst.ui.navigation.bottombars.KeyboardAwareBackHandler import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.Nav import com.vitorpamplona.amethyst.ui.navigation.topbars.PostingTopBar @@ -141,7 +141,7 @@ fun NewProductScreen( StrippingFailureDialog(postViewModel.strippingFailureConfirmation) - BackHandler { + KeyboardAwareBackHandler { accountViewModel.launchSigner { postViewModel.sendDraftSync() postViewModel.cancel() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostScreen.kt index db7e95f3be..a4bc2c6bfb 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostScreen.kt @@ -23,7 +23,6 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.home import android.annotation.SuppressLint import android.content.Intent import android.net.Uri -import androidx.activity.compose.BackHandler import androidx.compose.foundation.clickable import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Arrangement @@ -93,6 +92,7 @@ import com.vitorpamplona.amethyst.ui.actions.uploads.VoiceMessagePreview import com.vitorpamplona.amethyst.ui.components.OutlinedThinPaddingTextField import com.vitorpamplona.amethyst.ui.components.ThinPaddingTextField import com.vitorpamplona.amethyst.ui.components.getActivity +import com.vitorpamplona.amethyst.ui.navigation.bottombars.KeyboardAwareBackHandler import com.vitorpamplona.amethyst.ui.navigation.navs.Nav import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.navigation.topbars.PostingTopBar @@ -235,7 +235,7 @@ internal fun NewPostScreenInner( StrippingFailureDialog(postViewModel.strippingFailureConfirmation) - BackHandler { + KeyboardAwareBackHandler { accountViewModel.launchSigner { postViewModel.sendDraftSync() postViewModel.cancel() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/nip75Goals/NewGoalScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/nip75Goals/NewGoalScreen.kt index 5a6348cb6d..f7aabcd6f7 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/nip75Goals/NewGoalScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/nip75Goals/NewGoalScreen.kt @@ -20,7 +20,6 @@ */ package com.vitorpamplona.amethyst.ui.screen.loggedIn.home.nip75Goals -import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -48,6 +47,7 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.ui.navigation.bottombars.KeyboardAwareBackHandler import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.Nav import com.vitorpamplona.amethyst.ui.navigation.topbars.PostingTopBar @@ -81,7 +81,7 @@ fun NewGoalScreen( accountViewModel: AccountViewModel, nav: INav, ) { - BackHandler { + KeyboardAwareBackHandler { goalViewModel.cancel() nav.popBack() } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageScreen.kt index 56e1382b6a..f9e277665c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageScreen.kt @@ -20,7 +20,6 @@ */ package com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.publicMessages -import androidx.activity.compose.BackHandler import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy import androidx.compose.foundation.layout.Column @@ -64,6 +63,7 @@ import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery import com.vitorpamplona.amethyst.ui.actions.uploads.TakePictureButton import com.vitorpamplona.amethyst.ui.actions.uploads.TakeVideoButton import com.vitorpamplona.amethyst.ui.components.ThinPaddingTextField +import com.vitorpamplona.amethyst.ui.navigation.bottombars.KeyboardAwareBackHandler import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.Nav import com.vitorpamplona.amethyst.ui.navigation.topbars.PostingTopBar @@ -134,7 +134,7 @@ fun NewPublicMessageScreen( StrippingFailureDialog(postViewModel.strippingFailureConfirmation) - BackHandler { + KeyboardAwareBackHandler { accountViewModel.launchSigner { postViewModel.sendDraftSync() postViewModel.cancel() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/workouts/NewWorkoutScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/workouts/NewWorkoutScreen.kt index a3de2013d0..5bc98f4cdb 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/workouts/NewWorkoutScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/workouts/NewWorkoutScreen.kt @@ -20,7 +20,6 @@ */ package com.vitorpamplona.amethyst.ui.screen.loggedIn.workouts -import androidx.activity.compose.BackHandler import androidx.compose.animation.Crossfade import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -61,6 +60,7 @@ import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols +import com.vitorpamplona.amethyst.ui.navigation.bottombars.KeyboardAwareBackHandler import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.navigation.topbars.PostingTopBar @@ -80,7 +80,7 @@ fun NewWorkoutScreen( postViewModel.init(accountViewModel) postViewModel.prefill(prefill) - BackHandler { + KeyboardAwareBackHandler { postViewModel.cancel() nav.popBack() }