TF-313 Apply new ui for email address detail
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
<svg width="9" height="10" viewBox="0 0 9 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="4.5" cy="5" r="4.5" fill="#007AFF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 150 B |
@@ -93,6 +93,7 @@ extension AppColor on Color {
|
||||
static const colorTime = Color(0xFF92A1B4);
|
||||
static const colorEmailAddressPrefix = Color(0xFF9AA7B6);
|
||||
static const colorEmailAddressTag = Color(0x146D7885);
|
||||
static const colorLineLeftEmailView = Color(0x2999A2AD);
|
||||
|
||||
static const mapGradientColor = [
|
||||
[Color(0xFF21D4FD), Color(0xFFB721FF)],
|
||||
|
||||
@@ -65,6 +65,7 @@ class ImagePaths {
|
||||
String get icDeleteEmailAddress => _getImagePath('ic_delete_email_address.svg');
|
||||
String get icDeleteEmail => _getImagePath('ic_delete_email.svg');
|
||||
String get icNewMessage => _getImagePath('ic_new_message.svg');
|
||||
String get icUnreadStatus => _getImagePath('ic_unread_status.svg');
|
||||
|
||||
String _getImagePath(String imageName) {
|
||||
return AssetsPaths.images + imageName;
|
||||
|
||||
@@ -250,6 +250,9 @@ class ComposerController extends BaseController {
|
||||
if (listToEmailAddress.isNotEmpty || listCcEmailAddress.isNotEmpty || listBccEmailAddress.isNotEmpty) {
|
||||
isInitialRecipient.value = true;
|
||||
}
|
||||
} else if (arguments.emailAddress != null) {
|
||||
listToEmailAddress.add(arguments.emailAddress!);
|
||||
isInitialRecipient.value = true;
|
||||
}
|
||||
_updateStatusEmailSendButton();
|
||||
}
|
||||
@@ -265,6 +268,8 @@ class ComposerController extends BaseController {
|
||||
case PrefixEmailAddress.bcc:
|
||||
listBccEmailAddress = newListEmailAddress;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_updateStatusEmailSendButton();
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@ import 'package:dartz/dartz.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||
@@ -27,6 +29,8 @@ import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/email_address_bottom_sheet_builder.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/email_address_dialog_builder.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
@@ -38,6 +42,7 @@ class EmailController extends BaseController {
|
||||
|
||||
final mailboxDashBoardController = Get.find<MailboxDashBoardController>();
|
||||
final responsiveUtils = Get.find<ResponsiveUtils>();
|
||||
final imagePaths = Get.find<ImagePaths>();
|
||||
|
||||
final GetEmailContentInteractor _getEmailContentInteractor;
|
||||
final MarkAsEmailReadInteractor _markAsEmailReadInteractor;
|
||||
@@ -398,7 +403,9 @@ class EmailController extends BaseController {
|
||||
mailboxDashBoardController.dispatchState(Right(success));
|
||||
}
|
||||
|
||||
void handleEmailAction(PresentationEmail presentationEmail, EmailActionType actionType) {
|
||||
void handleEmailAction(BuildContext context, PresentationEmail presentationEmail, EmailActionType actionType) {
|
||||
popBack();
|
||||
|
||||
switch(actionType) {
|
||||
case EmailActionType.markAsUnread:
|
||||
markAsEmailRead(presentationEmail, ReadActions.markAsUnread);
|
||||
@@ -413,6 +420,7 @@ class EmailController extends BaseController {
|
||||
moveToMailboxAction(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.delete:
|
||||
_appToast.showToast(AppLocalizations.of(context).the_feature_is_under_development);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -440,6 +448,51 @@ class EmailController extends BaseController {
|
||||
isDisplayFullEmailAddress.value = true;
|
||||
}
|
||||
|
||||
void openEmailAddressDialog(BuildContext context, EmailAddress emailAddress) {
|
||||
if (responsiveUtils.isMobile(context) || responsiveUtils.isMobileDevice(context)) {
|
||||
(EmailAddressBottomSheetBuilder(context, imagePaths, emailAddress)
|
||||
..addOnCloseContextMenuAction(() => popBack())
|
||||
..addOnCopyEmailAddressAction((emailAddress) => copyEmailAddress(context, emailAddress))
|
||||
..addOnComposeEmailAction((emailAddress) => composeEmailFromEmailAddress(emailAddress)))
|
||||
.show();
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
|
||||
builder: (BuildContext context) => (EmailAddressDialogBuilder(context, imagePaths, emailAddress)
|
||||
..addOnCloseContextMenuAction(() => popBack())
|
||||
..addOnCopyEmailAddressAction((emailAddress) => copyEmailAddress(context, emailAddress))
|
||||
..addOnComposeEmailAction((emailAddress) => composeEmailFromEmailAddress(emailAddress)))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
void copyEmailAddress(BuildContext context, EmailAddress emailAddress) {
|
||||
popBack();
|
||||
|
||||
Clipboard.setData(ClipboardData(text: emailAddress.emailAddress)).then((_){
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(AppLocalizations.of(context).email_address_copied_to_clipboard))
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
void composeEmailFromEmailAddress(EmailAddress emailAddress) {
|
||||
popBack();
|
||||
|
||||
if (canComposeEmail()) {
|
||||
push(
|
||||
AppRoutes.COMPOSER,
|
||||
arguments: ComposerArguments(
|
||||
emailActionType: EmailActionType.composeFromEmailAddress,
|
||||
emailAddress: emailAddress,
|
||||
mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role,
|
||||
session: mailboxDashBoardController.sessionCurrent!,
|
||||
userProfile: mailboxDashBoardController.userProfile.value!,
|
||||
mapMailboxId: mailboxDashBoardController.mapDefaultMailboxId));
|
||||
}
|
||||
}
|
||||
|
||||
void closeMoreMenu() {
|
||||
popBack();
|
||||
}
|
||||
@@ -457,18 +510,33 @@ class EmailController extends BaseController {
|
||||
}
|
||||
|
||||
void pressEmailAction(EmailActionType emailActionType) {
|
||||
if (emailActionType == EmailActionType.compose) {
|
||||
composeEmailAction();
|
||||
} else {
|
||||
if (canComposeEmail()) {
|
||||
push(
|
||||
AppRoutes.COMPOSER,
|
||||
arguments: ComposerArguments(
|
||||
emailActionType: emailActionType,
|
||||
presentationEmail: mailboxDashBoardController.selectedEmail.value!,
|
||||
emailContents: emailContents,
|
||||
attachments: attachments,
|
||||
mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role,
|
||||
session: mailboxDashBoardController.sessionCurrent!,
|
||||
userProfile: mailboxDashBoardController.userProfile.value!,
|
||||
mapMailboxId: mailboxDashBoardController.mapDefaultMailboxId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void composeEmailAction() {
|
||||
if (canComposeEmail()) {
|
||||
push(
|
||||
AppRoutes.COMPOSER,
|
||||
arguments: ComposerArguments(
|
||||
emailActionType: emailActionType,
|
||||
presentationEmail: mailboxDashBoardController.selectedEmail.value!,
|
||||
emailContents: emailContents,
|
||||
attachments: attachments,
|
||||
mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role,
|
||||
session: mailboxDashBoardController.sessionCurrent!,
|
||||
userProfile: mailboxDashBoardController.userProfile.value!,
|
||||
mapMailboxId: mailboxDashBoardController.mapDefaultMailboxId));
|
||||
AppRoutes.COMPOSER,
|
||||
arguments: ComposerArguments(
|
||||
session: mailboxDashBoardController.sessionCurrent!,
|
||||
userProfile: mailboxDashBoardController.userProfile.value!,
|
||||
mapMailboxId: mailboxDashBoardController.mapDefaultMailboxId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,21 +31,33 @@ class EmailView extends GetView {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColor.primaryLightColor,
|
||||
body: SafeArea(
|
||||
right: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context),
|
||||
left: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
_buildAppBar(context),
|
||||
_buildDivider(),
|
||||
Expanded(child: _buildEmailBody(context)),
|
||||
Divider(color: AppColor.colorDividerEmailView, height: 1),
|
||||
_buildBottomBar(context),
|
||||
]
|
||||
)
|
||||
));
|
||||
backgroundColor: Colors.white,
|
||||
body: Container(
|
||||
padding: EdgeInsets.zero,
|
||||
margin: EdgeInsets.zero,
|
||||
decoration: !(responsiveUtils.isMobile(context) && responsiveUtils.isMobileDevice(context))
|
||||
? BoxDecoration(border: Border(left: BorderSide(color: AppColor.colorLineLeftEmailView, width: 1.0)))
|
||||
: null,
|
||||
child: SafeArea(
|
||||
right: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context),
|
||||
left: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
_buildAppBar(context),
|
||||
Obx(() => emailController.currentEmail != null
|
||||
? _buildDivider()
|
||||
: SizedBox.shrink()),
|
||||
Expanded(child: _buildEmailBody(context)),
|
||||
Obx(() => emailController.currentEmail != null
|
||||
? Divider(color: AppColor.colorDividerEmailView, height: 1)
|
||||
: SizedBox.shrink()),
|
||||
_buildBottomBar(context),
|
||||
]
|
||||
)
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDivider({EdgeInsets? edgeInsets}){
|
||||
@@ -64,7 +76,7 @@ class EmailView extends GetView {
|
||||
emailController.currentEmail,
|
||||
emailController.currentMailbox)
|
||||
..onBackActionClick(() => emailController.backToThreadView())
|
||||
..addOnEmailActionClick((email, action) => emailController.handleEmailAction(email, action))
|
||||
..addOnEmailActionClick((email, action) => emailController.handleEmailAction(context, email, action))
|
||||
..addOnMoreActionClick((email, position) => responsiveUtils.isMobileDevice(context)
|
||||
? emailController.openMoreMenuEmailAction(
|
||||
context,
|
||||
@@ -235,20 +247,23 @@ class EmailView extends GetView {
|
||||
...displayedEmailAddress.map((emailAddress) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(left: 10),
|
||||
child: Chip(
|
||||
labelPadding: EdgeInsets.only(left: 8, right: 8, bottom: 2),
|
||||
label: Text('${emailAddress.emailAddress}', maxLines: 1, overflow: TextOverflow.ellipsis),
|
||||
labelStyle: TextStyle(color: AppColor.colorNameEmail, fontSize: 15, fontWeight: FontWeight.normal),
|
||||
backgroundColor: AppColor.colorEmailAddressTag,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
side: BorderSide(width: 0, color: AppColor.colorEmailAddressTag),
|
||||
child: GestureDetector(
|
||||
onTap: () => emailController.openEmailAddressDialog(context, emailAddress),
|
||||
child: Chip(
|
||||
labelPadding: EdgeInsets.only(left: 8, right: 8, bottom: 2),
|
||||
label: Text('${emailAddress.asString()}', maxLines: 1, overflow: TextOverflow.ellipsis),
|
||||
labelStyle: TextStyle(color: AppColor.colorNameEmail, fontSize: 15, fontWeight: FontWeight.normal),
|
||||
backgroundColor: AppColor.colorEmailAddressTag,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
side: BorderSide(width: 0, color: AppColor.colorEmailAddressTag),
|
||||
),
|
||||
avatar: (AvatarBuilder()
|
||||
..text('${emailAddress.asString().characters.first.toUpperCase()}')
|
||||
..addTextStyle(TextStyle(fontSize: 12, color: Colors.white, fontWeight: FontWeight.w600))
|
||||
..avatarColor(emailAddress.avatarColors))
|
||||
.build(),
|
||||
),
|
||||
avatar: (AvatarBuilder()
|
||||
..text('${emailAddress.emailAddress.characters.first.toUpperCase()}')
|
||||
..addTextStyle(TextStyle(fontSize: 12, color: Colors.white, fontWeight: FontWeight.w600))
|
||||
..avatarColor(emailAddress.avatarColors))
|
||||
.build(),
|
||||
)
|
||||
);
|
||||
}).toList(),
|
||||
@@ -484,7 +499,7 @@ class EmailView extends GetView {
|
||||
iconRightPadding: responsiveUtils.isMobile(context)
|
||||
? EdgeInsets.only(right: 12)
|
||||
: EdgeInsets.zero)
|
||||
..onActionClick((email) => emailController.handleEmailAction(email, EmailActionType.markAsUnread)))
|
||||
..onActionClick((email) => emailController.handleEmailAction(context, email, EmailActionType.markAsUnread)))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:model/model.dart';
|
||||
|
||||
@@ -8,6 +9,7 @@ class ComposerArguments with EquatableMixin {
|
||||
final EmailActionType emailActionType;
|
||||
final PresentationEmail? presentationEmail;
|
||||
final List<EmailContent>? emailContents;
|
||||
final EmailAddress? emailAddress;
|
||||
final List<Attachment>? attachments;
|
||||
final Session session;
|
||||
final UserProfile userProfile;
|
||||
@@ -20,6 +22,7 @@ class ComposerArguments with EquatableMixin {
|
||||
this.emailContents,
|
||||
this.attachments,
|
||||
this.mailboxRole,
|
||||
this.emailAddress,
|
||||
required this.session,
|
||||
required this.userProfile,
|
||||
required this.mapMailboxId,
|
||||
@@ -31,6 +34,7 @@ class ComposerArguments with EquatableMixin {
|
||||
emailContents,
|
||||
attachments,
|
||||
mailboxRole,
|
||||
emailAddress,
|
||||
session,
|
||||
userProfile,
|
||||
mapMailboxId,
|
||||
|
||||
@@ -99,7 +99,6 @@ class AppBarMailWidgetBuilder {
|
||||
(_presentationEmail != null && _presentationEmail!.isFlaggedEmail())
|
||||
? _imagePaths.icStar
|
||||
: _imagePaths.icUnStar,
|
||||
color: AppColor.colorButton,
|
||||
fit: BoxFit.fill),
|
||||
onPressed: () {
|
||||
if (_presentationEmail != null) {
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/material.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:model/model.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
typedef OnCloseBottomSheetAction = void Function();
|
||||
typedef OnCopyEmailAddressBottomSheetAction = void Function(EmailAddress);
|
||||
typedef OnComposeEmailBottomSheetAction = void Function(EmailAddress);
|
||||
|
||||
class EmailAddressBottomSheetBuilder {
|
||||
|
||||
final BuildContext _context;
|
||||
final ImagePaths _imagePaths;
|
||||
final EmailAddress _emailAddress;
|
||||
|
||||
OnCloseBottomSheetAction? _onCloseBottomSheetAction;
|
||||
OnCopyEmailAddressBottomSheetAction? _onCopyEmailAddressAction;
|
||||
OnComposeEmailBottomSheetAction? _onComposeEmailAction;
|
||||
|
||||
EmailAddressBottomSheetBuilder(
|
||||
this._context,
|
||||
this._imagePaths,
|
||||
this._emailAddress
|
||||
);
|
||||
|
||||
void addOnCloseContextMenuAction(OnCloseBottomSheetAction onCloseBottomSheetAction) {
|
||||
_onCloseBottomSheetAction = onCloseBottomSheetAction;
|
||||
}
|
||||
|
||||
void addOnCopyEmailAddressAction(OnCopyEmailAddressBottomSheetAction onCopyEmailAddressAction) {
|
||||
_onCopyEmailAddressAction = onCopyEmailAddressAction;
|
||||
}
|
||||
|
||||
void addOnComposeEmailAction(OnComposeEmailBottomSheetAction onComposeEmailAction) {
|
||||
_onComposeEmailAction = onComposeEmailAction;
|
||||
}
|
||||
|
||||
RoundedRectangleBorder _shape() {
|
||||
return RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(20.0),
|
||||
topRight: Radius.circular(20.0)));
|
||||
}
|
||||
|
||||
BoxDecoration _decoration(BuildContext context) {
|
||||
return BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: const Radius.circular(20.0),
|
||||
topRight: const Radius.circular(20.0)));
|
||||
}
|
||||
|
||||
void show() {
|
||||
Get.bottomSheet(
|
||||
GestureDetector(
|
||||
onTap: () => _onCloseBottomSheetAction?.call(),
|
||||
child: SingleChildScrollView(
|
||||
child: Container(
|
||||
margin: EdgeInsets.zero,
|
||||
decoration: _decoration(_context),
|
||||
child: SafeArea(child: GestureDetector(
|
||||
onTap: () => {},
|
||||
child: Column(
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: IconButton(
|
||||
padding: EdgeInsets.only(top: 16, right: 16),
|
||||
onPressed: () => _onCloseBottomSheetAction?.call(),
|
||||
icon: SvgPicture.asset(_imagePaths.icCloseMailbox, width: 24, height: 24, fit: BoxFit.fill))),
|
||||
(AvatarBuilder()
|
||||
..text('${_emailAddress.asString().characters.first.toUpperCase()}')
|
||||
..size(64)
|
||||
..addTextStyle(TextStyle(fontWeight: FontWeight.w600, fontSize: 23, color: Colors.white))
|
||||
..avatarColor(_emailAddress.avatarColors))
|
||||
.build(),
|
||||
if (_emailAddress.displayName.isNotEmpty)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 16, right: 16, top: 16),
|
||||
child: Text(
|
||||
_emailAddress.asString(),
|
||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: AppColor.colorNameEmail),
|
||||
)),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 16, right: 16, top: _emailAddress.displayName.isNotEmpty ? 12 : 16),
|
||||
child: Text(
|
||||
_emailAddress.emailAddress,
|
||||
style: TextStyle(fontSize: 17, fontWeight: FontWeight.normal, color: AppColor.colorMessageConfirmDialog),
|
||||
)),
|
||||
Material(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: Colors.transparent,
|
||||
child: TextButton(
|
||||
child: Text(
|
||||
AppLocalizations.of(_context).copy_email_address,
|
||||
style: TextStyle(fontSize: 13, color: AppColor.colorTextButton, fontWeight: FontWeight.normal),
|
||||
),
|
||||
onPressed: () => _onCopyEmailAddressAction?.call(_emailAddress)
|
||||
)
|
||||
),
|
||||
SizedBox(height: _emailAddress.displayName.isNotEmpty ? 100 : 130),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 16, right: 16, bottom: 20),
|
||||
child: SizedBox(
|
||||
key: Key('compose_email_button'),
|
||||
width: double.infinity,
|
||||
height: 48,
|
||||
child: ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.resolveWith<Color>((Set<MaterialState> states) => Colors.white),
|
||||
backgroundColor: MaterialStateProperty.resolveWith<Color>((Set<MaterialState> states) => AppColor.colorTextButton),
|
||||
shape: MaterialStateProperty.all(RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
side: BorderSide(width: 0, color: AppColor.colorTextButton)))),
|
||||
child: Text(AppLocalizations.of(_context).compose_email, style: TextStyle(fontSize: 16, color: Colors.white, fontWeight: FontWeight.w500)),
|
||||
onPressed: () => _onComposeEmailAction?.call(_emailAddress)),
|
||||
)
|
||||
)
|
||||
],
|
||||
),
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
useRootNavigator: true,
|
||||
shape: _shape(),
|
||||
isScrollControlled: true,
|
||||
enableDrag: false,
|
||||
backgroundColor: Colors.transparent
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
typedef OnCloseDialogAction = void Function();
|
||||
typedef OnCopyEmailAddressDialogAction = void Function(EmailAddress);
|
||||
typedef OnComposeEmailDialogAction = void Function(EmailAddress);
|
||||
|
||||
class EmailAddressDialogBuilder {
|
||||
|
||||
final BuildContext _context;
|
||||
final ImagePaths _imagePaths;
|
||||
final EmailAddress _emailAddress;
|
||||
|
||||
OnCloseDialogAction? _onCloseDialogAction;
|
||||
OnCopyEmailAddressDialogAction? _onCopyEmailAddressAction;
|
||||
OnComposeEmailDialogAction? _onComposeEmailAction;
|
||||
|
||||
EmailAddressDialogBuilder(
|
||||
this._context,
|
||||
this._imagePaths,
|
||||
this._emailAddress
|
||||
);
|
||||
|
||||
void addOnCloseContextMenuAction(OnCloseDialogAction onCloseDialogAction) {
|
||||
_onCloseDialogAction = onCloseDialogAction;
|
||||
}
|
||||
|
||||
void addOnCopyEmailAddressAction(OnCopyEmailAddressDialogAction onCopyEmailAddressAction) {
|
||||
_onCopyEmailAddressAction = onCopyEmailAddressAction;
|
||||
}
|
||||
|
||||
void addOnComposeEmailAction(OnComposeEmailDialogAction onComposeEmailAction) {
|
||||
_onComposeEmailAction = onComposeEmailAction;
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
return Dialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))),
|
||||
insetPadding: EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0),
|
||||
child: Container(
|
||||
margin: EdgeInsets.zero,
|
||||
padding: EdgeInsets.zero,
|
||||
width: 400,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.all(Radius.circular(16))),
|
||||
child: Wrap(
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: IconButton(
|
||||
padding: EdgeInsets.only(top: 16, right: 16),
|
||||
onPressed: () => _onCloseDialogAction?.call(),
|
||||
icon: SvgPicture.asset(_imagePaths.icCloseMailbox, width: 24, height: 24, fit: BoxFit.fill))),
|
||||
Padding(padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Center(child: (AvatarBuilder()
|
||||
..text('${_emailAddress.asString().characters.first.toUpperCase()}')
|
||||
..size(64)
|
||||
..addTextStyle(TextStyle(fontWeight: FontWeight.w600, fontSize: 23, color: Colors.white))
|
||||
..avatarColor(_emailAddress.avatarColors))
|
||||
.build())),
|
||||
if (_emailAddress.displayName.isNotEmpty)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 16, right: 16, top: 16),
|
||||
child: Center(child: Text(
|
||||
_emailAddress.asString(),
|
||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: AppColor.colorNameEmail),
|
||||
))
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 16, right: 16, top: _emailAddress.displayName.isNotEmpty ? 12 : 16),
|
||||
child: Center(child: Text(
|
||||
_emailAddress.emailAddress,
|
||||
style: TextStyle(fontSize: 17, fontWeight: FontWeight.normal, color: AppColor.colorMessageConfirmDialog),
|
||||
))
|
||||
),
|
||||
Padding(padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Center(child: Material(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: Colors.transparent,
|
||||
child: TextButton(
|
||||
child: Text(
|
||||
AppLocalizations.of(_context).copy_email_address,
|
||||
style: TextStyle(fontSize: 13, color: AppColor.colorTextButton, fontWeight: FontWeight.normal),
|
||||
),
|
||||
onPressed: () => _onCopyEmailAddressAction?.call(_emailAddress)
|
||||
)
|
||||
))),
|
||||
SizedBox(height: _emailAddress.displayName.isNotEmpty ? 100 : 130),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 16, right: 16, bottom: 20),
|
||||
child: SizedBox(
|
||||
key: Key('compose_email_button'),
|
||||
width: double.infinity,
|
||||
height: 48,
|
||||
child: ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.resolveWith<Color>((Set<MaterialState> states) => Colors.white),
|
||||
backgroundColor: MaterialStateProperty.resolveWith<Color>((Set<MaterialState> states) => AppColor.colorTextButton),
|
||||
shape: MaterialStateProperty.all(RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
side: BorderSide(width: 0, color: AppColor.colorTextButton)))),
|
||||
child: Text(AppLocalizations.of(_context).compose_email, style: TextStyle(fontSize: 16, color: Colors.white, fontWeight: FontWeight.w500)),
|
||||
onPressed: () => _onComposeEmailAction?.call(_emailAddress)),
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
-209
@@ -1,209 +0,0 @@
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
typedef OnOpenExpandAddressReceiverActionClick = void Function();
|
||||
|
||||
class SenderAndReceiverInformationTileBuilder {
|
||||
|
||||
static const int LIMIT_ADDRESS_DISPLAY = 1;
|
||||
|
||||
final ImagePaths _imagePaths;
|
||||
final BuildContext _context;
|
||||
final PresentationEmail? _presentationEmail;
|
||||
final ExpandMode _expandMode;
|
||||
|
||||
OnOpenExpandAddressReceiverActionClick? _onOpenExpandAddressReceiverActionClick;
|
||||
|
||||
SenderAndReceiverInformationTileBuilder(
|
||||
this._context,
|
||||
this._imagePaths,
|
||||
this._presentationEmail,
|
||||
this._expandMode,
|
||||
);
|
||||
|
||||
SenderAndReceiverInformationTileBuilder onOpenExpandAddressReceiverActionClick(OnOpenExpandAddressReceiverActionClick onOpenExpandAddressReceiverActionClick) {
|
||||
_onOpenExpandAddressReceiverActionClick = onOpenExpandAddressReceiverActionClick;
|
||||
return this;
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
if (_presentationEmail == null) {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
return Theme(
|
||||
data: ThemeData(
|
||||
splashColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent),
|
||||
child: MediaQuery(
|
||||
data: MediaQueryData(padding: EdgeInsets.zero),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: Transform(
|
||||
transform: Matrix4.translationValues(0.0, 0.0, 0.0),
|
||||
child: (AvatarBuilder()
|
||||
..text('${_presentationEmail!.getAvatarText()}')
|
||||
..textColor(Colors.white)
|
||||
..avatarColor(_presentationEmail?.avatarColors)
|
||||
..size(GetPlatform.isWeb ? 48 : 56))
|
||||
// .iconStatus(_imagePaths.icOffline)
|
||||
.build()),
|
||||
title: Transform(
|
||||
transform: Matrix4.translationValues(0.0, 0.0, 0.0),
|
||||
child: Row(children: [
|
||||
Expanded(child: Text(
|
||||
'${_presentationEmail!.getSenderName()}',
|
||||
style: TextStyle(fontSize: 17, color: AppColor.colorNameEmail, fontWeight: FontWeight.w500),
|
||||
)),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 8),
|
||||
child: Text(
|
||||
'${_presentationEmail!.getReceivedAt(Localizations.localeOf(_context).toLanguageTag())}',
|
||||
maxLines: 1,
|
||||
overflow:TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 15, color: AppColor.colorContentEmail)))
|
||||
])),
|
||||
subtitle: Transform(
|
||||
transform: Matrix4.translationValues(0.0, 0.0, 0.0),
|
||||
child: Row(children: [
|
||||
Expanded(child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (_presentationEmail!.to.numberEmailAddress() > 0) _buildAddressToReceiverWidget(),
|
||||
if (_presentationEmail!.cc.numberEmailAddress() > 0) _buildAddressCcReceiverWidget(),
|
||||
if (_presentationEmail!.bcc.numberEmailAddress() > 0) _buildAddressBccReceiverWidget(),
|
||||
],
|
||||
)),
|
||||
if (_presentationEmail?.hasAttachment == true)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 8),
|
||||
child: (ButtonBuilder(_imagePaths.icAttachment)
|
||||
..paddingIcon(EdgeInsets.zero)
|
||||
..size(16))
|
||||
.build()),
|
||||
]))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildExpandAddressWidget(String typeReceiver, String nameAddress) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'$typeReceiver: ',
|
||||
style: TextStyle(fontSize: 12, color: AppColor.baseTextColor, fontWeight: FontWeight.w500)),
|
||||
Expanded(child: Text(
|
||||
'$nameAddress',
|
||||
style: TextStyle(fontSize: 12, color: AppColor.baseTextColor, fontWeight: FontWeight.w500),
|
||||
))
|
||||
]);
|
||||
}
|
||||
|
||||
Widget _buildCollapseAddressWidget(String typeReceiver, String nameAddress) {
|
||||
return Row(
|
||||
children: [
|
||||
Text(
|
||||
'$typeReceiver: $nameAddress',
|
||||
style: TextStyle(fontSize: 12, color: AppColor.baseTextColor, fontWeight: FontWeight.w500)),
|
||||
if (_expandMode == ExpandMode.COLLAPSE
|
||||
&& _presentationEmail != null
|
||||
&& _presentationEmail!.numberOfAllEmailAddress() > LIMIT_ADDRESS_DISPLAY)
|
||||
_buildButtonExpandAddress()
|
||||
]);
|
||||
}
|
||||
|
||||
Widget _buildAddressWidget(String typeReceiver, String nameAddress) {
|
||||
if (_expandMode == ExpandMode.EXPAND
|
||||
|| (_presentationEmail != null && _presentationEmail!.numberOfAllEmailAddress() <= LIMIT_ADDRESS_DISPLAY)) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 6),
|
||||
child: _buildExpandAddressWidget(typeReceiver, nameAddress));
|
||||
} else {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 6),
|
||||
child: _buildCollapseAddressWidget(typeReceiver, nameAddress));
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildAddressToReceiverWidget() {
|
||||
return _buildAddressWidget(
|
||||
AppLocalizations.of(_context).to_email_address_prefix,
|
||||
_presentationEmail!.to.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY));
|
||||
}
|
||||
|
||||
Widget _buildAddressCcReceiverWidget() {
|
||||
if (_presentationEmail!.to.numberEmailAddress() > 0) {
|
||||
if (_expandMode == ExpandMode.EXPAND) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 6),
|
||||
child: _buildExpandAddressWidget(AppLocalizations.of(_context).cc_email_address_prefix, _presentationEmail!.cc.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY)));
|
||||
} else {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
} else {
|
||||
return _buildAddressWidget(
|
||||
AppLocalizations.of(_context).cc_email_address_prefix,
|
||||
_presentationEmail!.cc.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY));
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildAddressBccReceiverWidget() {
|
||||
if (_presentationEmail!.to.numberEmailAddress() > 0) {
|
||||
if (_expandMode == ExpandMode.EXPAND) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 6),
|
||||
child: _buildExpandAddressWidget(AppLocalizations.of(_context).bcc_email_address_prefix, _presentationEmail!.bcc.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY)));
|
||||
} else {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
} else {
|
||||
if (_presentationEmail!.cc.numberEmailAddress() > 0) {
|
||||
if (_expandMode == ExpandMode.EXPAND) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 6),
|
||||
child: _buildExpandAddressWidget(AppLocalizations.of(_context).bcc_email_address_prefix, _presentationEmail!.bcc.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY)));
|
||||
} else {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
} else {
|
||||
return _buildAddressWidget(
|
||||
AppLocalizations.of(_context).bcc_email_address_prefix,
|
||||
_presentationEmail!.bcc.listEmailAddressToString(expandMode: _expandMode, limitAddress: LIMIT_ADDRESS_DISPLAY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String getRemainCountAddressReceiver() {
|
||||
if (_presentationEmail!.numberOfAllEmailAddress() - LIMIT_ADDRESS_DISPLAY >= 999) {
|
||||
return '999';
|
||||
}
|
||||
return '${_presentationEmail!.numberOfAllEmailAddress() - LIMIT_ADDRESS_DISPLAY}';
|
||||
}
|
||||
|
||||
Widget _buildButtonExpandAddress() {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (_onOpenExpandAddressReceiverActionClick != null) {
|
||||
_onOpenExpandAddressReceiverActionClick!();
|
||||
}},
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
'+${getRemainCountAddressReceiver()}',
|
||||
style: TextStyle(fontSize: 12, color: AppColor.baseTextColor, fontWeight: FontWeight.w500),
|
||||
),
|
||||
SvgPicture.asset(_imagePaths.icMoreReceiver, width: 14, height: 14, fit: BoxFit.fill),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -81,7 +81,7 @@ class EmailTileBuilder {
|
||||
if (_presentationEmail.isUnReadEmail())
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 5),
|
||||
child: SvgPicture.asset(_imagePaths.icUnread, width: 9, height: 9, fit: BoxFit.fill)),
|
||||
child: SvgPicture.asset(_imagePaths.icUnreadStatus, width: 9, height: 9, fit: BoxFit.fill)),
|
||||
Expanded(
|
||||
child: _searchStatus == SearchStatus.ACTIVE && _searchQuery != null && _searchQuery!.value.isNotEmpty
|
||||
? RichTextBuilder(
|
||||
|
||||
@@ -755,4 +755,22 @@ class AppLocalizations {
|
||||
'Hide',
|
||||
name: 'hide');
|
||||
}
|
||||
|
||||
String get copy_email_address {
|
||||
return Intl.message(
|
||||
'Copy email address',
|
||||
name: 'copy_email_address');
|
||||
}
|
||||
|
||||
String get compose_email {
|
||||
return Intl.message(
|
||||
'Compose email',
|
||||
name: 'compose_email');
|
||||
}
|
||||
|
||||
String get email_address_copied_to_clipboard {
|
||||
return Intl.message(
|
||||
'Email address copied to clipboard',
|
||||
name: 'email_address_copied_to_clipboard');
|
||||
}
|
||||
}
|
||||
@@ -13,4 +13,5 @@ enum EmailActionType {
|
||||
markAsSpam,
|
||||
delete,
|
||||
edit,
|
||||
composeFromEmailAddress
|
||||
}
|
||||
Reference in New Issue
Block a user