From ec342077c578c71b04cfcd6cab3e86106d3befa4 Mon Sep 17 00:00:00 2001 From: David Gonzalez Date: Wed, 19 Aug 2026 23:57:51 +0200 Subject: [PATCH] Restore native input focus after attaching a file The attachment picker callbacks added the attachment to state but never returned focus or the keyboard to the input field, so the user had to tap the field again before they could send the message. Cancelling the picker left the same dead-focus state. Add restoreInputFocus() to NativeInputHost and call it from both picker callbacks in AttachmentView. The widget posts the request because picker results are delivered in onActivityResult, before the host activity resumes, and the IME ignores a show request until then. https://app.asana.com/1/137249556945/project/1157893581871903/task/1217314046325775 Co-Authored-By: Claude Opus 5 --- .../duckchat/impl/nativeinput/NativeInputPlugin.kt | 3 +++ .../duckchat/impl/ui/nativeinput/views/AttachmentView.kt | 2 ++ .../impl/ui/nativeinput/views/NativeInputModeWidget.kt | 9 +++++++++ 3 files changed, 14 insertions(+) diff --git a/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/nativeinput/NativeInputPlugin.kt b/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/nativeinput/NativeInputPlugin.kt index 0e2592e678cb..e3cfc71f20c0 100644 --- a/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/nativeinput/NativeInputPlugin.kt +++ b/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/nativeinput/NativeInputPlugin.kt @@ -38,6 +38,9 @@ interface NativeInputHost { fun showModelPicker(showing: Boolean) fun showReasoningPicker(showing: Boolean) + /** Return focus and the keyboard to the input field after a plugin handed control to another screen. */ + fun restoreInputFocus() + fun attachmentChanged(hasAttachments: Boolean, limitExceeded: Boolean, supportsUpload: Boolean) /** diff --git a/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/nativeinput/views/AttachmentView.kt b/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/nativeinput/views/AttachmentView.kt index 8872fbddac47..183a9f65195f 100644 --- a/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/nativeinput/views/AttachmentView.kt +++ b/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/nativeinput/views/AttachmentView.kt @@ -409,11 +409,13 @@ class AttachmentView( private fun buildImagePickerCallback(source: AttachmentViewModel.ImageSource): ValueCallback> = ValueCallback { uris -> val list = uris?.toList() if (!list.isNullOrEmpty()) viewModel?.onImagesPicked(list, source) + host?.restoreInputFocus() } private fun buildFilePickerCallback(): ValueCallback> = ValueCallback { uris -> val list = uris?.toList() if (!list.isNullOrEmpty()) viewModel?.onFilesPicked(list) + host?.restoreInputFocus() } } diff --git a/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/nativeinput/views/NativeInputModeWidget.kt b/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/nativeinput/views/NativeInputModeWidget.kt index 354cb557042b..6c0c35ac38d7 100644 --- a/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/nativeinput/views/NativeInputModeWidget.kt +++ b/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/nativeinput/views/NativeInputModeWidget.kt @@ -2044,6 +2044,15 @@ class NativeInputModeWidget @JvmOverloads constructor( onAttachmentChooserStateChanged?.invoke(showing) } + override fun restoreInputFocus() { + // Picker results are delivered in onActivityResult, before the host activity resumes, and the IME + // ignores a show request until then. Posting runs this once that transaction completes. + post { + requestInputFocus() + showKeyboard() + } + } + override fun attachmentChanged( hasAttachments: Boolean, limitExceeded: Boolean,