Files
chanora/apps
EdisonJwa 79f83604da fix(ui,ios): apply community workaround for flutter/flutter#181474 (iOS 26 keyboard stale-focus)
User reported: 'input field still need to click twice' on iPhone +
'a bit lag after keyboard pop up'. The previous Listener-based
approach (020be77 \u2192 23bd1c7) actively made both symptoms worse.

Root cause is a confirmed open Flutter framework bug:

  flutter/flutter#181474 \u2014 [iPadOS] Keyboard is dismissed, but the
  TextField keeps focus, causing subsequent taps not to trigger
  keyboard presentation.
  Open, P2, triaged-text-input, platform-ios, e: OS-version specific.
  Reported on iPadOS 26.2 + Flutter 3.38.1 in Jan 2026 by
  Crazymuyang.

Reproduction matches our symptom exactly: iOS 26 dismisses the soft
keyboard (e.g. on tap-outside, or in some fresh-launch states), but
the EditableText's FocusNode keeps hasFocus = true. Because the
node is already focused, the next user tap is a no-op from the
focus system's perspective, so the platform TextInput channel is
never re-opened and iOS keeps the soft keyboard hidden until a
second tap finally triggers an explicit re-focus path.

Why our previous attempts failed:

  * 020be77 wrapped each TextField in a Listener that called
    requestFocus pre-arena. That's racing the wrong layer \u2014 it
    doesn't help when the bug is 'node is already focused, so
    requestFocus is a no-op'.

  * 23bd1c7 added SystemChannels.textInput.invokeMethod('TextInput.show')
    to the same Listener. This forced the keyboard up but raced
    EditableText's own attach path, producing the post-attach
    typing lag the user reported.

Fix: the community-recommended workaround in the issue thread \u2014
on every TextField tap, **unfocus first, then re-request focus on
the next microtask**. This forces a real false\u2192true focus-change
transition that re-opens TextInput on the first tap. No platform
channel races, no gesture-arena fighting, no Listener wrappers.

  void _kickFocus(FocusNode node) {
    if (node.hasFocus) node.unfocus();
    Future.microtask(() {
      if (!mounted) return;
      node.requestFocus();
    });
  }

  TextField(
    onTap: () => _kickFocus(_hostFocus),
    ...
  )

Wired into all three connect-form fields (host / nickname /
password). Removed the now-redundant _focusOnTap Listener helper.

No-op on hosts where #181474 doesn't reproduce \u2014 the unfocus call
is a no-op when the node isn't focused, and the microtask
requestFocus is what TextField would have done anyway via its own
TapGestureRecognizer.

flutter analyze: 6 pre-existing Radio.groupValue deprecation infos
in voice_settings.dart (unchanged). flutter build ios --release
--no-codesign: 27.6 s, Runner.app 30.2 MB.
2026-05-16 18:31:48 +08:00
..