TF-1544: Support can TAB another field in composer

(cherry picked from commit 38f24da4295f4e6231eb77af18b2181496ad78f8)
This commit is contained in:
HuyNguyen
2023-04-12 00:40:22 +07:00
committed by Dat Vu
parent b61d538b1a
commit 006d805304
3 changed files with 65 additions and 7 deletions
@@ -12,6 +12,7 @@ import 'package:filesize/filesize.dart';
import 'package:fk_user_agent/fk_user_agent.dart'; import 'package:fk_user_agent/fk_user_agent.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:http_parser/http_parser.dart'; import 'package:http_parser/http_parser.dart';
@@ -346,7 +347,15 @@ class ComposerController extends BaseController {
void createFocusNodeInput() { void createFocusNodeInput() {
toAddressFocusNode = FocusNode(); toAddressFocusNode = FocusNode();
subjectEmailInputFocusNode = FocusNode(); subjectEmailInputFocusNode = FocusNode(
onKey: (focus, event) {
if (event is RawKeyDownEvent && event.logicalKey == LogicalKeyboardKey.tab) {
richTextWebController.editorController.setFocus();
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
}
);
ccAddressFocusNode = FocusNode(); ccAddressFocusNode = FocusNode();
bccAddressFocusNode = FocusNode(); bccAddressFocusNode = FocusNode();
@@ -1198,9 +1207,11 @@ class ComposerController extends BaseController {
updateListEmailAddress(prefixEmailAddress, <EmailAddress>[]); updateListEmailAddress(prefixEmailAddress, <EmailAddress>[]);
switch(prefixEmailAddress) { switch(prefixEmailAddress) {
case PrefixEmailAddress.cc: case PrefixEmailAddress.cc:
ccAddressFocusNode = FocusNode();
ccEmailAddressController.clear(); ccEmailAddressController.clear();
break; break;
case PrefixEmailAddress.bcc: case PrefixEmailAddress.bcc:
bccAddressFocusNode = FocusNode();
bccEmailAddressController.clear(); bccEmailAddressController.clear();
break; break;
default: default:
@@ -1632,4 +1643,26 @@ class ComposerController extends BaseController {
Navigator.maybePop(context); Navigator.maybePop(context);
onEditorFocusChange(true); onEditorFocusChange(true);
} }
FocusNode? getNextFocusOfToEmailAddress() {
if (listEmailAddressType.contains(PrefixEmailAddress.cc) == true) {
return ccAddressFocusNode;
} else if (listEmailAddressType.contains(PrefixEmailAddress.bcc) == true) {
return bccAddressFocusNode;
} else {
return subjectEmailInputFocusNode;
}
}
FocusNode? getNextFocusOfCcEmailAddress() {
if (listEmailAddressType.contains(PrefixEmailAddress.bcc) == true) {
return bccAddressFocusNode;
} else {
return subjectEmailInputFocusNode;
}
}
void handleFocusNextAddressAction() {
_autoCreateEmailTag();
}
} }
@@ -579,13 +579,15 @@ class ComposerView extends GetWidget<ComposerController>
focusNode: controller.toAddressFocusNode, focusNode: controller.toAddressFocusNode,
autoDisposeFocusNode: false, autoDisposeFocusNode: false,
isInitial: controller.isInitialRecipient.value, isInitial: controller.isInitialRecipient.value,
keyTagEditor: controller.keyToEmailTagEditor keyTagEditor: controller.keyToEmailTagEditor,
nextFocusNode: controller.getNextFocusOfToEmailAddress()
) )
..addOnFocusEmailAddressChangeAction((prefixEmailAddress, focus) => controller.onEmailAddressFocusChange(prefixEmailAddress, focus)) ..addOnFocusEmailAddressChangeAction((prefixEmailAddress, focus) => controller.onEmailAddressFocusChange(prefixEmailAddress, focus))
..addOnShowFullListEmailAddressAction((prefixEmailAddress) => controller.showFullEmailAddress(prefixEmailAddress)) ..addOnShowFullListEmailAddressAction((prefixEmailAddress) => controller.showFullEmailAddress(prefixEmailAddress))
..addOnAddEmailAddressTypeAction((prefixEmailAddress) => controller.addEmailAddressType(prefixEmailAddress)) ..addOnAddEmailAddressTypeAction((prefixEmailAddress) => controller.addEmailAddressType(prefixEmailAddress))
..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress)) ..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress))
..addOnSuggestionEmailAddress(controller.getAutoCompleteSuggestion)) ..addOnSuggestionEmailAddress(controller.getAutoCompleteSuggestion)
..addOnFocusNextAddressAction(controller.handleFocusNextAddressAction))
.build() .build()
)), )),
Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.cc) == true Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.cc) == true
@@ -604,13 +606,16 @@ class ComposerView extends GetWidget<ComposerController>
expandMode: controller.ccAddressExpandMode.value, expandMode: controller.ccAddressExpandMode.value,
controller: controller.ccEmailAddressController, controller: controller.ccEmailAddressController,
isInitial: controller.isInitialRecipient.value, isInitial: controller.isInitialRecipient.value,
keyTagEditor: controller.keyCcEmailTagEditor keyTagEditor: controller.keyCcEmailTagEditor,
focusNode: controller.ccAddressFocusNode,
nextFocusNode: controller.getNextFocusOfCcEmailAddress()
) )
..addOnFocusEmailAddressChangeAction((prefixEmailAddress, focus) => controller.onEmailAddressFocusChange(prefixEmailAddress, focus)) ..addOnFocusEmailAddressChangeAction((prefixEmailAddress, focus) => controller.onEmailAddressFocusChange(prefixEmailAddress, focus))
..addOnShowFullListEmailAddressAction((prefixEmailAddress) => controller.showFullEmailAddress(prefixEmailAddress)) ..addOnShowFullListEmailAddressAction((prefixEmailAddress) => controller.showFullEmailAddress(prefixEmailAddress))
..addOnDeleteEmailAddressTypeAction((prefixEmailAddress) => controller.deleteEmailAddressType(prefixEmailAddress)) ..addOnDeleteEmailAddressTypeAction((prefixEmailAddress) => controller.deleteEmailAddressType(prefixEmailAddress))
..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress)) ..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress))
..addOnSuggestionEmailAddress(controller.getAutoCompleteSuggestion)) ..addOnSuggestionEmailAddress(controller.getAutoCompleteSuggestion)
..addOnFocusNextAddressAction(controller.handleFocusNextAddressAction))
.build()) .build())
: const SizedBox.shrink() : const SizedBox.shrink()
), ),
@@ -630,13 +635,16 @@ class ComposerView extends GetWidget<ComposerController>
expandMode: controller.bccAddressExpandMode.value, expandMode: controller.bccAddressExpandMode.value,
controller: controller.bccEmailAddressController, controller: controller.bccEmailAddressController,
isInitial: controller.isInitialRecipient.value, isInitial: controller.isInitialRecipient.value,
keyTagEditor: controller.keyBccEmailTagEditor keyTagEditor: controller.keyBccEmailTagEditor,
focusNode: controller.bccAddressFocusNode,
nextFocusNode: controller.subjectEmailInputFocusNode
) )
..addOnFocusEmailAddressChangeAction((prefixEmailAddress, focus) => controller.onEmailAddressFocusChange(prefixEmailAddress, focus)) ..addOnFocusEmailAddressChangeAction((prefixEmailAddress, focus) => controller.onEmailAddressFocusChange(prefixEmailAddress, focus))
..addOnShowFullListEmailAddressAction((prefixEmailAddress) => controller.showFullEmailAddress(prefixEmailAddress)) ..addOnShowFullListEmailAddressAction((prefixEmailAddress) => controller.showFullEmailAddress(prefixEmailAddress))
..addOnDeleteEmailAddressTypeAction((prefixEmailAddress) => controller.deleteEmailAddressType(prefixEmailAddress)) ..addOnDeleteEmailAddressTypeAction((prefixEmailAddress) => controller.deleteEmailAddressType(prefixEmailAddress))
..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress)) ..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress))
..addOnSuggestionEmailAddress(controller.getAutoCompleteSuggestion)) ..addOnSuggestionEmailAddress(controller.getAutoCompleteSuggestion)
..addOnFocusNextAddressAction(controller.handleFocusNextAddressAction))
.build()) .build())
: const SizedBox.shrink() : const SizedBox.shrink()
), ),
@@ -5,6 +5,7 @@ import 'package:collection/collection.dart';
import 'package:core/core.dart'; import 'package:core/core.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.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';
@@ -21,6 +22,7 @@ typedef OnAddEmailAddressTypeAction = void Function(PrefixEmailAddress);
typedef OnDeleteEmailAddressTypeAction = void Function(PrefixEmailAddress); typedef OnDeleteEmailAddressTypeAction = void Function(PrefixEmailAddress);
typedef OnShowFullListEmailAddressAction = void Function(PrefixEmailAddress); typedef OnShowFullListEmailAddressAction = void Function(PrefixEmailAddress);
typedef OnFocusEmailAddressChangeAction = void Function(PrefixEmailAddress, bool); typedef OnFocusEmailAddressChangeAction = void Function(PrefixEmailAddress, bool);
typedef OnFocusNextAddressAction = void Function();
class EmailAddressInputBuilder { class EmailAddressInputBuilder {
@@ -35,6 +37,7 @@ class EmailAddressInputBuilder {
final FocusNode? focusNode; final FocusNode? focusNode;
final bool autoDisposeFocusNode; final bool autoDisposeFocusNode;
final GlobalKey? keyTagEditor; final GlobalKey? keyTagEditor;
final FocusNode? nextFocusNode;
List<EmailAddress> listEmailAddress = <EmailAddress>[]; List<EmailAddress> listEmailAddress = <EmailAddress>[];
@@ -44,6 +47,7 @@ class EmailAddressInputBuilder {
OnDeleteEmailAddressTypeAction? _onDeleteEmailAddressTypeAction; OnDeleteEmailAddressTypeAction? _onDeleteEmailAddressTypeAction;
OnShowFullListEmailAddressAction? _onShowFullListEmailAddressAction; OnShowFullListEmailAddressAction? _onShowFullListEmailAddressAction;
OnFocusEmailAddressChangeAction? _onFocusEmailAddressChangeAction; OnFocusEmailAddressChangeAction? _onFocusEmailAddressChangeAction;
OnFocusNextAddressAction? _onFocusNextAddressAction;
Timer? _gapBetweenTagChangedAndFindSuggestion; Timer? _gapBetweenTagChangedAndFindSuggestion;
bool lastTagFocused = false; bool lastTagFocused = false;
@@ -72,6 +76,10 @@ class EmailAddressInputBuilder {
_onFocusEmailAddressChangeAction = onFocusEmailAddressChangeAction; _onFocusEmailAddressChangeAction = onFocusEmailAddressChangeAction;
} }
void addOnFocusNextAddressAction(OnFocusNextAddressAction onFocusNextAddressAction) {
_onFocusNextAddressAction = onFocusNextAddressAction;
}
EmailAddressInputBuilder( EmailAddressInputBuilder(
this._context, this._context,
this._imagePaths, this._imagePaths,
@@ -85,6 +93,7 @@ class EmailAddressInputBuilder {
this.autoDisposeFocusNode = true, this.autoDisposeFocusNode = true,
this.expandMode = ExpandMode.EXPAND, this.expandMode = ExpandMode.EXPAND,
this.keyTagEditor, this.keyTagEditor,
this.nextFocusNode,
} }
); );
@@ -132,6 +141,14 @@ class EmailAddressInputBuilder {
final newListEmailAddress = _isCollapse ? listEmailAddress.sublist(0, 1) : listEmailAddress; final newListEmailAddress = _isCollapse ? listEmailAddress.sublist(0, 1) : listEmailAddress;
return FocusScope(child: Focus( return FocusScope(child: Focus(
onFocusChange: (focus) => _onFocusEmailAddressChangeAction?.call(_prefixEmailAddress, focus), onFocusChange: (focus) => _onFocusEmailAddressChangeAction?.call(_prefixEmailAddress, focus),
onKey: (focusNode, event) {
if (event is RawKeyDownEvent && event.logicalKey == LogicalKeyboardKey.tab) {
nextFocusNode?.requestFocus();
_onFocusNextAddressAction?.call();
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
},
child: TagEditor<SuggestionEmailAddress>( child: TagEditor<SuggestionEmailAddress>(
key: keyTagEditor, key: keyTagEditor,
length: newListEmailAddress.length, length: newListEmailAddress.length,