Skip to content

[PM-28227] fix: Keep keyboard alive in autofillText mode via SwiftUI @FocusState anchor#2599

Draft
fedemkr wants to merge 4 commits intomainfrom
PM-28227/workaround-autofill-text-keyboard-always
Draft

[PM-28227] fix: Keep keyboard alive in autofillText mode via SwiftUI @FocusState anchor#2599
fedemkr wants to merge 4 commits intomainfrom
PM-28227/workaround-autofill-text-keyboard-always

Conversation

@fedemkr
Copy link
Copy Markdown
Member

@fedemkr fedemkr commented Apr 30, 2026

🎟️ Tracking

PM-28227

📔 Objective

Fixes the autofillText mode keyboard being dismissed (and the extension closing ~5 seconds later) when the user cancels an inline vault search.

In autofillText mode the extension is shown as a keyboard panel (InputUI) backed by a Remote Text Input (RTI) session. Any text field that becomes first responder via UIKit's explicit becomeFirstResponder() causes the RTI system to tag the session with delayEndInputSession:YES (fromBecomeFirstResponder:1), starting a ~5-second countdown that tears down the keyboard panel and dismisses the extension when it fires.

The previous approach used a UIKit KeyboardAnchorTextField and called becomeFirstResponder() on it when the search Cancel button was tapped — triggering exactly that timer. This PR replaces that path with a hidden SwiftUI TextField bound to a @FocusState enum (FocusableField.anchor / .search). SwiftUI's internal focus machinery uses fromBecomeFirstResponder:0delayEndInputSession:NO, so every focus handoff (including Cancel → anchor) is a clean RTI session continuation with no countdown timer.

As a secondary fix, .searchable / UISearchController is replaced with a custom inline search bar in autofillText mode, since UISearchController also calls explicit becomeFirstResponder() on resign.

📸 Screenshots

N/A — keyboard extension panel behaviour, no visual UI change.

fedemkr added 4 commits April 30, 2026 11:49
…chor in a workaround.

Replace the UIKit `KeyboardAnchorTextField.becomeFirstResponder()` call on
Cancel with a hidden SwiftUI `TextField` bound to a `@FocusState` enum.
UIKit's explicit `becomeFirstResponder()` produces `fromBecomeFirstResponder:1`
→ `delayEndInputSession:YES`, starting a ~5-second RTI countdown that
dismisses the extension. SwiftUI's focus machinery uses
`fromBecomeFirstResponder:0` → `delayEndInputSession:NO`, keeping the
keyboard panel alive indefinitely.
@github-actions github-actions Bot added app:password-manager Bitwarden Password Manager app context t:bug Change Type - Bug labels Apr 30, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 30, 2026

Codecov Report

❌ Patch coverage is 10.07752% with 116 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.15%. Comparing base (3ecf4ce) to head (d8c9a0e).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
...ult/Vault/AutofillList/VaultAutofillListView.swift 13.04% 60 Missing ⚠️
...llExtension/CredentialProviderViewController.swift 0.00% 56 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2599      +/-   ##
==========================================
- Coverage   87.20%   87.15%   -0.06%     
==========================================
  Files        1894     1895       +1     
  Lines      167519   167838     +319     
==========================================
+ Hits       146087   146279     +192     
- Misses      21432    21559     +127     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app:password-manager Bitwarden Password Manager app context t:bug Change Type - Bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant