TF-282 Fix bug email address is cut off when displaying on the mobile app

This commit is contained in:
dab246
2022-03-01 16:52:22 +07:00
committed by Dat H. Pham
parent 7a9be7aac2
commit 977e791bab
10 changed files with 260 additions and 166 deletions
@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.12" d="M12 24C18.6274 24 24 18.6274 24 12C24 5.37258 18.6274 0 12 0C5.37258 0 0 5.37258 0 12C0 18.6274 5.37258 24 12 24Z" fill="#818C99"/>
<path d="M16.7364 7.2636C17.0879 7.61508 17.0879 8.18492 16.7364 8.5364L13.273 12L16.7364 15.4636C17.0586 15.7858 17.0854 16.2915 16.817 16.6442L16.7364 16.7364C16.3849 17.0879 15.8151 17.0879 15.4636 16.7364L12 13.273L8.5364 16.7364C8.18492 17.0879 7.61508 17.0879 7.2636 16.7364C6.91213 16.3849 6.91213 15.8151 7.2636 15.4636L10.727 12L7.2636 8.5364C6.94142 8.21421 6.91457 7.70853 7.18306 7.35577L7.2636 7.2636C7.61508 6.91213 8.18492 6.91213 8.5364 7.2636L12 10.727L15.4636 7.2636C15.8151 6.91213 16.3849 6.91213 16.7364 7.2636Z" fill="#007AFF"/>
</svg>

After

Width:  |  Height:  |  Size: 810 B

@@ -49,9 +49,9 @@ extension AppColor on Color {
static const subjectEmailTextColorUnRead = Color(0xFF3840F7);
static const dividerColor = Color(0xFFEAEAEA);
static const bgComposer = Color(0xFFFBFBFF);
static const emailAddressChipColor = Color(0xFFF5F5F7);
static const enableSendEmailButtonColor = Color(0xFF3840F7);
static const disableSendEmailButtonColor = Color(0xFFACAFFF);
static const emailAddressChipColor = Color(0x0D001C3D);
static const enableSendEmailButtonColor = Color(0xFF007AFF);
static const disableSendEmailButtonColor = Color(0xFFA9B4C2);
static const borderLeftEmailContentColor = Color(0xFFEFEFEF);
static const toastBackgroundColor = Color(0xFFACAFFF);
static const toastSuccessBackgroundColor = Color(0xFF04AA11);
@@ -85,6 +85,9 @@ extension AppColor on Color {
static const colorActionCancelDialog= Color(0xFF007AFF);
static const colorMessageDialog= Color(0xFF222222);
static const colorConfirmActionDialog= Color(0xFFF2F2F2);
static const colorEmailAddress = Color(0xFF333333);
static const colorHintEmailAddressInput = Color(0x993C3C43);
static const coloDividerComposer = Color(0xFFC6C6C8);
static const mapGradientColor = [
[Color(0xFF21D4FD), Color(0xFFB721FF)],
@@ -84,6 +84,7 @@ class ImagePaths {
String get icRenameMailbox => _getImagePath('ic_rename_mailbox.svg');
String get icDeleteToast => _getImagePath('ic_delete_toast.svg');
String get icRemoveDialog => _getImagePath('ic_remove_dialog.svg');
String get icDeleteEmailAddress => _getImagePath('ic_delete_email_address.svg');
String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
@@ -9,7 +9,6 @@ import 'package:file_picker/file_picker.dart';
import 'package:fk_user_agent/fk_user_agent.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_chips_input/flutter_chips_input.dart';
import 'package:get/get.dart';
import 'package:html_editor_enhanced/html_editor.dart' as HtmlEditorBrowser;
import 'package:http_parser/http_parser.dart';
@@ -54,6 +53,7 @@ class ComposerController extends BaseController {
final expandMode = ExpandMode.COLLAPSE.obs;
final composerArguments = Rxn<ComposerArguments>();
final isEnableEmailSendButton = false.obs;
final isInitialRecipient = false.obs;
final attachments = <Attachment>[].obs;
final emailContents = <EmailContent>[].obs;
@@ -79,9 +79,10 @@ class ComposerController extends BaseController {
ContactSuggestionSource _contactSuggestionSource = ContactSuggestionSource.localContact;
HtmlEditorApi? htmlEditorApi;
final HtmlEditorBrowser.HtmlEditorController htmlControllerBrowser = HtmlEditorBrowser.HtmlEditorController();
final keyToEmailAddress = GlobalKey<ChipsInputState>();
final keyCcEmailAddress = GlobalKey<ChipsInputState>();
final keyBccEmailAddress = GlobalKey<ChipsInputState>();
final toEmailAddressController = TextEditingController();
final ccEmailAddressController = TextEditingController();
final bccEmailAddressController = TextEditingController();
List<Attachment> initialAttachments = <Attachment>[];
@@ -132,6 +133,18 @@ class ComposerController extends BaseController {
Future.delayed(Duration(milliseconds: 500), () => _checkContactPermission());
}
@override
void onClose() {
subjectEmailInputController.dispose();
toEmailAddressController.dispose();
ccEmailAddressController.dispose();
bccEmailAddressController.dispose();
htmlControllerBrowser.clearFocus();
super.onClose();
}
@override
void onDone() {
viewState.value.fold(
@@ -238,16 +251,8 @@ class ComposerController extends BaseController {
expandMode.value = ExpandMode.COLLAPSE;
}
if (listToEmailAddress.isNotEmpty) {
keyToEmailAddress.currentState?.addMultipleValue(listToEmailAddress);
}
if (listCcEmailAddress.isNotEmpty) {
keyCcEmailAddress.currentState?.addMultipleValue(listCcEmailAddress);
}
if (listBccEmailAddress.isNotEmpty) {
keyBccEmailAddress.currentState?.addMultipleValue(listBccEmailAddress);
if (listToEmailAddress.isNotEmpty || listCcEmailAddress.isNotEmpty || listBccEmailAddress.isNotEmpty) {
isInitialRecipient.value = true;
}
}
_updateStatusEmailSendButton();
@@ -18,6 +18,7 @@ class ComposerView extends GetWidget<ComposerController> {
final responsiveUtils = Get.find<ResponsiveUtils>();
final imagePaths = Get.find<ImagePaths>();
final _appToast = Get.find<AppToast>();
final keyboardUtils = Get.find<KeyboardUtils>();
@override
@@ -39,6 +40,7 @@ class ComposerView extends GetWidget<ComposerController> {
left: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context),
child: Container(
margin: EdgeInsets.zero,
padding: EdgeInsets.zero,
alignment: Alignment.topCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
@@ -106,19 +108,26 @@ class ComposerView extends GetWidget<ComposerController> {
return Container(
margin: EdgeInsets.zero,
padding: EdgeInsets.only(top: 20),
color: AppColor.bgComposer,
color: Colors.white,
alignment: Alignment.topCenter,
child: Column(
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 24),
padding: EdgeInsets.only(left: 16),
child: _buildEmailAddress(context)),
_buildDivider(),
_buildSubjectEmail(context),
Divider(color: AppColor.dividerColor, height: 1)
_buildDivider(),
],
),
);
}
Widget _buildDivider(){
return Padding(
padding: EdgeInsets.only(left: 16),
child: Divider(color: AppColor.coloDividerComposer, height: 1));
}
Widget _buildEmailAddress(BuildContext context) {
return Column(
@@ -126,7 +135,7 @@ class ComposerView extends GetWidget<ComposerController> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(bottom: 8),
padding: EdgeInsets.only(bottom: 12),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -136,7 +145,7 @@ class ComposerView extends GetWidget<ComposerController> {
'${AppLocalizations.of(context).from_email_address_prefix}:',
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(fontSize: 14, color: AppColor.nameUserColor, fontWeight: FontWeight.w500))),
style: TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput))),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
@@ -145,7 +154,7 @@ class ComposerView extends GetWidget<ComposerController> {
Obx(() => controller.composerArguments.value != null
? Text(
'<${controller.getEmailAddressSender()}>',
style: TextStyle(fontSize: 14, color: AppColor.nameUserColor))
style: TextStyle(fontSize: 14, color: AppColor.colorEmailAddress, fontWeight: FontWeight.w500))
: SizedBox.shrink()
)
],
@@ -154,37 +163,50 @@ class ComposerView extends GetWidget<ComposerController> {
]
)
),
Divider(color: AppColor.coloDividerComposer, height: 1),
Obx(() => (EmailAddressInputBuilder(
context,
imagePaths,
_appToast,
PrefixEmailAddress.to,
controller.listToEmailAddress,
keyInput: controller.keyToEmailAddress,
controller: controller.toEmailAddressController,
isInitial: controller.isInitialRecipient.value,
expandMode: controller.expandMode.value)
..addExpandAddressActionClick(() => controller.expandEmailAddressAction())
..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress))
..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word)))
.build()
),
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
? Divider(color: AppColor.coloDividerComposer, height: 1)
: SizedBox.shrink()),
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
? (EmailAddressInputBuilder(
context,
imagePaths,
_appToast,
PrefixEmailAddress.cc,
controller.listCcEmailAddress,
keyInput: controller.keyCcEmailAddress)
controller: controller.ccEmailAddressController,
isInitial: controller.isInitialRecipient.value,)
..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress))
..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word)))
.build()
: SizedBox.shrink()
),
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
? Divider(color: AppColor.coloDividerComposer, height: 1)
: SizedBox.shrink()),
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
? (EmailAddressInputBuilder(
context,
imagePaths,
_appToast,
PrefixEmailAddress.bcc,
controller.listBccEmailAddress,
keyInput: controller.keyBccEmailAddress)
controller: controller.bccEmailAddressController,
isInitial: controller.isInitialRecipient.value,)
..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress))
..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word)))
.build()
@@ -196,22 +218,34 @@ class ComposerView extends GetWidget<ComposerController> {
Widget _buildSubjectEmail(BuildContext context) {
return Padding(
padding: EdgeInsets.only(left: 24, right: 24, bottom: 10, top: 8),
child: (TextFieldBuilder()
..key(Key('subject_email_input'))
..textInputAction(TextInputAction.newline)
..maxLines(null)
..onChange((value) => controller.setSubjectEmail(value))
..textStyle(TextStyle(color: AppColor.nameUserColor, fontSize: 14, fontWeight: FontWeight.w500))
..textDecoration(InputDecoration(
hintText: AppLocalizations.of(context).subject_email,
hintStyle: TextStyle(color: AppColor.baseTextColor, fontSize: 14, fontWeight: FontWeight.w500),
contentPadding: EdgeInsets.zero,
filled: true,
border: InputBorder.none,
fillColor: AppColor.bgComposer))
..addController(controller.subjectEmailInputController))
.build()
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(right: 8),
child: Text(
'${AppLocalizations.of(context).subject_email}:',
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput))),
Expanded(
child: (TextFieldBuilder()
..key(Key('subject_email_input'))
..textInputAction(TextInputAction.newline)
..maxLines(null)
..cursorColor(AppColor.colorTextButton)
..onChange((value) => controller.setSubjectEmail(value))
..textStyle(TextStyle(color: AppColor.colorEmailAddress, fontSize: 15))
..textDecoration(InputDecoration(
contentPadding: EdgeInsets.zero,
border: InputBorder.none))
..addController(controller.subjectEmailInputController))
.build()
)
]
)
);
}
@@ -222,7 +256,7 @@ class ComposerView extends GetWidget<ComposerController> {
children: [
_buildEmailHeader(context),
Container(
color: AppColor.primaryLightColor,
color: Colors.white,
margin: EdgeInsets.zero,
padding: EdgeInsets.zero,
alignment: Alignment.topCenter,
@@ -1,29 +1,31 @@
import 'dart:async';
import 'package:core/core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_chips_input/flutter_chips_input.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:material_tag_editor/tag_editor.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/prefix_email_address_extension.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
typedef OnOpenExpandAddressActionClick = void Function();
typedef OnSuggestionEmailAddress = Future<List<EmailAddress>> Function(String word);
typedef OnUpdateListEmailAddressAction = void Function(
PrefixEmailAddress prefixEmailAddress,
List<EmailAddress> listEmailAddress
);
typedef OnUpdateListEmailAddressAction = void Function(PrefixEmailAddress, List<EmailAddress>);
class EmailAddressInputBuilder {
final Key? keyInput;
final BuildContext _context;
final ImagePaths _imagePaths;
final AppToast _appToast;
final ExpandMode expandMode;
final PrefixEmailAddress _prefixEmailAddress;
final List<EmailAddress> _listEmailAddress;
final TextEditingController? controller;
final bool? isInitial;
OnOpenExpandAddressActionClick? _onOpenExpandAddressActionClick;
OnUpdateListEmailAddressAction? _onUpdateListEmailAddressAction;
@@ -44,119 +46,135 @@ class EmailAddressInputBuilder {
EmailAddressInputBuilder(
this._context,
this._imagePaths,
this._appToast,
this._prefixEmailAddress,
this._listEmailAddress,
{
this.keyInput,
this.isInitial,
this.controller,
this.expandMode = ExpandMode.COLLAPSE,
}
);
Widget build() {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(right: 8, top: 15),
child: Text(
'${_prefixEmailAddress.asName(_context)}:',
style: TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput))),
Expanded(child: _buildTagEditor()),
if (_prefixEmailAddress == PrefixEmailAddress.to)
Padding(
padding: EdgeInsets.only(right: 8, top: _listEmailAddress.isNotEmpty ? 20 : 18),
child: Text(
'${_prefixEmailAddress.asName(_context)}:',
style: TextStyle(fontSize: 14, color: AppColor.nameUserColor, fontWeight: FontWeight.w500))),
Expanded(child: ChipsInput<EmailAddress>(
key: keyInput,
initialValue: _listEmailAddress,
textStyle: TextStyle(color: AppColor.nameUserColor, fontSize: 14, fontWeight: FontWeight.w500),
cursorColor: AppColor.primaryColor,
inputType: TextInputType.emailAddress,
decoration: InputDecoration(
border: InputBorder.none,
hintText: AppLocalizations.of(_context).hint_text_email_address,
hintMaxLines: 1,
hintStyle: TextStyle(color: AppColor.baseTextColor, fontSize: 14, fontWeight: FontWeight.w500)),
findSuggestions: (query) {
if (query.isNotEmpty && _onSuggestionEmailAddress != null) {
return _onSuggestionEmailAddress!(query);
}
return [];
},
onChanged: (data) {
if (_onUpdateListEmailAddressAction != null) {
_onUpdateListEmailAddressAction!(_prefixEmailAddress, data);
}
},
onChipInputActionDone: (state, value) {
if (GetUtils.isEmail(value)) {
state.selectSuggestion(EmailAddress(value, value));
}
},
onChipInputChangeFocusAction: (state, value) {
if (GetUtils.isEmail(value)) {
state.selectSuggestion(EmailAddress(value, value));
}
},
chipBuilder: (context, state, emailAddress) {
return InputChip(
key: ObjectKey(emailAddress),
label: Text(emailAddress.asString()),
labelStyle: TextStyle(color: AppColor.nameUserColor, fontSize: 12, fontWeight: FontWeight.w500),
backgroundColor: AppColor.emailAddressChipColor,
padding: EdgeInsets.all(3),
deleteIconColor: AppColor.baseTextColor,
avatar: CircleAvatar(
backgroundColor: AppColor.avatarColor,
child: Text(
emailAddress.asString().isNotEmpty ? emailAddress.asString()[0].toUpperCase() : '',
style: TextStyle(color: AppColor.appColor, fontSize: 12, fontWeight: FontWeight.w500))),
onDeleted: () => state.deleteChip(emailAddress),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
);
},
suggestionBuilder: (context, state, emailAddress) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.white),
color: Colors.white),
child: ListTile(
key: ObjectKey(emailAddress),
leading: CircleAvatar(
backgroundColor: AppColor.avatarColor,
child: Text(
emailAddress.asString().isNotEmpty ? emailAddress.asString()[0].toUpperCase() : '',
style: TextStyle(color: AppColor.appColor, fontSize: 16, fontWeight: FontWeight.w500))),
title: Text(
emailAddress.asString(),
style: TextStyle(color: AppColor.nameUserColor, fontSize: 14, fontWeight: FontWeight.w500)),
subtitle: emailAddress.displayName.isNotEmpty && emailAddress.emailAddress.isNotEmpty
? Text(
emailAddress.emailAddress,
style: TextStyle(color: AppColor.baseTextColor, fontSize: 12, fontWeight: FontWeight.w500))
: null,
onTap: () => state.selectSuggestion(emailAddress),
),
);
}
)),
if (_prefixEmailAddress == PrefixEmailAddress.to)
Padding(
padding: EdgeInsets.only(top: _listEmailAddress.isNotEmpty ? 6 : 3),
child: _buildButtonExpandAddress())
]
padding: EdgeInsets.only(top: 4),
child: _buildButtonExpandAddress())
]
);
}
Widget _buildButtonExpandAddress() {
return IconButton(
color: AppColor.baseTextColor,
icon: SvgPicture.asset(
expandMode == ExpandMode.EXPAND ? _imagePaths.icExpandAddress : _imagePaths.icMoreReceiver,
width: 20,
height: 20,
fit: BoxFit.fill),
onPressed: () {
if (_onOpenExpandAddressActionClick != null) {
_onOpenExpandAddressActionClick!();
}
}
return Material(
type: MaterialType.circle,
color: Colors.transparent,
child: IconButton(
icon: SvgPicture.asset(
expandMode == ExpandMode.EXPAND ? _imagePaths.icExpandAddress : _imagePaths.icMoreReceiver,
width: 20,
height: 20,
fit: BoxFit.fill),
onPressed: () => _onOpenExpandAddressActionClick?.call()
)
);
}
Widget _buildTagEditor() {
return StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
return TagEditor<EmailAddress>(
length: _listEmail.length,
controller: controller,
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.done,
hasAddButton: false,
resetTextOnSubmitted: true,
textStyle: TextStyle(color: AppColor.colorEmailAddress, fontSize: 14, fontWeight: FontWeight.w500),
onSubmitted: (value) {
if (GetUtils.isEmail(value)) {
setState(() => _listEmailAddress.add(EmailAddress(value, value)));
_onUpdateListEmailAddressAction?.call(_prefixEmailAddress, _listEmailAddress);
} else {
_appToast.showErrorToast(AppLocalizations.of(context).email_address_is_not_in_the_correct_format);
}
},
inputDecoration: InputDecoration(
border: InputBorder.none,
hintText: AppLocalizations.of(_context).hint_text_email_address,
hintMaxLines: 1,
hintStyle: TextStyle(color: AppColor.colorHintEmailAddressInput, fontSize: 14, fontWeight: FontWeight.w500)
),
tagBuilder: (context, index) => Padding(
padding: EdgeInsets.only(top: kIsWeb ? 8 : 0),
child: Chip(
labelPadding: EdgeInsets.only(left: 8, right: 8, bottom: 2),
label: Text(_listEmail[index], maxLines: 1, overflow: TextOverflow.ellipsis),
deleteIcon: SvgPicture.asset(_imagePaths.icDeleteEmailAddress, fit: BoxFit.fill),
labelStyle: TextStyle(color: AppColor.colorEmailAddress, fontSize: 14, fontWeight: FontWeight.w500),
backgroundColor: AppColor.emailAddressChipColor,
avatar: CircleAvatar(
backgroundColor: AppColor.colorTextButton,
child: Text(
_listEmail[index].isNotEmpty ? _listEmail[index][0].toUpperCase() : '',
style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w500))),
onDeleted: () {
setState(() => _listEmailAddress.removeAt(index));
_onUpdateListEmailAddressAction?.call(_prefixEmailAddress, _listEmailAddress);
},
)),
onTagChanged: (String value) {},
findSuggestions: (String query) {
if (query.isNotEmpty && _onSuggestionEmailAddress != null) {
return _onSuggestionEmailAddress!(query);
}
return [];
},
suggestionBuilder: (context, tagEditorState, emailAddress) {
return _buildSuggestionItem(setState, context, tagEditorState, emailAddress);
},
);
});
}
List<String> get _listEmail => _listEmailAddress.map((emailAddress) => emailAddress.asString()).toList();
Widget _buildSuggestionItem(StateSetter setState, BuildContext context, TagsEditorState<EmailAddress> tagEditorState, EmailAddress emailAddress) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.white),
color: Colors.white),
child: ListTile(
key: ObjectKey(emailAddress),
leading: CircleAvatar(
backgroundColor: AppColor.avatarColor,
child: Text(
emailAddress.asString().isNotEmpty ? emailAddress.asString()[0].toUpperCase() : '',
style: TextStyle(color: AppColor.appColor, fontSize: 16, fontWeight: FontWeight.w500))),
title: Text(
emailAddress.asString(),
style: TextStyle(color: AppColor.nameUserColor, fontSize: 14, fontWeight: FontWeight.w500)),
subtitle: emailAddress.displayName.isNotEmpty && emailAddress.emailAddress.isNotEmpty
? Text(
emailAddress.emailAddress,
style: TextStyle(color: AppColor.baseTextColor, fontSize: 12, fontWeight: FontWeight.w500))
: null,
onTap: () {
setState(() => _listEmailAddress.add(emailAddress));
tagEditorState.selectSuggestion(emailAddress);
_onUpdateListEmailAddressAction?.call(_prefixEmailAddress, _listEmailAddress);
},
),
);
}
}
@@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
class SuggestionsBoxController {
final BuildContext context;
OverlayEntry? overlayEntry;
bool _isOpened = false;
bool get isOpened => _isOpened;
SuggestionsBoxController(this.context);
void open() {
if (_isOpened) return;
assert(overlayEntry != null);
Overlay.of(context)?.insert(overlayEntry!);
_isOpened = true;
}
void close() {
if (!_isOpened) return;
assert(overlayEntry != null);
overlayEntry!.remove();
_isOpened = false;
}
void toggle() {
if (_isOpened) {
close();
} else {
open();
}
}
}
@@ -68,16 +68,9 @@ class TopBarComposerWidgetBuilder {
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// IconButton(
// key: Key('button_file_share'),
// color: AppColor.baseTextColor,
// icon: SvgPicture.asset(_imagePaths.icComposerFileShare, color: AppColor.baseTextColor, fit: BoxFit.fill),
// onPressed: () {}
// ),
IconButton(
key: Key('button_attachment'),
color: AppColor.baseTextColor,
icon: SvgPicture.asset(_imagePaths.icShare, color: AppColor.baseTextColor, fit: BoxFit.fill),
icon: SvgPicture.asset(_imagePaths.icShare, fit: BoxFit.fill),
onPressed: () {
if (_onAttachFileActionClick != null) {
_onAttachFileActionClick!();
@@ -98,12 +91,6 @@ class TopBarComposerWidgetBuilder {
}
),
SizedBox(width: 8)
// IconButton(
// key: Key('button_menu_composer'),
// color: AppColor.baseTextColor,
// icon: SvgPicture.asset(_imagePaths.icComposerMenu, color: AppColor.baseTextColor, fit: BoxFit.fill),
// onPressed: () {}
// )
]
);
}
@@ -722,4 +722,11 @@ class AppLocalizations {
name: 'there_is_already_folder_with_the_same_name',
);
}
String get email_address_is_not_in_the_correct_format {
return Intl.message(
'Email address is not in the correct format',
name: 'email_address_is_not_in_the_correct_format',
);
}
}
+4 -4
View File
@@ -80,11 +80,11 @@ dependencies:
# file_size
filesize: 2.0.1
# flutter_chips_input
flutter_chips_input:
# material_tag_editor
material_tag_editor:
git:
url: https://github.com/dab246/flutter_chips_input.git
ref: master
url: https://github.com/dab246/material_tag_editor.git
ref: feature/support_suggestion_box
# uuid
uuid: 3.0.4