TF-4011 Support Tab shortcut key to switch focus between tag & input field

This commit is contained in:
dab246
2025-11-04 11:38:59 +07:00
committed by Dat H. Pham
parent c479d47da8
commit 35fa43ed6b
4 changed files with 787 additions and 725 deletions
@@ -1,6 +1,7 @@
import 'package:core/presentation/views/responsive/responsive_widget.dart'; import 'package:core/presentation/views/responsive/responsive_widget.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:model/email/prefix_email_address.dart'; import 'package:model/email/prefix_email_address.dart';
@@ -73,7 +74,19 @@ class ComposerView extends GetWidget<ComposerController> {
responsiveUtils: controller.responsiveUtils, responsiveUtils: controller.responsiveUtils,
mobile: MobileResponsiveContainerView( mobile: MobileResponsiveContainerView(
childBuilder: (_, constraints) { childBuilder: (_, constraints) {
return GestureDetector( return Shortcuts(
shortcuts: {
LogicalKeySet(LogicalKeyboardKey.tab):
const DoNothingAndStopPropagationIntent(),
},
child: Actions(
actions: {
DoNothingAndStopPropagationIntent:
CallbackAction<DoNothingAndStopPropagationIntent>(
onInvoke: (_) => null
),
},
child: GestureDetector(
onTap: controller.clickOutsideComposer, onTap: controller.clickOutsideComposer,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -315,12 +328,26 @@ class ComposerView extends GetWidget<ComposerController> {
), ),
] ]
), ),
),
),
); );
} }
), ),
desktop: Obx(() => DesktopResponsiveContainerView( desktop: Obx(() => DesktopResponsiveContainerView(
childBuilder: (_, constraints) { childBuilder: (_, constraints) {
return GestureDetector( return Shortcuts(
shortcuts: {
LogicalKeySet(LogicalKeyboardKey.tab):
const DoNothingAndStopPropagationIntent(),
},
child: Actions(
actions: {
DoNothingAndStopPropagationIntent:
CallbackAction<DoNothingAndStopPropagationIntent>(
onInvoke: (_) => null
),
},
child: GestureDetector(
onTap: controller.clickOutsideComposer, onTap: controller.clickOutsideComposer,
child: Column(children: [ child: Column(children: [
Obx(() => DesktopAppBarComposerWidget( Obx(() => DesktopAppBarComposerWidget(
@@ -579,6 +606,8 @@ class ComposerView extends GetWidget<ComposerController> {
), ),
), ),
]), ]),
),
),
); );
}, },
composerManager: controller.mailboxDashBoardController.composerManager, composerManager: controller.mailboxDashBoardController.composerManager,
@@ -591,7 +620,19 @@ class ComposerView extends GetWidget<ComposerController> {
)), )),
tablet: TabletResponsiveContainerView( tablet: TabletResponsiveContainerView(
childBuilder: (_, constraints) { childBuilder: (_, constraints) {
return GestureDetector( return Shortcuts(
shortcuts: {
LogicalKeySet(LogicalKeyboardKey.tab):
const DoNothingAndStopPropagationIntent(),
},
child: Actions(
actions: {
DoNothingAndStopPropagationIntent:
CallbackAction<DoNothingAndStopPropagationIntent>(
onInvoke: (_) => null
),
},
child: GestureDetector(
onTap: controller.clickOutsideComposer, onTap: controller.clickOutsideComposer,
child: Column(children: [ child: Column(children: [
Obx(() => DesktopAppBarComposerWidget( Obx(() => DesktopAppBarComposerWidget(
@@ -845,6 +886,8 @@ class ComposerView extends GetWidget<ComposerController> {
), ),
) )
]), ]),
),
),
); );
}, },
) )
@@ -134,6 +134,9 @@ class _RecipientComposerWidgetState extends State<RecipientComposerWidget> {
void initState() { void initState() {
super.initState(); super.initState();
_currentListEmailAddress = widget.listEmailAddress; _currentListEmailAddress = widget.listEmailAddress;
if (PlatformInfo.isWeb) {
widget.focusNodeKeyboard?.addListener(_onFocusKeyboardListener);
}
} }
@override @override
@@ -144,6 +147,20 @@ class _RecipientComposerWidgetState extends State<RecipientComposerWidget> {
} }
} }
@override
void dispose() {
if (PlatformInfo.isWeb) {
widget.focusNodeKeyboard?.removeListener(_onFocusKeyboardListener);
}
super.dispose();
}
void _onFocusKeyboardListener() {
if (widget.focusNodeKeyboard?.hasFocus != true && mounted) {
setState(() => _tagIndexFocused = -1);
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
bool isMobileResponsive = _responsiveUtils.isMobile(context); bool isMobileResponsive = _responsiveUtils.isMobile(context);
@@ -406,7 +423,9 @@ class _RecipientComposerWidgetState extends State<RecipientComposerWidget> {
} }
KeyEventResult _recipientInputOnKeyListener(FocusNode node, KeyEvent event) { KeyEventResult _recipientInputOnKeyListener(FocusNode node, KeyEvent event) {
if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.tab) { if (widget.focusNode?.hasFocus == true &&
event is KeyDownEvent &&
event.logicalKey == LogicalKeyboardKey.tab) {
widget.nextFocusNode?.requestFocus(); widget.nextFocusNode?.requestFocus();
widget.onFocusNextAddressAction?.call(); widget.onFocusNextAddressAction?.call();
return KeyEventResult.handled; return KeyEventResult.handled;
+2 -2
View File
@@ -2170,10 +2170,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: super_tag_editor name: super_tag_editor
sha256: "83823674fa1048eb0411d169c9072028fa80ba6998ef18b357c29f58b835ea75" sha256: "7f7c1cb38e98e9cfa92fb074d4d5f5f53846d6bffcc96e05cb2191c159dba28d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.4.1" version: "1.1.0"
syncfusion_flutter_core: syncfusion_flutter_core:
dependency: transitive dependency: transitive
description: description:
+1 -1
View File
@@ -110,7 +110,7 @@ dependencies:
ref: master ref: master
### Dependencies from pub.dev ### ### Dependencies from pub.dev ###
super_tag_editor: 0.4.1 super_tag_editor: 1.1.0
external_app_launcher: 4.0.3 external_app_launcher: 4.0.3