diff --git a/assets/images/ic_logout.svg b/assets/images/ic_logout.svg
new file mode 100644
index 000000000..f166f3cc1
--- /dev/null
+++ b/assets/images/ic_logout.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/ic_setting.svg b/assets/images/ic_setting.svg
new file mode 100644
index 000000000..c879a366f
--- /dev/null
+++ b/assets/images/ic_setting.svg
@@ -0,0 +1,3 @@
+
diff --git a/core/lib/core.dart b/core/lib/core.dart
index 4ebc370e7..432f9e855 100644
--- a/core/lib/core.dart
+++ b/core/lib/core.dart
@@ -61,6 +61,7 @@ export 'presentation/views/bottom_popup/cupertino_action_sheet_builder.dart';
export 'presentation/views/bottom_popup/confirmation_dialog_action_sheet_builder.dart';
export 'presentation/views/modal_sheets/edit_text_modal_sheet_builder.dart';
export 'presentation/views/search/search_bar_view.dart';
+export 'presentation/views/popup_menu/popup_menu_item_widget.dart';
// Resources
export 'presentation/resources/assets_paths.dart';
diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart
index 3840d4d77..7d2e6802c 100644
--- a/core/lib/presentation/resources/image_paths.dart
+++ b/core/lib/presentation/resources/image_paths.dart
@@ -92,6 +92,8 @@ class ImagePaths {
String get icToastNotSpam => _getImagePath('ic_toast_not_spam.svg');
String get icNotSpam => _getImagePath('ic_not_spam.svg');
String get icAvatarSpam => _getImagePath('ic_avatar_spam.svg');
+ String get icLogout => _getImagePath('ic_logout.svg');
+ String get icSetting => _getImagePath('ic_setting.svg');
String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
diff --git a/core/lib/presentation/views/image/avatar_builder.dart b/core/lib/presentation/views/image/avatar_builder.dart
index c8e160145..93dfe9055 100644
--- a/core/lib/presentation/views/image/avatar_builder.dart
+++ b/core/lib/presentation/views/image/avatar_builder.dart
@@ -78,6 +78,7 @@ class AvatarBuilder {
_onTapAvatarActionWithPositionClick?.call(position);
}
},
+ borderRadius: BorderRadius.circular((_size ?? 40) / 2),
child: Container(
key: _key,
width: _size ?? 40,
diff --git a/core/lib/presentation/views/popup_menu/popup_menu_item_widget.dart b/core/lib/presentation/views/popup_menu/popup_menu_item_widget.dart
new file mode 100644
index 000000000..a49832004
--- /dev/null
+++ b/core/lib/presentation/views/popup_menu/popup_menu_item_widget.dart
@@ -0,0 +1,37 @@
+
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+
+@immutable
+class PopupMenuItemWidget extends StatelessWidget {
+
+ final Function onCallBack;
+ final String icon;
+ final String name;
+ final Color? iconColor;
+ final String? iconSelection;
+
+ PopupMenuItemWidget(this.icon, this.name, this.onCallBack, {this.iconSelection, this.iconColor});
+
+ @override
+ Widget build(BuildContext context) {
+ return InkWell(
+ onTap: () => onCallBack.call(),
+ child: Padding(
+ padding: EdgeInsets.symmetric(horizontal: 20, vertical: 16),
+ child: SizedBox(
+ child: Row(children: [
+ SvgPicture.asset(icon, width: 20, height: 20, fit: BoxFit.fill, color: iconColor),
+ SizedBox(width: 12),
+ Expanded(child: Text(name,
+ style: TextStyle(fontSize: 15, color: Colors.black, fontWeight: FontWeight.w500))),
+ if (iconSelection != null)
+ Padding(
+ padding: EdgeInsets.only(left: 12),
+ child: SvgPicture.asset(iconSelection!, width: 16, height: 16, fit: BoxFit.fill)),
+ ])
+ ),
+ )
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/features/base/action/ui_action.dart b/lib/features/base/action/ui_action.dart
new file mode 100644
index 000000000..0552a70e6
--- /dev/null
+++ b/lib/features/base/action/ui_action.dart
@@ -0,0 +1,6 @@
+
+import 'package:equatable/equatable.dart';
+
+abstract class Action with EquatableMixin {}
+
+abstract class UIAction extends Action {}
\ No newline at end of file
diff --git a/lib/features/base/mixin/app_loader_mixin.dart b/lib/features/base/mixin/app_loader_mixin.dart
new file mode 100644
index 000000000..f2b99fa36
--- /dev/null
+++ b/lib/features/base/mixin/app_loader_mixin.dart
@@ -0,0 +1,13 @@
+
+import 'package:core/core.dart';
+import 'package:flutter/cupertino.dart';
+
+mixin AppLoaderMixin {
+
+ Widget get loadingWidget {
+ return Center(child: SizedBox(
+ width: 24,
+ height: 24,
+ child: CupertinoActivityIndicator(color: AppColor.colorLoading)));
+ }
+}
\ No newline at end of file
diff --git a/lib/features/base/mixin/popup_context_menu_action_mixin.dart b/lib/features/base/mixin/popup_context_menu_action_mixin.dart
index 0eb935bd7..b246a2bcc 100644
--- a/lib/features/base/mixin/popup_context_menu_action_mixin.dart
+++ b/lib/features/base/mixin/popup_context_menu_action_mixin.dart
@@ -19,8 +19,8 @@ mixin PopupContextMenuActionMixin {
context: context,
position: position ?? RelativeRect.fromLTRB(16, 40, 16, 16),
color: Colors.white,
- elevation: 5,
- shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)),
+ elevation: 4,
+ shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
items: popupMenuItems);
}
diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart
index b2d610284..e23d0bf13 100644
--- a/lib/features/composer/presentation/composer_controller.dart
+++ b/lib/features/composer/presentation/composer_controller.dart
@@ -42,8 +42,8 @@ import 'package:tmail_ui_user/features/composer/presentation/model/screen_displa
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
+import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_action.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
-import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/dashboard_action.dart';
import 'package:tmail_ui_user/features/upload/domain/state/local_file_picker_state.dart';
import 'package:tmail_ui_user/features/upload/domain/usecases/local_file_picker_interactor.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
@@ -782,7 +782,7 @@ class ComposerController extends BaseController {
void closeComposerWeb() {
FocusManager.instance.primaryFocus?.unfocus();
- mailboxDashBoardController.dispatchDashBoardAction(DashBoardAction.none);
+ mailboxDashBoardController.dispatchAction(CloseComposeEmailAction());
}
void displayScreenTypeComposerAction(ScreenDisplayMode displayMode) {
@@ -798,7 +798,7 @@ class ComposerController extends BaseController {
void deleteComposer() {
FocusManager.instance.primaryFocus?.unfocus();
- mailboxDashBoardController.dispatchDashBoardAction(DashBoardAction.none);
+ mailboxDashBoardController.dispatchAction(CloseComposeEmailAction());
}
void toggleDisplayAttachments() {
diff --git a/lib/features/email/presentation/email_bindings.dart b/lib/features/email/presentation/email_bindings.dart
index af1cb70ca..9c031362a 100644
--- a/lib/features/email/presentation/email_bindings.dart
+++ b/lib/features/email/presentation/email_bindings.dart
@@ -23,11 +23,6 @@ import 'package:tmail_ui_user/features/login/domain/repository/credential_reposi
class EmailBindings extends BaseBindings {
- @override
- void dependencies() {
- super.dependencies();
- }
-
@override
void bindingsController() {
Get.put(EmailController(
diff --git a/lib/features/email/presentation/email_controller.dart b/lib/features/email/presentation/email_controller.dart
index 6aa97b564..a08edb3ca 100644
--- a/lib/features/email/presentation/email_controller.dart
+++ b/lib/features/email/presentation/email_controller.dart
@@ -35,9 +35,9 @@ import 'package:tmail_ui_user/features/email/presentation/model/composer_argumen
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/action/dashboard_action.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart';
-import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/dashboard_action.dart';
import 'package:tmail_ui_user/features/thread/presentation/model/delete_action_type.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart';
@@ -86,7 +86,7 @@ class EmailController extends BaseController {
@override
void onInit() {
mailboxDashBoardController.selectedEmail.listen((presentationEmail) {
- log('EmailController::onReady(): ${presentationEmail.toString()}');
+ log('EmailController::onReady(): selectedEmail: ${presentationEmail.toString()}');
if (_currentEmailId != presentationEmail?.id) {
_currentEmailId = presentationEmail?.id;
_resetToOriginalValue();
@@ -546,8 +546,8 @@ class EmailController extends BaseController {
emailAddress: emailAddress,
mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role);
if (kIsWeb) {
- if (mailboxDashBoardController.dashBoardAction != DashBoardAction.compose) {
- mailboxDashBoardController.dispatchDashBoardAction(DashBoardAction.compose, arguments: arguments);
+ if (mailboxDashBoardController.dashBoardAction.value is! ComposeEmailAction) {
+ mailboxDashBoardController.dispatchAction(ComposeEmailAction(arguments: arguments));
}
} else {
push(AppRoutes.COMPOSER, arguments: arguments);
@@ -565,8 +565,8 @@ class EmailController extends BaseController {
emailAddress: emailAddress,
mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role);
if (kIsWeb) {
- if (mailboxDashBoardController.dashBoardAction != DashBoardAction.compose) {
- mailboxDashBoardController.dispatchDashBoardAction(DashBoardAction.compose, arguments: arguments);
+ if (mailboxDashBoardController.dashBoardAction.value is! ComposeEmailAction) {
+ mailboxDashBoardController.dispatchAction(ComposeEmailAction(arguments: arguments));
}
if (Get.currentRoute == AppRoutes.EMAIL) {
popBack();
@@ -629,8 +629,8 @@ class EmailController extends BaseController {
mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role);
if (kIsWeb) {
- if (mailboxDashBoardController.dashBoardAction != DashBoardAction.compose) {
- mailboxDashBoardController.dispatchDashBoardAction(DashBoardAction.compose, arguments: arguments);
+ if (mailboxDashBoardController.dashBoardAction.value is! ComposeEmailAction) {
+ mailboxDashBoardController.dispatchAction(ComposeEmailAction(arguments: arguments));
}
if (Get.currentRoute == AppRoutes.EMAIL) {
popBack();
@@ -643,8 +643,8 @@ class EmailController extends BaseController {
void composeEmailAction() {
if (kIsWeb) {
- if (mailboxDashBoardController.dashBoardAction != DashBoardAction.compose) {
- mailboxDashBoardController.dispatchDashBoardAction(DashBoardAction.compose, arguments: ComposerArguments());
+ if (mailboxDashBoardController.dashBoardAction.value is! ComposeEmailAction) {
+ mailboxDashBoardController.dispatchAction(ComposeEmailAction(arguments: ComposerArguments()));
}
if (Get.currentRoute == AppRoutes.EMAIL) {
popBack();
diff --git a/lib/features/email/presentation/email_view.dart b/lib/features/email/presentation/email_view.dart
index cdbad3e0e..76b23b36e 100644
--- a/lib/features/email/presentation/email_view.dart
+++ b/lib/features/email/presentation/email_view.dart
@@ -15,11 +15,10 @@ import 'package:tmail_ui_user/features/email/presentation/widgets/app_bar_mail_w
import 'package:tmail_ui_user/features/email/presentation/widgets/attachment_file_tile_builder.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/bottom_bar_mail_widget_builder.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/email_action_cupertino_action_sheet_action_builder.dart';
-import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/user_setting_popup_menu_mixin.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:filesize/filesize.dart';
-class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectionMixin {
+class EmailView extends GetView with NetworkConnectionMixin {
final emailController = Get.find();
final responsiveUtils = Get.find();
@@ -27,6 +26,8 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
static const int LIMIT_ADDRESS_DISPLAY = 1;
+ EmailView({Key? key}) : super(key: key);
+
@override
Widget build(BuildContext context) {
return WillPopScope(
@@ -37,58 +38,22 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
child: Scaffold(
backgroundColor: responsiveUtils.isDesktop(context) ? AppColor.colorBgDesktop : Colors.white,
body: Stack(children: [
- Container(
- padding: EdgeInsets.zero,
- margin: EdgeInsets.zero,
- decoration: responsiveUtils.isTabletLarge(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: [
- if (responsiveUtils.isDesktop(context))
- Container(
- color: Colors.white,
- padding: EdgeInsets.only(right: 10, top: 16, bottom: 10),
- child: _buildHeader(context)),
- Expanded(child: _buildBody(context)),
- ]
- )
- ),
- ),
+ Row(children: [
+ if ((!kIsWeb && !responsiveUtils.isMobile(context)) || (kIsWeb && responsiveUtils.isTabletLarge(context)))
+ const VerticalDivider(color: AppColor.lineItemListColor, width: 1, thickness: 0.2),
+ Expanded(child: SafeArea(
+ right: responsiveUtils.isLandscapeMobile(context),
+ left: responsiveUtils.isLandscapeMobile(context),
+ child: _buildBody(context)))
+ ]),
Obx(() => !emailController.mailboxDashBoardController.isNetworkConnectionAvailable() && (responsiveUtils.isMobile(context) || responsiveUtils.isTablet(context))
? Align(alignment: Alignment.bottomCenter, child: buildNetworkConnectionWidget(context))
- : SizedBox.shrink()),
+ : const SizedBox.shrink()),
])
)
);
}
- Widget _buildHeader(BuildContext context) {
- return Row(children: [
- Spacer(),
- Padding(
- padding: EdgeInsets.only(right: 16),
- child: (AvatarBuilder()
- ..text(emailController.mailboxDashBoardController.userProfile.value?.getAvatarText() ?? '')
- ..backgroundColor(Colors.white)
- ..textColor(Colors.black)
- ..context(context)
- ..addOnTapAvatarActionWithPositionClick((position) => openUserSettingAction(
- context,
- position,
- popupMenuUserSettingActionTile(context, () => emailController.mailboxDashBoardController.logoutAction())))
- ..addBoxShadows([BoxShadow(
- color: AppColor.colorShadowBgContentEmail,
- spreadRadius: 1, blurRadius: 1, offset: Offset(0, 0.5))])
- ..size(48))
- .build()),
- ]);
- }
-
Widget _buildBody(BuildContext context) {
return Container(
decoration: responsiveUtils.isDesktop(context)
@@ -97,17 +62,17 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
border: Border.all(color: AppColor.colorBorderBodyThread, width: 1),
color: Colors.white)
: null,
- margin: responsiveUtils.isDesktop(context) ? EdgeInsets.all(16) : EdgeInsets.zero,
- padding: responsiveUtils.isDesktop(context) ? EdgeInsets.only(top: 5, bottom: 5, left: 5, right: 3) : EdgeInsets.zero,
+ margin: responsiveUtils.isDesktop(context) ? const EdgeInsets.all(16) : EdgeInsets.zero,
+ padding: responsiveUtils.isDesktop(context) ? const EdgeInsets.only(top: 5, bottom: 5, left: 5, right: 3) : EdgeInsets.zero,
child: Column(children: [
_buildAppBar(context),
- if (responsiveUtils.isDesktop(context)) SizedBox(height: 5),
+ if (responsiveUtils.isDesktop(context)) const SizedBox(height: 5),
Obx(() => emailController.currentEmail != null && !responsiveUtils.isDesktop(context)
- ? _buildDivider() : SizedBox.shrink()),
+ ? _buildDivider() : const SizedBox.shrink()),
Expanded(child: _buildEmailBody(context)),
Obx(() => emailController.currentEmail != null
- ? Divider(color: AppColor.colorDividerEmailView, height: 1)
- : SizedBox.shrink()),
+ ? const Divider(color: AppColor.colorDividerEmailView, height: 1)
+ : const SizedBox.shrink()),
_buildBottomBar(context),
])
);
@@ -115,13 +80,13 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
Widget _buildDivider({EdgeInsets? edgeInsets}){
return Padding(
- padding: edgeInsets ?? EdgeInsets.symmetric(horizontal: 16),
- child: Divider(color: AppColor.colorDividerEmailView, height: 0.5));
+ padding: edgeInsets ?? const EdgeInsets.symmetric(horizontal: 16),
+ child: const Divider(color: AppColor.colorDividerEmailView, height: 0.5));
}
Widget _buildAppBar(BuildContext context) {
return Obx(() => Padding(
- padding: EdgeInsets.only(top: 6),
+ padding: const EdgeInsets.only(top: 6),
child: (AppBarMailWidgetBuilder(context, imagePaths, responsiveUtils, emailController.currentEmail, emailController.currentMailbox)
..onBackActionClick(() => emailController.backToThreadView(context))
..addOnEmailActionClick((email, action) => emailController.handleEmailAction(context, email, action))
@@ -154,7 +119,7 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
return _buildEmailMessage(context);
} else {
return SingleChildScrollView(
- physics : ClampingScrollPhysics(),
+ physics : const ClampingScrollPhysics(),
child: Container(
margin: EdgeInsets.zero,
width: double.infinity,
@@ -176,12 +141,12 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
return Text(
AppLocalizations.of(context).no_mail_selected,
textAlign: TextAlign.center,
- style: TextStyle(fontSize: 25, color: AppColor.mailboxTextColor, fontWeight: FontWeight.bold));
+ style: const TextStyle(fontSize: 25, color: AppColor.mailboxTextColor, fontWeight: FontWeight.bold));
}
Widget _buildEmailSubject(BuildContext context) {
return Padding(
- padding: EdgeInsets.only(right: 16),
+ padding: const EdgeInsets.only(right: 16),
child: SelectableText(
'${emailController.mailboxDashBoardController.selectedEmail.value?.getEmailTitle()}',
maxLines: kIsWeb ? 3 : null,
@@ -196,7 +161,7 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
Widget _buildEmailMessage(BuildContext context) {
return Container(
- padding: EdgeInsets.only(left: 16, right: 16, top: 10),
+ padding: const EdgeInsets.only(left: 16, right: 16, top: 10),
alignment: Alignment.center,
color: Colors.white,
child: LayoutBuilder(
@@ -209,22 +174,22 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
Expanded(child: _buildEmailSubject(context)),
_buildEmailTime(context),
]),
- if (responsiveUtils.isDesktop(context)) SizedBox(height: 20),
- if (!responsiveUtils.isDesktop(context)) _buildDivider(edgeInsets: EdgeInsets.only(top: 16)),
+ if (responsiveUtils.isDesktop(context)) const SizedBox(height: 20),
+ if (!responsiveUtils.isDesktop(context)) _buildDivider(edgeInsets: const EdgeInsets.only(top: 16)),
Obx(() => emailController.currentEmail != null
? _buildEmailAddress(
context,
emailController.currentEmail!,
emailController.emailAddressExpandMode.value,
emailController.isDisplayFullEmailAddress.value)
- : SizedBox.shrink()),
- _buildDivider(edgeInsets: EdgeInsets.only(top: 8)),
+ : const SizedBox.shrink()),
+ _buildDivider(edgeInsets: const EdgeInsets.only(top: 8)),
_buildAttachments(context),
if (kIsWeb)
Expanded(child: _buildEmailContent(context, constraints))
else
_buildEmailContent(context, constraints),
- SizedBox(height: 16),
+ const SizedBox(height: 16),
],
);
})
@@ -240,7 +205,7 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
pattern: emailController.currentEmail?.receivedAt?.value.toLocal().toPatternForEmailView())}',
maxLines: 1,
overflow:TextOverflow.ellipsis,
- style: TextStyle(fontSize: 13, color: AppColor.colorTime)));
+ style: const TextStyle(fontSize: 13, color: AppColor.colorTime)));
}
Widget _buildEmailAddress(BuildContext context, PresentationEmail email, ExpandMode expandMode, bool isDisplayFull) {
@@ -251,15 +216,15 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
if (email.from.numberEmailAddress() > 0)
_buildEmailAddressByPrefix(context, email, PrefixEmailAddress.from, isDisplayFull),
if (email.to.numberEmailAddress() > 0 && expandMode == ExpandMode.EXPAND)
- _buildDivider(edgeInsets: EdgeInsets.only(top: kIsWeb ? 8 : 4, bottom: 4)),
+ _buildDivider(edgeInsets: const EdgeInsets.only(top: kIsWeb ? 8 : 4, bottom: 4)),
if (email.to.numberEmailAddress() > 0 && expandMode == ExpandMode.EXPAND)
_buildEmailAddressByPrefix(context, email, PrefixEmailAddress.to, isDisplayFull),
if (email.cc.numberEmailAddress() > 0 && expandMode == ExpandMode.EXPAND && isDisplayFull)
- _buildDivider(edgeInsets: EdgeInsets.only(top: kIsWeb ? 8 : 4, bottom: 4)),
+ _buildDivider(edgeInsets: const EdgeInsets.only(top: kIsWeb ? 8 : 4, bottom: 4)),
if (email.cc.numberEmailAddress() > 0 && expandMode == ExpandMode.EXPAND && isDisplayFull)
_buildEmailAddressByPrefix(context, email, PrefixEmailAddress.cc, isDisplayFull),
if (email.bcc.numberEmailAddress() > 0 && expandMode == ExpandMode.EXPAND && isDisplayFull)
- _buildDivider(edgeInsets: EdgeInsets.only(top: kIsWeb ? 8 : 4, bottom: 4)),
+ _buildDivider(edgeInsets: const EdgeInsets.only(top: kIsWeb ? 8 : 4, bottom: 4)),
if (email.bcc.numberEmailAddress() > 0 && expandMode == ExpandMode.EXPAND && isDisplayFull)
_buildEmailAddressByPrefix(context, email, PrefixEmailAddress.bcc, isDisplayFull),
],
@@ -277,10 +242,10 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
- padding: EdgeInsets.only(top: kIsWeb ? 10: 20),
+ padding: const EdgeInsets.only(top: kIsWeb ? 10: 20),
child: Text(
'${prefixEmailAddress.asName(context)}:',
- style: TextStyle(fontSize: 14, color: AppColor.colorEmailAddressPrefix))),
+ style: const TextStyle(fontSize: 14, color: AppColor.colorEmailAddressPrefix))),
Expanded(child: _buildEmailAddressWidget(
context,
presentationEmail,
@@ -302,26 +267,26 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
) {
final displayedEmailAddress = isDisplayFull ? listEmailAddress : listEmailAddress.sublist(0, LIMIT_ADDRESS_DISPLAY);
return Padding(
- padding: EdgeInsets.only(top: 4),
+ padding: const EdgeInsets.only(top: 4),
child: Wrap(
children: [
...displayedEmailAddress.map((emailAddress) {
return Padding(
- padding: EdgeInsets.only(left: 10),
+ padding: const EdgeInsets.only(left: 10),
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),
+ labelPadding: const EdgeInsets.only(left: 8, right: 8, bottom: 2),
+ label: Text(emailAddress.asString(), maxLines: 1, overflow: TextOverflow.ellipsis),
+ labelStyle: const 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),
+ side: const BorderSide(width: 0, color: AppColor.colorEmailAddressTag),
),
avatar: (AvatarBuilder()
- ..text('${emailAddress.asString().characters.first.toUpperCase()}')
- ..addTextStyle(TextStyle(fontSize: 12, color: Colors.white, fontWeight: FontWeight.w600))
+ ..text(emailAddress.asString().characters.first.toUpperCase())
+ ..addTextStyle(const TextStyle(fontSize: 12, color: Colors.white, fontWeight: FontWeight.w600))
..avatarColor(emailAddress.avatarColors))
.build(),
),
@@ -341,14 +306,14 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
borderRadius: BorderRadius.circular(12),
color: Colors.transparent,
child: Padding(
- padding: EdgeInsets.only(top: 4, left: 16),
+ padding: const EdgeInsets.only(top: 4, left: 16),
child: TextButton(
onPressed: () => emailController.toggleDisplayEmailAddressAction(),
child: Text(
emailController.isExpandEmailAddress
? AppLocalizations.of(context).hide
: AppLocalizations.of(context).details,
- style: TextStyle(fontSize: 15, color: AppColor.colorTextButton, fontWeight: FontWeight.normal),
+ style: const TextStyle(fontSize: 15, color: AppColor.colorTextButton, fontWeight: FontWeight.normal),
),
)
)
@@ -366,15 +331,15 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
return GestureDetector(
onTap: () => emailController.showFullEmailAddress(),
child: Padding(
- padding: EdgeInsets.only(left: 8),
+ padding: const EdgeInsets.only(left: 8),
child: Chip(
- labelPadding: EdgeInsets.symmetric(horizontal: 8),
+ labelPadding: const EdgeInsets.symmetric(horizontal: 8),
label: Text('+${_getRemainCountAddressReceiver(email)}', maxLines: 1, overflow: TextOverflow.ellipsis),
- labelStyle: TextStyle(color: AppColor.colorTextButton, fontSize: 15, fontWeight: FontWeight.normal),
+ labelStyle: const TextStyle(color: AppColor.colorTextButton, fontSize: 15, fontWeight: FontWeight.normal),
backgroundColor: AppColor.colorEmailAddressTag,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
- side: BorderSide(width: 0, color: AppColor.colorEmailAddressTag),
+ side: const BorderSide(width: 0, color: AppColor.colorEmailAddressTag),
),
),
),
@@ -383,15 +348,15 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
Widget _buildAttachments(BuildContext context) {
return Obx(() => emailController.viewState.value.fold(
- (failure) => SizedBox.shrink(),
+ (failure) => const SizedBox.shrink(),
(success) {
if (success is LoadingState) {
- return SizedBox.shrink();
+ return const SizedBox.shrink();
} else {
final attachments = emailController.attachments.listAttachmentsDisplayedOutSide;
return attachments.isNotEmpty
? _buildAttachmentsBody(context, attachments)
- : SizedBox.shrink();
+ : const SizedBox.shrink();
}
}));
}
@@ -424,7 +389,7 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
padding: EdgeInsets.zero,
child: _buildAttachmentsHeader(context, attachments)),
GridView.builder(
- key: Key('list_attachment'),
+ key: const Key('list_attachment'),
primary: false,
shrinkWrap: true,
padding: EdgeInsets.only(top: isExpand ? 0 : 16, bottom: 16),
@@ -483,18 +448,18 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
- '${AppLocalizations.of(context).count_attachment(attachments.length)}',
- style: TextStyle(fontSize: 12, color: AppColor.baseTextColor)),
+ AppLocalizations.of(context).count_attachment(attachments.length),
+ style: const TextStyle(fontSize: 12, color: AppColor.baseTextColor)),
Padding(
- padding: EdgeInsets.only(left: 8),
+ padding: const EdgeInsets.only(left: 8),
child: Text(
'(${filesize(attachments.totalSize(), 1)})',
- style: TextStyle(fontSize: 12, color: AppColor.nameUserColor, fontWeight: FontWeight.w500)))
+ style: const TextStyle(fontSize: 12, color: AppColor.nameUserColor, fontWeight: FontWeight.w500)))
],
),
if (attachments.length > 2)
Padding(
- padding: EdgeInsets.only(left: 8),
+ padding: const EdgeInsets.only(left: 8),
child: IconButton(
icon: SvgPicture.asset(imagePaths.icExpandAttachment,
width: 20,
@@ -508,10 +473,10 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
Widget _buildEmailContent(BuildContext context, BoxConstraints constraints) {
return Obx(() => emailController.viewState.value.fold(
- (failure) => SizedBox.shrink(),
+ (failure) => const SizedBox.shrink(),
(success) {
if (success is LoadingState) {
- return Align(alignment: Alignment.topCenter, child: Padding(
+ return const Align(alignment: Alignment.topCenter, child: Padding(
padding: EdgeInsets.all(16),
child: SizedBox(
width: 30,
@@ -535,7 +500,7 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
mailtoDelegate: (uri) async => emailController.openMailToLink(uri));
}
} else {
- return SizedBox.shrink();
+ return const SizedBox.shrink();
}
}
}));
@@ -550,15 +515,15 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
Widget _markAsEmailUnreadAction(BuildContext context, PresentationEmail email) {
return (EmailActionCupertinoActionSheetActionBuilder(
- Key('mark_as_unread_action'),
+ const Key('mark_as_unread_action'),
SvgPicture.asset(imagePaths.icUnreadEmail, width: 28, height: 28, fit: BoxFit.fill, color: AppColor.colorTextButton),
AppLocalizations.of(context).mark_as_unread,
email,
iconLeftPadding: responsiveUtils.isMobile(context)
- ? EdgeInsets.only(left: 12, right: 16)
- : EdgeInsets.only(right: 12),
+ ? const EdgeInsets.only(left: 12, right: 16)
+ : const EdgeInsets.only(right: 12),
iconRightPadding: responsiveUtils.isMobile(context)
- ? EdgeInsets.only(right: 12)
+ ? const EdgeInsets.only(right: 12)
: EdgeInsets.zero)
..onActionClick((email) => emailController.handleEmailAction(context, email, EmailActionType.markAsUnread)))
.build();
@@ -566,7 +531,7 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
Widget _markAsEmailSpamOrUnSpamAction(BuildContext context, PresentationEmail email) {
return (EmailActionCupertinoActionSheetActionBuilder(
- Key('mark_as_spam_or_un_spam_action'),
+ const Key('mark_as_spam_or_un_spam_action'),
SvgPicture.asset(
emailController.currentMailbox?.isSpam == true ? imagePaths.icNotSpam : imagePaths.icSpam,
width: 28, height: 28, fit: BoxFit.fill, color: AppColor.colorTextButton),
@@ -575,10 +540,10 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
: AppLocalizations.of(context).mark_as_spam,
email,
iconLeftPadding: responsiveUtils.isMobile(context)
- ? EdgeInsets.only(left: 12, right: 16)
- : EdgeInsets.only(right: 12),
+ ? const EdgeInsets.only(left: 12, right: 16)
+ : const EdgeInsets.only(right: 12),
iconRightPadding: responsiveUtils.isMobile(context)
- ? EdgeInsets.only(right: 12)
+ ? const EdgeInsets.only(right: 12)
: EdgeInsets.zero)
..onActionClick((email) => emailController.handleEmailAction(context, email,
emailController.currentMailbox?.isSpam == true ? EmailActionType.unSpam : EmailActionType.moveToSpam)))
@@ -587,8 +552,8 @@ class EmailView extends GetView with UserSettingPopupMenuMixin, NetworkConnectio
List _popupMenuEmailActionTile(BuildContext context, PresentationEmail email) {
return [
- PopupMenuItem(padding: EdgeInsets.symmetric(horizontal: 8), child: _markAsEmailUnreadAction(context, email)),
- PopupMenuItem(padding: EdgeInsets.symmetric(horizontal: 8), child: _markAsEmailSpamOrUnSpamAction(context, email)),
+ PopupMenuItem(padding: const EdgeInsets.symmetric(horizontal: 8), child: _markAsEmailUnreadAction(context, email)),
+ PopupMenuItem(padding: const EdgeInsets.symmetric(horizontal: 8), child: _markAsEmailSpamOrUnSpamAction(context, email)),
];
}
}
\ No newline at end of file
diff --git a/lib/features/email/presentation/widgets/app_bar_mail_widget_builder.dart b/lib/features/email/presentation/widgets/app_bar_mail_widget_builder.dart
index 672ec239a..55641a53c 100644
--- a/lib/features/email/presentation/widgets/app_bar_mail_widget_builder.dart
+++ b/lib/features/email/presentation/widgets/app_bar_mail_widget_builder.dart
@@ -3,8 +3,8 @@ import 'package:core/core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:model/model.dart';
-import 'package:tmail_ui_user/features/setting/presentation/model/app_setting.dart';
-import 'package:tmail_ui_user/features/setting/presentation/model/reading_pane.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/model/app_setting.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/model/reading_pane.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
typedef OnBackActionClick = void Function();
@@ -44,12 +44,12 @@ class AppBarMailWidgetBuilder {
Widget build() {
return Container(
- key: Key('app_bar_messenger_widget'),
+ key: const Key('app_bar_messenger_widget'),
alignment: Alignment.center,
padding: EdgeInsets.zero,
margin: EdgeInsets.zero,
child: MediaQuery(
- data: MediaQueryData(padding: EdgeInsets.zero),
+ data: const MediaQueryData(padding: EdgeInsets.zero),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
@@ -83,10 +83,10 @@ class AppBarMailWidgetBuilder {
return Transform(
transform: Matrix4.translationValues(-10.0, 0.0, 0.0),
child: Text(
- '${_currentMailbox?.name?.name.capitalizeFirstEach ?? ''}',
+ _currentMailbox?.name?.name.capitalizeFirstEach ?? '',
maxLines: 1,
overflow: TextOverflow.ellipsis,
- style: TextStyle(fontSize: 17, color: AppColor.colorTextButton))
+ style: const TextStyle(fontSize: 17, color: AppColor.colorTextButton))
);
}
@@ -115,7 +115,7 @@ class AppBarMailWidgetBuilder {
}
}),
Padding(
- padding: EdgeInsets.only(left: 10, right: 16),
+ padding: const EdgeInsets.only(left: 10, right: 16),
child: buildIconWebHasPosition(
_context,
tooltip: AppLocalizations.of(_context).more,
diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart
index de9542cbc..595b8d660 100644
--- a/lib/features/mailbox/presentation/mailbox_controller.dart
+++ b/lib/features/mailbox/presentation/mailbox_controller.dart
@@ -106,64 +106,24 @@ class MailboxController extends BaseMailboxController {
@override
void onInit() {
- mailboxDashBoardController.accountId.listen((accountId) {
- if (accountId != null) {
- getAllMailboxAction(accountId);
- }
- });
+ _onMailboxDashBoardListener();
super.onInit();
}
@override
void onReady() {
- super.onReady();
- mailboxDashBoardController.viewState.listen((state) {
- state.fold(
- (failure) {
- if (failure is EmptyTrashFolderFailure) {
- mailboxDashBoardController.clearState();
- refreshMailboxChanges();
- }
- },
- (success) {
- if (success is MarkAsMultipleEmailReadAllSuccess
- || success is MarkAsMultipleEmailReadHasSomeEmailFailure) {
- mailboxDashBoardController.clearState();
- refreshMailboxChanges();
- } else if (success is MoveMultipleEmailToMailboxAllSuccess
- || success is MoveMultipleEmailToMailboxHasSomeEmailFailure) {
- mailboxDashBoardController.clearState();
- refreshMailboxChanges();
- } else if (success is DeleteMultipleEmailsPermanentlyAllSuccess
- || success is DeleteMultipleEmailsPermanentlyHasSomeEmailFailure) {
- mailboxDashBoardController.clearState();
- refreshMailboxChanges();
- } else if (success is EmptyTrashFolderSuccess) {
- mailboxDashBoardController.clearState();
- refreshMailboxChanges();
- } else if (success is MarkAsEmailReadSuccess
- || success is MoveToMailboxSuccess
- || success is DeleteEmailPermanentlySuccess
- || success is SaveEmailAsDraftsSuccess
- || success is RemoveEmailDraftsSuccess
- || success is SendEmailSuccess
- || success is UpdateEmailDraftsSuccess) {
- refreshMailboxChanges();
- }
- }
- );
- });
-
- _openMailboxEventController.stream.throttleTime(const Duration(milliseconds: 800)).listen((event) {
+ _openMailboxEventController.stream.throttleTime(Duration(milliseconds: 800)).listen((event) {
_handleOpenMailbox(event.buildContext, event.presentationMailbox);
});
_initCollapseMailboxCategories();
+ super.onReady();
}
@override
void onClose() {
mailboxDashBoardController.accountId.close();
+ mailboxDashBoardController.viewState.close();
searchInputController.dispose();
searchFocus.dispose();
super.onClose();
@@ -216,6 +176,50 @@ class MailboxController extends BaseMailboxController {
@override
void onError(error) {}
+ void _onMailboxDashBoardListener() {
+ mailboxDashBoardController.accountId.listen((accountId) {
+ log('MailboxController::_onMailboxDashBoardListener(): accountId: $accountId');
+ if (accountId != null) {
+ getAllMailboxAction(accountId);
+ }
+ });
+
+ mailboxDashBoardController.viewState.listen((state) {
+ log('MailboxController::_onMailboxDashBoardListener(): viewState: $viewState');
+ state.fold((failure) {
+ if (failure is EmptyTrashFolderFailure) {
+ mailboxDashBoardController.clearState();
+ refreshMailboxChanges();
+ }
+ }, (success) {
+ if (success is MarkAsMultipleEmailReadAllSuccess ||
+ success is MarkAsMultipleEmailReadHasSomeEmailFailure) {
+ mailboxDashBoardController.clearState();
+ refreshMailboxChanges();
+ } else if (success is MoveMultipleEmailToMailboxAllSuccess ||
+ success is MoveMultipleEmailToMailboxHasSomeEmailFailure) {
+ mailboxDashBoardController.clearState();
+ refreshMailboxChanges();
+ } else if (success is DeleteMultipleEmailsPermanentlyAllSuccess ||
+ success is DeleteMultipleEmailsPermanentlyHasSomeEmailFailure) {
+ mailboxDashBoardController.clearState();
+ refreshMailboxChanges();
+ } else if (success is EmptyTrashFolderSuccess) {
+ mailboxDashBoardController.clearState();
+ refreshMailboxChanges();
+ } else if (success is MarkAsEmailReadSuccess ||
+ success is MoveToMailboxSuccess ||
+ success is DeleteEmailPermanentlySuccess ||
+ success is SaveEmailAsDraftsSuccess ||
+ success is RemoveEmailDraftsSuccess ||
+ success is SendEmailSuccess ||
+ success is UpdateEmailDraftsSuccess) {
+ refreshMailboxChanges();
+ }
+ });
+ });
+ }
+
void _initCollapseMailboxCategories() {
if (currentContext != null) {
if (kIsWeb && (_responsiveUtils.isMobile(currentContext!)) || _responsiveUtils.isTablet(currentContext!)) {
diff --git a/lib/features/mailbox/presentation/mailbox_view_web.dart b/lib/features/mailbox/presentation/mailbox_view_web.dart
index e8822ca58..66e05f6cb 100644
--- a/lib/features/mailbox/presentation/mailbox_view_web.dart
+++ b/lib/features/mailbox/presentation/mailbox_view_web.dart
@@ -25,11 +25,12 @@ class MailboxView extends GetWidget {
@override
Widget build(BuildContext context) {
return Drawer(
+ elevation: _responsiveUtils.isDesktop(context) ? 0 : 16.0,
child: Scaffold(
backgroundColor: Colors.white,
body: Column(
children: [
- _buildLogoApp(context),
+ if (!_responsiveUtils.isDesktop(context)) _buildLogoApp(context),
if (!_responsiveUtils.isDesktop(context)) const Divider(color: AppColor.colorDividerMailbox, height: 0.5, thickness: 0.2),
Expanded(child: Container(
padding: EdgeInsets.zero,
@@ -75,7 +76,7 @@ class MailboxView extends GetWidget {
bottom: _responsiveUtils.isDesktop(context) ? 25 : 16,
left: _responsiveUtils.isDesktop(context) ? 32 : 16),
child: Row(children: [
- (SloganBuilder(arrangedByHorizontal: true)
+ (SloganBuilder(arrangedByHorizontal: true)
..setSloganText(AppLocalizations.of(context).app_name)
..setSloganTextAlign(TextAlign.center)
..setSloganTextStyle(const TextStyle(color: Colors.black, fontSize: 20, fontWeight: FontWeight.bold))
diff --git a/lib/features/mailbox/presentation/widgets/user_information_widget_builder.dart b/lib/features/mailbox/presentation/widgets/user_information_widget_builder.dart
index dba9e9c59..675d079ab 100644
--- a/lib/features/mailbox/presentation/widgets/user_information_widget_builder.dart
+++ b/lib/features/mailbox/presentation/widgets/user_information_widget_builder.dart
@@ -65,7 +65,7 @@ class UserInformationWidgetBuilder {
child: TextButton(
onPressed: () => _onLogoutActionClick?.call(),
child: Text(
- AppLocalizations.of(_context).logout,
+ AppLocalizations.of(_context).manage_account,
style: const TextStyle(fontSize: 14, color: AppColor.colorTextButton),
),
)
diff --git a/lib/features/mailbox_dashboard/presentation/action/dashboard_action.dart b/lib/features/mailbox_dashboard/presentation/action/dashboard_action.dart
new file mode 100644
index 000000000..819e48edd
--- /dev/null
+++ b/lib/features/mailbox_dashboard/presentation/action/dashboard_action.dart
@@ -0,0 +1,97 @@
+
+import 'package:flutter/cupertino.dart';
+import 'package:model/email/email_action_type.dart';
+import 'package:model/email/filter_message_option.dart';
+import 'package:model/email/presentation_email.dart';
+import 'package:tmail_ui_user/features/base/action/ui_action.dart';
+import 'package:tmail_ui_user/main/routes/router_arguments.dart';
+
+class DashBoardAction extends UIAction {
+ static final idle = DashBoardAction();
+
+ DashBoardAction() : super();
+
+ @override
+ List