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
This commit is contained in:
Blazebrain 2025-04-17 07:51:03 +01:00
parent b2d4698cdf
commit d9c01a5d07

View file

@ -38,6 +38,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
static const fourPinLength = 4; static const fourPinLength = 4;
final _gridViewKey = GlobalKey(); final _gridViewKey = GlobalKey();
final _key = GlobalKey<ScaffoldState>(); final _key = GlobalKey<ScaffoldState>();
late final FocusNode _focusNode;
int pinLength; int pinLength;
String pin; String pin;
@ -54,7 +55,17 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
pin = ''; pin = '';
title = S.current.enter_your_pin; title = S.current.enter_your_pin;
_aspectRatio = 0; _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); void setTitle(String title) => setState(() => this.title = title);
@ -120,8 +131,8 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
); );
return KeyboardListener( return KeyboardListener(
focusNode: FocusNode(), focusNode: _focusNode,
autofocus: true, autofocus: false,
onKeyEvent: (keyEvent) { onKeyEvent: (keyEvent) {
if (keyEvent is KeyDownEvent) { if (keyEvent is KeyDownEvent) {
if (keyEvent.logicalKey.keyLabel == "Backspace") { if (keyEvent.logicalKey.keyLabel == "Backspace") {
@ -144,8 +155,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
style: TextStyle( style: TextStyle(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)),
Theme.of(context).extension<CakeTextTheme>()!.titleColor)),
Spacer(flex: 8), Spacer(flex: 8),
Container( Container(
width: 180, width: 180,
@ -162,7 +172,9 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
shape: BoxShape.circle, shape: BoxShape.circle,
color: isFilled color: isFilled
? Theme.of(context).extension<CakeTextTheme>()!.titleColor ? Theme.of(context).extension<CakeTextTheme>()!.titleColor
: Theme.of(context).extension<PinCodeTheme>()!.indicatorsColor : Theme.of(context)
.extension<PinCodeTheme>()!
.indicatorsColor
.withOpacity(0.25), .withOpacity(0.25),
)); ));
}), }),
@ -225,7 +237,8 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
child: TextButton( child: TextButton(
onPressed: () => _pop(), onPressed: () => _pop(),
style: TextButton.styleFrom( style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.background, backgroundColor:
Theme.of(context).colorScheme.background,
shape: CircleBorder(), shape: CircleBorder(),
), ),
child: deleteIconImage, child: deleteIconImage,
@ -250,7 +263,9 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
style: TextStyle( style: TextStyle(
fontSize: 25.0, fontSize: 25.0,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)), color: Theme.of(context)
.extension<CakeTextTheme>()!
.titleColor)),
), ),
); );
}), }),