From d9c01a5d07c2ce44064c2e9f2191ab31e93995ad Mon Sep 17 00:00:00 2001 From: Blazebrain Date: Thu, 17 Apr 2025 07:51:03 +0100 Subject: [PATCH] fix(desktop-pin-code-issue): persist FocusNode so KeyboardListener works on macOS Previously, every rebuild created a new FocusNode, so KeyboardListener never held focus and missed key events on macOS. This change: - Moves the FocusNode into state and initializes it in initState - Requests focus once after the first frame - Disposes of the FocusNode in dispose - Removes the inline FocusNode creation from build --- lib/src/screens/pin_code/pin_code_widget.dart | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/lib/src/screens/pin_code/pin_code_widget.dart b/lib/src/screens/pin_code/pin_code_widget.dart index f6249576d..410349336 100644 --- a/lib/src/screens/pin_code/pin_code_widget.dart +++ b/lib/src/screens/pin_code/pin_code_widget.dart @@ -38,6 +38,7 @@ class PinCodeState extends State { static const fourPinLength = 4; final _gridViewKey = GlobalKey(); final _key = GlobalKey(); + late final FocusNode _focusNode; int pinLength; String pin; @@ -54,7 +55,17 @@ class PinCodeState extends State { pin = ''; title = S.current.enter_your_pin; _aspectRatio = 0; - WidgetsBinding.instance.addPostFrameCallback(_afterLayout); + _focusNode = FocusNode(); + WidgetsBinding.instance.addPostFrameCallback((_) { + _focusNode.requestFocus(); + _afterLayout(_); + }); + } + + @override + void dispose() { + _focusNode.dispose(); + super.dispose(); } void setTitle(String title) => setState(() => this.title = title); @@ -120,8 +131,8 @@ class PinCodeState extends State { ); return KeyboardListener( - focusNode: FocusNode(), - autofocus: true, + focusNode: _focusNode, + autofocus: false, onKeyEvent: (keyEvent) { if (keyEvent is KeyDownEvent) { if (keyEvent.logicalKey.keyLabel == "Backspace") { @@ -144,8 +155,7 @@ class PinCodeState extends State { style: TextStyle( fontSize: 20, fontWeight: FontWeight.w500, - color: - Theme.of(context).extension()!.titleColor)), + color: Theme.of(context).extension()!.titleColor)), Spacer(flex: 8), Container( width: 180, @@ -162,7 +172,9 @@ class PinCodeState extends State { shape: BoxShape.circle, color: isFilled ? Theme.of(context).extension()!.titleColor - : Theme.of(context).extension()!.indicatorsColor + : Theme.of(context) + .extension()! + .indicatorsColor .withOpacity(0.25), )); }), @@ -225,7 +237,8 @@ class PinCodeState extends State { child: TextButton( onPressed: () => _pop(), style: TextButton.styleFrom( - backgroundColor: Theme.of(context).colorScheme.background, + backgroundColor: + Theme.of(context).colorScheme.background, shape: CircleBorder(), ), child: deleteIconImage, @@ -250,7 +263,9 @@ class PinCodeState extends State { style: TextStyle( fontSize: 25.0, fontWeight: FontWeight.w600, - color: Theme.of(context).extension()!.titleColor)), + color: Theme.of(context) + .extension()! + .titleColor)), ), ); }),