TF-467 Apply new UI for mailbox mobile

This commit is contained in:
dab246
2022-04-08 12:43:45 +07:00
committed by Dat H. Pham
parent 3eb5f31dcd
commit 7b5a2dd820
22 changed files with 1058 additions and 435 deletions
+3
View File
@@ -0,0 +1,3 @@
<svg width="16" height="24" viewBox="0 0 16 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.70575 7.70501C4.31596 7.31523 4.31809 6.68113 4.70605 6.29316L4.7939 6.20532C5.18386 5.81536 5.81349 5.81275 6.20796 6.20723L11.292 11.2913C11.683 11.6823 11.6865 12.3127 11.292 12.7072L6.20796 17.7913C5.81695 18.1823 5.18187 18.1811 4.7939 17.7932L4.70605 17.7053C4.3161 17.3154 4.31275 16.6865 4.70575 16.2935L8.99998 11.9992L4.70575 7.70501Z" fill="#007AFF"/>
</svg>

After

Width:  |  Height:  |  Size: 478 B

+2 -2
View File
@@ -1,3 +1,3 @@
<svg width="12" height="7" viewBox="0 0 12 7" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="24" height="16" viewBox="0 0 24 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.7205 1.60974L6.46599 6.80901C6.20841 7.06366 5.79226 7.06366 5.53401 6.80901L0.27946 1.60974C-0.0931995 1.24212 -0.0931996 0.643994 0.27946 0.275719C0.65212 -0.0919047 1.25694 -0.0919047 1.6296 0.275719L6.00034 4.60131L10.3697 0.275717C10.743 -0.0919061 11.3478 -0.0919061 11.7205 0.275717C12.0932 0.643993 12.0932 1.24211 11.7205 1.60974Z" fill="#7E869B"/> <path d="M16.2943 4.70557C16.684 4.31578 17.3181 4.31791 17.7061 4.70587L17.794 4.79372C18.1839 5.18367 18.1865 5.8133 17.792 6.20778L12.708 11.2918C12.317 11.6828 11.6865 11.6863 11.292 11.2918L6.20801 6.20778C5.817 5.81677 5.81814 5.18168 6.20611 4.79372L6.29395 4.70587C6.68391 4.31592 7.3128 4.31257 7.7058 4.70557L12 8.99979L16.2943 4.70557Z" fill="#007AFF"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 512 B

After

Width:  |  Height:  |  Size: 468 B

-3
View File
@@ -1,3 +0,0 @@
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.60974 0.279495L6.80901 5.53401C7.06367 5.79159 7.06367 6.20774 6.80901 6.46599L1.60974 11.7205C1.24212 12.0932 0.643994 12.0932 0.275719 11.7205C-0.0919046 11.3479 -0.0919045 10.7431 0.275719 10.3704L4.60131 5.99966L0.275718 1.6303C-0.0919047 1.25697 -0.0919046 0.652155 0.275718 0.279495C0.643994 -0.093165 1.24212 -0.0931649 1.60974 0.279495Z" fill="#7E869B"/>
</svg>

Before

Width:  |  Height:  |  Size: 516 B

-3
View File
@@ -1,3 +0,0 @@
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.60974 0.279495L6.80901 5.53401C7.06367 5.79159 7.06367 6.20774 6.80901 6.46599L1.60974 11.7205C1.24212 12.0932 0.643994 12.0932 0.275719 11.7205C-0.0919046 11.3479 -0.0919045 10.7431 0.275719 10.3704L4.60131 5.99966L0.275718 1.6303C-0.0919047 1.25697 -0.0919046 0.652155 0.275718 0.279495C0.643994 -0.093165 1.24212 -0.0931649 1.60974 0.279495Z" fill="#3840F7"/>
</svg>

Before

Width:  |  Height:  |  Size: 516 B

@@ -3,7 +3,7 @@ import 'dart:ui' show Color;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
extension AppColor on Color { extension AppColor on Color {
static const primaryColor = Color(0xFF837DFF); static const primaryColor = Color(0xFF007AFF);
static const primaryDarkColor = Color(0xFF1C1C1C); static const primaryDarkColor = Color(0xFF1C1C1C);
static const primaryLightColor = Color(0xFFFFFFFF); static const primaryLightColor = Color(0xFFFFFFFF);
static const baseTextColor = Color(0xFF7E869B); static const baseTextColor = Color(0xFF7E869B);
@@ -69,7 +69,8 @@ extension AppColor on Color {
static const colorBgSearchBar = Color(0xFFEBEDF0); static const colorBgSearchBar = Color(0xFFEBEDF0);
static const colorShadowBgContentEmail = Color(0x14000000); static const colorShadowBgContentEmail = Color(0x14000000);
static const colorDividerMailbox = Color(0xFF99A2AD); static const colorDividerMailbox = Color(0xFF99A2AD);
static const colorArrowUserMailbox = Color(0xFFB8C1CC); static const colorCollapseMailbox = Color(0xFFB8C1CC);
static const colorExpandMailbox = Color(0xFF007AFF);
static const colorBgMailbox = Color(0xFFF7F7F7); static const colorBgMailbox = Color(0xFFF7F7F7);
static const colorFilterMessageDisabled = Color(0xFF99A2AD); static const colorFilterMessageDisabled = Color(0xFF99A2AD);
static const colorFilterMessageEnabled = Color(0xFF007AFF); static const colorFilterMessageEnabled = Color(0xFF007AFF);
@@ -2,11 +2,10 @@ import 'package:core/presentation/resources/assets_paths.dart';
class ImagePaths { class ImagePaths {
String get icSearch => _getImagePath('ic_search.svg'); String get icSearch => _getImagePath('ic_search.svg');
String get icNextArrow => _getImagePath('ic_next_arrow.svg');
String get icMailboxAllMail => _getImagePath('ic_mailbox_allmail.svg'); String get icMailboxAllMail => _getImagePath('ic_mailbox_allmail.svg');
String get icMailboxTemplate => _getImagePath('ic_mailbox_template.svg'); String get icMailboxTemplate => _getImagePath('ic_mailbox_template.svg');
String get icFolderArrow => _getImagePath('ic_folder_arrow.svg');
String get icExpandFolder => _getImagePath('ic_expand_folder.svg'); String get icExpandFolder => _getImagePath('ic_expand_folder.svg');
String get icCollapseFolder => _getImagePath('ic_collapse_folder.svg');
String get icBack => _getImagePath('ic_back.svg'); String get icBack => _getImagePath('ic_back.svg');
String get icEyeDisable => _getImagePath('ic_eye_disable.svg'); String get icEyeDisable => _getImagePath('ic_eye_disable.svg');
String get icShare => _getImagePath('ic_share.svg'); String get icShare => _getImagePath('ic_share.svg');
@@ -8,6 +8,9 @@ class ResponsiveUtils {
final int minTabletWidth = 600; final int minTabletWidth = 600;
final int minTabletLargeWidth = 900; final int minTabletLargeWidth = 900;
final double defaultSizeDrawerWidthMobileTablet = 375;
final double defaultSizeDrawerWidthWeb = 320;
final double _loginTextFieldWidthSmallScreen = 280.0; final double _loginTextFieldWidthSmallScreen = 280.0;
final double _loginTextFieldWidthLargeScreen = 320.0; final double _loginTextFieldWidthLargeScreen = 320.0;
final double _loginButtonWidth = 240.0; final double _loginButtonWidth = 240.0;
@@ -83,7 +83,9 @@ class TreeViewChild {
AnimatedContainer( AnimatedContainer(
duration: Duration(milliseconds: 400), duration: Duration(milliseconds: 400),
child: isExpanded! child: isExpanded!
? Column(mainAxisSize: MainAxisSize.min, children: children) ? Column(
mainAxisSize: MainAxisSize.min,
children: children.map((child) => Padding(padding: EdgeInsets.only(left: 20), child: child)).toList())
: Offstage(), : Offstage(),
), ),
], ],
@@ -36,6 +36,8 @@ import 'package:tmail_ui_user/features/mailbox/domain/usecases/refresh_all_mailb
import 'package:tmail_ui_user/features/mailbox/domain/usecases/rename_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/rename_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/search_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/search_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_categories.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_categories_expand_mode.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/open_mailbox_view_event.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/open_mailbox_view_event.dart';
@@ -81,6 +83,7 @@ class MailboxController extends BaseMailboxController {
final searchState = SearchState.initial().obs; final searchState = SearchState.initial().obs;
final searchQuery = SearchQuery.initial().obs; final searchQuery = SearchQuery.initial().obs;
final currentSelectMode = SelectMode.INACTIVE.obs; final currentSelectMode = SelectMode.INACTIVE.obs;
final mailboxCategoriesExpandMode = MailboxCategoriesExpandMode.initial().obs;
final _openMailboxEventController = StreamController<OpenMailboxViewEvent>(); final _openMailboxEventController = StreamController<OpenMailboxViewEvent>();
final searchInputController = TextEditingController(); final searchInputController = TextEditingController();
@@ -672,6 +675,21 @@ class MailboxController extends BaseMailboxController {
log('MailboxController::_createListMailboxNameAsStringInMailboxLocation(): $listMailboxNameAsStringExist'); log('MailboxController::_createListMailboxNameAsStringInMailboxLocation(): $listMailboxNameAsStringExist');
} }
void toggleMailboxCategories(MailboxCategories categories) {
switch(categories) {
case MailboxCategories.exchange:
final newExpandMode = mailboxCategoriesExpandMode.value.defaultMailbox == ExpandMode.EXPAND ? ExpandMode.COLLAPSE : ExpandMode.EXPAND;
mailboxCategoriesExpandMode.value.defaultMailbox = newExpandMode;
mailboxCategoriesExpandMode.refresh();
break;
case MailboxCategories.folders:
final newExpandMode = mailboxCategoriesExpandMode.value.folderMailbox == ExpandMode.EXPAND ? ExpandMode.COLLAPSE : ExpandMode.EXPAND;
mailboxCategoriesExpandMode.value.folderMailbox = newExpandMode;
mailboxCategoriesExpandMode.refresh();
break;
}
}
void closeMailboxScreen(BuildContext context) { void closeMailboxScreen(BuildContext context) {
_cancelSelectMailbox(); _cancelSelectMailbox();
mailboxDashBoardController.closeDrawer(); mailboxDashBoardController.closeDrawer();
@@ -6,10 +6,11 @@ import 'package:get/get.dart';
import 'package:model/model.dart'; import 'package:model/model.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_controller.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_controller.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_categories.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/bottom_bar_selection_mailbox_widget.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/bottom_bar_selection_mailbox_widget.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_tile_builder.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/user_information_widget_builder.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/user_information_widget_builder.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/search_app_bar_widget.dart'; import 'package:tmail_ui_user/features/thread/presentation/widgets/search_app_bar_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
@@ -25,156 +26,176 @@ class MailboxView extends GetWidget<MailboxController> {
} }
Widget _buildBodyMailbox(BuildContext context) { Widget _buildBodyMailbox(BuildContext context) {
return SafeArea( return SafeArea(bottom: false, left: false, right: false, top: _responsiveUtils.isMobile(context),
top: _responsiveUtils.isMobile(context) ? true : false,
bottom: false,
left: false,
right: false,
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.only( borderRadius: _responsiveUtils.isMobile(context) && _responsiveUtils.isPortrait(context)
topRight: Radius.circular(_responsiveUtils.isMobile(context) ? 14 : 0), ? BorderRadius.only(topRight: Radius.circular(14), topLeft: Radius.circular(14))
topLeft: Radius.circular(_responsiveUtils.isMobile(context) ? 14 : 0)), : BorderRadius.all(Radius.zero),
child: Drawer( child: Drawer(
child: Scaffold( child: Scaffold(
backgroundColor: _responsiveUtils.isDesktop(context) ? AppColor.colorBgDesktop : Colors.white, backgroundColor: _responsiveUtils.isDesktop(context) ? AppColor.colorBgDesktop : Colors.white,
body: Column( body: Stack(children: [
children: [ Column(children: [
if (_responsiveUtils.isDesktop(context)) if (_responsiveUtils.isDesktop(context)) _buildLogoApp(context),
Container( if (!_responsiveUtils.isDesktop(context)) _buildHeaderMailbox(context),
color: Colors.white, if (_responsiveUtils.isDesktop(context)) _buildComposerButton(context),
padding: EdgeInsets.only(left: 20, top: 20, bottom: 24), Obx(() => !controller.isSearchActive() && _responsiveUtils.isDesktop(context)
child: (SloganBuilder(arrangedByHorizontal: true) ? Row(children: [
..setSloganText(AppLocalizations.of(context).app_name) Expanded(child: _buildSearchBarWidget(context)),
..setSloganTextAlign(TextAlign.center) _buildAddNewFolderButton(context),
..setSloganTextStyle(TextStyle(color: Colors.black, fontSize: 25, fontWeight: FontWeight.bold)) ])
..setSizeLogo(28) : SizedBox.shrink()),
..setLogo(_imagePaths.icLogoTMail)) Obx(() => controller.isSearchActive()
.build()), ? SafeArea(bottom: false, top: false, right: false, child: _buildInputSearchFormWidget(context))
if (!_responsiveUtils.isDesktop(context)) _buildHeaderMailbox(context), : SizedBox.shrink()),
if (_responsiveUtils.isDesktop(context)) Expanded(child: Obx(() => Container(
Row(children: [ color: _responsiveUtils.isDesktop(context)
Expanded(child: Container(
padding: EdgeInsets.only(top: 16, left: 20),
color: AppColor.colorBgDesktop,
alignment: Alignment.centerLeft,
child: (ButtonBuilder(_imagePaths.icCompose)
..key(Key('button_compose_email'))
..decoration(BoxDecoration(borderRadius: BorderRadius.circular(25), color: AppColor.colorTextButton))
..paddingIcon(EdgeInsets.only(right: 8))
..iconColor(Colors.white)
..maxWidth(140)
..size(20)
..radiusSplash(10)
..padding(EdgeInsets.symmetric(vertical: 13))
..textStyle(TextStyle(fontSize: 15, color: Colors.white, fontWeight: FontWeight.w500))
..onPressActionClick(() => controller.mailboxDashBoardController.composeEmailAction())
..text(AppLocalizations.of(context).compose, isVertical: false))
.build())
),
Obx(() {
if (controller.isSearchActive()) {
return controller.listMailboxSearched.isNotEmpty
? Padding(
padding: EdgeInsets.only(top: 16),
child: _buildEditMailboxButton(context, controller.isSelectionEnabled()))
: SizedBox.shrink();
} else {
return Padding(
padding: EdgeInsets.only(top: 16),
child: _buildEditMailboxButton(context, controller.isSelectionEnabled()));
}
})
]),
Obx(() => !controller.isSearchActive() && _responsiveUtils.isDesktop(context)
? Row(children: [
Expanded(child: _buildSearchBarWidget(context)),
buildIconWeb(
icon: SvgPicture.asset(_imagePaths.icAddNewFolder, color: AppColor.colorTextButton, fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).new_mailbox,
onTap: () => controller.goToCreateNewMailboxView()),
])
: SizedBox.shrink()),
Obx(() => controller.isSearchActive() ? _buildInputSearchFormWidget(context) : SizedBox.shrink()),
Expanded(child: Obx(() => Container(
color: _responsiveUtils.isDesktop(context)
? Colors.transparent ? Colors.transparent
: controller.isSearchActive() ? Colors.white : AppColor.colorBgMailbox, : controller.isSearchActive() ? Colors.white : AppColor.colorBgMailbox,
child: RefreshIndicator( child: RefreshIndicator(
color: AppColor.primaryColor, color: AppColor.primaryColor,
onRefresh: () async => controller.refreshAllMailbox(), onRefresh: () async => controller.refreshAllMailbox(),
child: controller.isSearchActive() child:controller.isSearchActive()
? _buildListMailboxSearched(context, controller.listMailboxSearched) ? SafeArea(
: _buildListMailbox(context)), bottom: !controller.isSelectionEnabled(),
))), top: false,
Obx(() => controller.isSelectionEnabled() right: false,
? _buildOptionSelectionMailbox(context) child: _buildListMailboxSearched(context))
: SizedBox.shrink()), : SafeArea(
] bottom: !controller.isSelectionEnabled(),
), right: false,
child: Padding(
padding: EdgeInsets.only(bottom: (_responsiveUtils.isMobile(context) && _responsiveUtils.isLandscape(context)) || controller.isSelectionEnabled() ? 0 : 55),
child: _buildListMailbox(context)))
),
))),
Obx(() => controller.isSelectionEnabled() ? _buildOptionSelectionMailbox(context) : SizedBox.shrink()),
]),
Obx(() {
if (controller.mailboxDashBoardController.appInformation.value != null
&& !controller.isSearchActive() && !controller.isSelectionEnabled()) {
if (_responsiveUtils.isMobile(context) && _responsiveUtils.isLandscape(context)) {
return SizedBox.shrink();
}
return Align(
alignment: Alignment.bottomCenter,
child: _buildVersionInformation(context, controller.mailboxDashBoardController.appInformation.value!));
} else {
return SizedBox.shrink();
}
})
]),
) )
) )
) )
); );
} }
Widget _buildLogoApp(BuildContext context) {
return Container(
color: Colors.white,
padding: EdgeInsets.only(left: 32, top: 20, bottom: 24),
child: (SloganBuilder(arrangedByHorizontal: true)
..setSloganText(AppLocalizations.of(context).app_name)
..setSloganTextAlign(TextAlign.center)
..setSloganTextStyle(TextStyle(color: Colors.black, fontSize: 25, fontWeight: FontWeight.bold))
..setSizeLogo(24)
..setLogo(_imagePaths.icLogoTMail))
.build());
}
Widget _buildHeaderMailbox(BuildContext context) { Widget _buildHeaderMailbox(BuildContext context) {
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Padding( Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(top: _responsiveUtils.isMobile(context) ? 10 : 30, bottom: 8),
top: _responsiveUtils.isMobile(context) ? 14 : 30, child: Row(
bottom: 10), mainAxisAlignment: MainAxisAlignment.center,
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ children: [
!_responsiveUtils.isDesktop(context) && !_responsiveUtils.isTabletLarge(context) _responsiveUtils.isMobile(context) || _responsiveUtils.isTablet(context)
? _buildCloseScreenButton(context) ? Padding(padding: EdgeInsets.only(left: 10), child: _buildCloseScreenButton(context))
: SizedBox(width: 50), : SizedBox(width: 50),
Obx(() { Obx(() {
if (controller.isSearchActive()) { if (controller.isSearchActive()) {
return controller.listMailboxSearched.isNotEmpty return controller.listMailboxSearched.isNotEmpty
? SizedBox(width: controller.isSelectionEnabled() ? 49 : 40) ? SizedBox(width: controller.isSelectionEnabled() ? 49 : 40)
: SizedBox.shrink(); : SizedBox.shrink();
} else { } else {
return SizedBox(width: controller.isSelectionEnabled() ? 49 : 40); return SizedBox(width: controller.isSelectionEnabled() ? 49 : 40);
} }
}), }),
Expanded(child: Text( Expanded(child: Text(
AppLocalizations.of(context).folders, AppLocalizations.of(context).folders,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle(fontSize: 20, color: AppColor.colorNameEmail, fontWeight: FontWeight.w700))), style: TextStyle(fontSize: 21, color: Colors.black, fontWeight: FontWeight.bold))),
Obx(() { Obx(() {
if (controller.isSearchActive()) { if (controller.isSearchActive()) {
return controller.listMailboxSearched.isNotEmpty return controller.listMailboxSearched.isNotEmpty
? _buildEditMailboxButton(context, controller.isSelectionEnabled()) ? _buildEditMailboxButton(context, controller.isSelectionEnabled())
: SizedBox(width: 25); : SizedBox(width: 25);
} else { } else {
return _buildEditMailboxButton(context, controller.isSelectionEnabled()); return _buildEditMailboxButton(context, controller.isSelectionEnabled());
} }
}), }),
_buildAddNewFolderButton(context), Padding(padding: EdgeInsets.only(right: 5), child: _buildAddNewFolderButton(context)),
])), ]
Divider(color: AppColor.colorDividerMailbox, height: 0.5, thickness: 0.2), )
),
if (!_responsiveUtils.isTabletLarge(context))
Divider(color: AppColor.colorDividerMailbox, height: 0.5, thickness: 0.2),
] ]
); );
} }
Widget _buildComposerButton(BuildContext context) {
return Row(children: [
Expanded(child: Container(
padding: EdgeInsets.only(top: 16, left: 20),
color: AppColor.colorBgDesktop,
alignment: Alignment.centerLeft,
child: (ButtonBuilder(_imagePaths.icCompose)
..key(Key('button_compose_email'))
..decoration(BoxDecoration(borderRadius: BorderRadius.circular(25), color: AppColor.colorTextButton))
..paddingIcon(EdgeInsets.only(right: 8))
..iconColor(Colors.white)
..maxWidth(140)
..size(20)
..radiusSplash(10)
..padding(EdgeInsets.symmetric(vertical: 13))
..textStyle(TextStyle(fontSize: 15, color: Colors.white, fontWeight: FontWeight.w500))
..onPressActionClick(() => controller.mailboxDashBoardController.composeEmailAction())
..text(AppLocalizations.of(context).compose, isVertical: false))
.build())
),
Obx(() {
if (controller.isSearchActive()) {
return controller.listMailboxSearched.isNotEmpty
? Padding(
padding: EdgeInsets.only(top: 16),
child: _buildEditMailboxButton(context, controller.isSelectionEnabled()))
: SizedBox.shrink();
} else {
return Padding(
padding: EdgeInsets.only(top: 16),
child: _buildEditMailboxButton(context, controller.isSelectionEnabled()));
}
})
]);
}
Widget _buildCloseScreenButton(BuildContext context) { Widget _buildCloseScreenButton(BuildContext context) {
return Padding( return buildIconWeb(
padding: EdgeInsets.only(left: 16, right: 16), icon: SvgPicture.asset(_imagePaths.icCloseMailbox, width: 28, height: 28, fit: BoxFit.fill),
child: IconButton( tooltip: AppLocalizations.of(context).close,
key: Key('mailbox_close_button'), onTap: () => controller.closeMailboxScreen(context));
onPressed: () => controller.closeMailboxScreen(context),
icon: SvgPicture.asset(_imagePaths.icCloseMailbox, width: 30, height: 30, fit: BoxFit.fill)));
} }
Widget _buildAddNewFolderButton(BuildContext context) { Widget _buildAddNewFolderButton(BuildContext context) {
return Padding( return buildIconWeb(
padding: EdgeInsets.only(right: 10), icon: SvgPicture.asset(_imagePaths.icAddNewFolder, width: 28, height: 24, color: AppColor.colorTextButton, fit: BoxFit.fill),
child: IconButton( tooltip: AppLocalizations.of(context).new_mailbox,
key: Key('create_new_mailbox_button'), onTap: () => controller.goToCreateNewMailboxView());
onPressed: () => controller.goToCreateNewMailboxView(),
icon: SvgPicture.asset(_imagePaths.icAddNewFolder, width: 30, height: 30, fit: BoxFit.fill)));
} }
Widget _buildEditMailboxButton(BuildContext context, bool isSelectionEnabled) { Widget _buildEditMailboxButton(BuildContext context, bool isSelectionEnabled) {
@@ -184,7 +205,7 @@ class MailboxView extends GetWidget<MailboxController> {
child: TextButton( child: TextButton(
child: Text( child: Text(
!isSelectionEnabled ? AppLocalizations.of(context).edit : AppLocalizations.of(context).cancel, !isSelectionEnabled ? AppLocalizations.of(context).edit : AppLocalizations.of(context).cancel,
style: TextStyle(fontSize: 17, color: AppColor.colorTextButton)), style: TextStyle(fontSize: 17, color: AppColor.colorTextButton, fontWeight: FontWeight.normal)),
onPressed: () => !isSelectionEnabled onPressed: () => !isSelectionEnabled
? controller.enableSelectionMailbox() ? controller.enableSelectionMailbox()
: controller.disableSelectionMailbox() : controller.disableSelectionMailbox()
@@ -192,20 +213,28 @@ class MailboxView extends GetWidget<MailboxController> {
); );
} }
Widget _buildUserInformationWidget(BuildContext context) { Widget _buildUserInformation(BuildContext context) {
return Padding( return Container(
padding: EdgeInsets.only(left: 16, top: 8.0, right: 16), child: Column(children: [
child: Obx(() => (UserInformationWidgetBuilder( Padding(
_imagePaths, padding: EdgeInsets.only(
context, left: _responsiveUtils.isMobile(context) && _responsiveUtils.isLandscape(context) ? 0 : 16,
controller.mailboxDashBoardController.userProfile.value) right: 16),
..addOnLogoutAction(() => controller.mailboxDashBoardController.logoutAction())) child: (UserInformationWidgetBuilder(_imagePaths, context, controller.mailboxDashBoardController.userProfile.value)
.build())); ..addOnLogoutAction(() => controller.mailboxDashBoardController.logoutAction()))
.build()),
Divider(color: AppColor.colorDividerMailbox, height: 0.5, thickness: 0.2)
]),
);
} }
Widget _buildSearchBarWidget(BuildContext context) { Widget _buildSearchBarWidget(BuildContext context) {
return Padding( return Padding(
padding: EdgeInsets.only(top: _responsiveUtils.isDesktop(context) ? 16 : 12, bottom: 16, left: 16, right: 16), padding: EdgeInsets.only(
top: _responsiveUtils.isDesktop(context) ? 16 : 12,
bottom: 16,
left: _responsiveUtils.isMobile(context) && _responsiveUtils.isLandscape(context) ? 0 : 16,
right: 16),
child: (SearchBarView(_imagePaths) child: (SearchBarView(_imagePaths)
..hintTextSearch(AppLocalizations.of(context).hint_search_mailboxes) ..hintTextSearch(AppLocalizations.of(context).hint_search_mailboxes)
..addOnOpenSearchViewAction(() => controller.enableSearch())) ..addOnOpenSearchViewAction(() => controller.enableSearch()))
@@ -231,90 +260,80 @@ class MailboxView extends GetWidget<MailboxController> {
key: PageStorageKey('mailbox_list'), key: PageStorageKey('mailbox_list'),
primary: false, primary: false,
shrinkWrap: true, shrinkWrap: true,
padding: EdgeInsets.zero, padding: EdgeInsets.only(bottom: controller.isSelectionEnabled() ? 16 : 0),
children: [ children: [
Obx(() => (controller.isSelectionEnabled() && _responsiveUtils.isMobileDevice(context) && _responsiveUtils.isLandscape(context)) Obx(() {
|| _responsiveUtils.isDesktop(context) ? SizedBox.shrink() : _buildUserInformationWidget(context)), if ((controller.isSelectionEnabled()
Obx(() => (controller.isSelectionEnabled() && _responsiveUtils.isMobileDevice(context) && _responsiveUtils.isLandscape(context)) && _responsiveUtils.isMobile(context)
|| _responsiveUtils.isDesktop(context) ? SizedBox.shrink() : _buildLineSpaceUserInformation()), && _responsiveUtils.isLandscape(context))
|| _responsiveUtils.isDesktop(context)) {
return SizedBox.shrink();
}
return _buildUserInformation(context);
}),
if (!_responsiveUtils.isDesktop(context)) _buildSearchBarWidget(context), if (!_responsiveUtils.isDesktop(context)) _buildSearchBarWidget(context),
_buildLoadingView(), _buildLoadingView(),
Obx(() => controller.defaultMailboxTree.value.root.childrenItems?.isNotEmpty ?? false Obx(() => controller.defaultMailboxTree.value.root.childrenItems?.isNotEmpty ?? false
? Container( ? _buildMailboxCategory(context, MailboxCategories.exchange, controller.defaultMailboxTree.value.root)
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: Colors.white),
margin: EdgeInsets.only(left: 16, right: 16, top: 4),
child: _buildDefaultMailbox(context))
: SizedBox.shrink()), : SizedBox.shrink()),
SizedBox(height: 12),
Obx(() => controller.folderMailboxTree.value.root.childrenItems?.isNotEmpty ?? false Obx(() => controller.folderMailboxTree.value.root.childrenItems?.isNotEmpty ?? false
? Padding( ? _buildMailboxCategory(context, MailboxCategories.folders, controller.folderMailboxTree.value.root)
padding: EdgeInsets.only(left: 25, top: 26, bottom: 12),
child: Text(
AppLocalizations.of(context).folders,
maxLines: 1,
style: TextStyle(fontSize: 20, color: AppColor.colorNameEmail, fontWeight: FontWeight.w600)))
: SizedBox.shrink()), : SizedBox.shrink()),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: Colors.white),
margin: EdgeInsets.only(left: 16, right: 16, bottom: 30),
child: _buildFolderMailbox(context),
),
Obx(() {
if (controller.mailboxDashBoardController.appInformation.value != null) {
return _buildVersionInformation(context, controller.mailboxDashBoardController.appInformation.value!);
} else {
return SizedBox.shrink();
}
}),
] ]
); );
} }
Widget _buildLineSpaceUserInformation() { Widget _buildHeaderMailboxCategory(BuildContext context, MailboxCategories categories) {
return Padding( return Padding(
padding: EdgeInsets.only(top: 16), padding: EdgeInsets.only(
child: Divider(color: AppColor.colorDividerMailbox, height: 0.5, thickness: 0.2)); left: _responsiveUtils.isMobile(context) && _responsiveUtils.isLandscape(context) ? 8 : 28,
right: 16),
child: Row(children: [
Expanded(child: Text(categories.getTitle(context),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 20, color: Colors.black, fontWeight: FontWeight.bold))),
buildIconWeb(
icon: SvgPicture.asset(
categories.getExpandMode(controller.mailboxCategoriesExpandMode.value) == ExpandMode.EXPAND
? _imagePaths.icExpandFolder
: _imagePaths.icCollapseFolder,
color: AppColor.primaryColor, fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).collapse,
onTap: () => controller.toggleMailboxCategories(categories))
]));
} }
Widget _buildDefaultMailbox(BuildContext context) { Widget _buildBodyMailboxCategory(BuildContext context, MailboxCategories categories, MailboxNode mailboxNode) {
return Obx(() => controller.defaultMailboxTree.value.root.childrenItems?.isNotEmpty ?? false final lastNode = mailboxNode.childrenItems?.last;
? Transform(
transform: Matrix4.translationValues(-4.0, 0.0, 0.0), return Container(
child: Padding( decoration: BoxDecoration(borderRadius: BorderRadius.circular(14), color: Colors.white),
padding: EdgeInsets.only(top: 10, bottom: 10), margin: EdgeInsets.only(
child: TreeView( left: _responsiveUtils.isMobile(context) && _responsiveUtils.isLandscape(context) ? 0 : 16,
startExpanded: false, right: 16),
key: Key('default_mailbox_list'), padding: EdgeInsets.only(left: 12, right: 8),
children: _buildListChildTileWidget(context, controller.defaultMailboxTree.value.root))) child: TreeView(
) key: Key('${categories.keyValue}_mailbox_list'),
: SizedBox.shrink() children: _buildListChildTileWidget(context, mailboxNode, lastNode: lastNode)));
);
} }
Widget _buildFolderMailbox(BuildContext context) { Widget _buildMailboxCategory(BuildContext context, MailboxCategories categories, MailboxNode mailboxNode) {
return Obx(() => controller.folderMailboxTree.value.root.childrenItems?.isNotEmpty ?? false return Column(children: [
? Transform( _buildHeaderMailboxCategory(context, categories),
transform: Matrix4.translationValues(-4.0, 0.0, 0.0), AnimatedContainer(
child: Padding( duration: Duration(milliseconds: 400),
padding: EdgeInsets.only(top: 10, bottom: 10), child: categories.getExpandMode(controller.mailboxCategoriesExpandMode.value) == ExpandMode.EXPAND
child: TreeView( ? _buildBodyMailboxCategory(context, categories, mailboxNode)
startExpanded: false, : Offstage())
key: Key('folder_mailbox_list'), ]);
children: _buildListChildTileWidget(context, controller.folderMailboxTree.value.root)))
)
: SizedBox.shrink()
);
} }
List<Widget> _buildListChildTileWidget(BuildContext context, MailboxNode parentNode) { List<Widget> _buildListChildTileWidget(BuildContext context, MailboxNode parentNode, {MailboxNode? lastNode}) {
return parentNode.childrenItems return parentNode.childrenItems
?.map((mailboxNode) => mailboxNode.hasChildren() ?.map((mailboxNode) => mailboxNode.hasChildren()
? Padding( ? TreeViewChild(
padding: EdgeInsets.only(left: 16),
child: TreeViewChild(
context, context,
key: Key('children_tree_mailbox_child'), key: Key('children_tree_mailbox_child'),
isExpanded: mailboxNode.expandMode == ExpandMode.EXPAND, isExpanded: mailboxNode.expandMode == ExpandMode.EXPAND,
@@ -322,25 +341,23 @@ class MailboxView extends GetWidget<MailboxController> {
context, context,
_imagePaths, _imagePaths,
mailboxNode, mailboxNode,
lastNode: lastNode,
allSelectMode: controller.currentSelectMode.value) allSelectMode: controller.currentSelectMode.value)
..addOnOpenMailboxFolderClick((mailboxNode) => controller.openMailbox(context, mailboxNode.item)) ..addOnOpenMailboxFolderClick((mailboxNode) => controller.openMailbox(context, mailboxNode.item))
..addOnExpandFolderActionClick((mailboxNode) => controller.toggleMailboxFolder(mailboxNode)) ..addOnExpandFolderActionClick((mailboxNode) => controller.toggleMailboxFolder(mailboxNode))
..addOnSelectMailboxFolderClick((mailboxNode) => controller.selectMailboxNode(mailboxNode))) ..addOnSelectMailboxFolderClick((mailboxNode) => controller.selectMailboxNode(mailboxNode)))
.build()), .build()),
children: _buildListChildTileWidget(context, mailboxNode) children: _buildListChildTileWidget(context, mailboxNode)
).build()) ).build()
: Padding( : Obx(() => (MailBoxFolderTileBuilder(
padding: EdgeInsets.only(left: 16),
child: Obx(() => (MailBoxFolderTileBuilder(
context, context,
_imagePaths, _imagePaths,
mailboxNode, mailboxNode,
lastNode: lastNode,
allSelectMode: controller.currentSelectMode.value) allSelectMode: controller.currentSelectMode.value)
..addOnOpenMailboxFolderClick((mailboxNode) => controller.openMailbox(context, mailboxNode.item)) ..addOnOpenMailboxFolderClick((mailboxNode) => controller.openMailbox(context, mailboxNode.item))
..addOnSelectMailboxFolderClick((mailboxNode) => controller.selectMailboxNode(mailboxNode))) ..addOnSelectMailboxFolderClick((mailboxNode) => controller.selectMailboxNode(mailboxNode)))
.build(), .build())
)
)
).toList() ?? <Widget>[]; ).toList() ?? <Widget>[];
} }
@@ -388,30 +405,31 @@ class MailboxView extends GetWidget<MailboxController> {
)); ));
} }
Widget _buildListMailboxSearched(BuildContext context, List<PresentationMailbox> listMailbox) { Widget _buildListMailboxSearched(BuildContext context) {
return Container( return Obx(() => Container(
margin: _responsiveUtils.isDesktop(context) margin: _responsiveUtils.isDesktop(context)
? EdgeInsets.only(left: 16, right: 16) ? EdgeInsets.only(left: 16, right: 16)
: EdgeInsets.zero, : EdgeInsets.zero,
decoration: _responsiveUtils.isDesktop(context) decoration: _responsiveUtils.isDesktop(context)
? BoxDecoration(borderRadius: BorderRadius.circular(14), color: Colors.white) ? BoxDecoration(borderRadius: BorderRadius.circular(14), color: Colors.white)
: null, : null,
child: ListView.builder( child: ListView.builder(
padding: EdgeInsets.only(left: 16, right: 8), padding: EdgeInsets.only(left: 16, right: 8),
key: Key('list_mailbox_searched'), key: Key('list_mailbox_searched'),
itemCount: listMailbox.length, itemCount: controller.listMailboxSearched.length,
shrinkWrap: true, shrinkWrap: true,
primary: false, primary: false,
itemBuilder: (context, index) => Obx(() => (MailboxTileBuilder( itemBuilder: (context, index) =>
_imagePaths, Obx(() => (MailboxSearchTileBuilder(
listMailbox[index], _imagePaths,
isSearchActive: controller.isSearchActive(), controller.listMailboxSearched[index],
allSelectMode: controller.currentSelectMode.value, allSelectMode: controller.currentSelectMode.value,
isLastElement: index == listMailbox.length - 1) lastMailbox: controller.listMailboxSearched.last)
..addOnOpenMailboxAction((mailbox) => controller.openMailbox(context, mailbox)) ..addOnOpenMailboxAction((mailbox) => controller.openMailbox(context, mailbox))
..addOnSelectMailboxActionClick((mailbox) => controller.selectMailbox(context, mailbox))) ..addOnSelectMailboxActionClick((mailbox) => controller.selectMailbox(context, mailbox)))
.build())) .build())
); )
));
} }
Widget _buildOptionSelectionMailbox(BuildContext context) { Widget _buildOptionSelectionMailbox(BuildContext context) {
@@ -430,25 +448,24 @@ class MailboxView extends GetWidget<MailboxController> {
} else { } else {
return Column(children: [ return Column(children: [
Divider(color: AppColor.lineItemListColor, height: 1, thickness: 0.2), Divider(color: AppColor.lineItemListColor, height: 1, thickness: 0.2),
Padding( SafeArea(
padding: EdgeInsets.only(bottom: 30, top: 5), child: Padding(
child: (BottomBarSelectionMailboxWidget(context, _imagePaths, controller.listMailboxSelected) padding: EdgeInsets.symmetric(vertical: 8),
..addOnMailboxActionsClick((actions, listMailboxSelected) => controller.pressMailboxSelectionAction(context, actions, listMailboxSelected))) child: (BottomBarSelectionMailboxWidget(context, _imagePaths, controller.listMailboxSelected)
.build() ..addOnMailboxActionsClick((actions, listMailboxSelected) => controller.pressMailboxSelectionAction(context, actions, listMailboxSelected)))
) .build()))
]); ]);
} }
} }
Widget _buildVersionInformation(BuildContext context, PackageInfo packageInfo) { Widget _buildVersionInformation(BuildContext context, PackageInfo packageInfo) {
return Container( return SafeArea(child: Container(
padding: EdgeInsets.symmetric(vertical: 16, horizontal: 16), padding: EdgeInsets.symmetric(vertical: 16, horizontal: 16),
margin: EdgeInsets.only(bottom: 30),
child: Text( child: Text(
'${AppLocalizations.of(context).version} ${packageInfo.version}', '${AppLocalizations.of(context).version} ${packageInfo.version}',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle(fontSize: 16, color: AppColor.colorContentEmail, fontWeight: FontWeight.w500), style: TextStyle(fontSize: 16, color: AppColor.colorContentEmail, fontWeight: FontWeight.w500),
), ),
); ));
} }
} }
@@ -0,0 +1,453 @@
import 'package:core/core.dart';
import 'package:flutter/cupertino.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:package_info_plus/package_info_plus.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_controller.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/bottom_bar_selection_mailbox_widget.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/user_information_widget_builder.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/search_app_bar_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class MailboxView extends GetWidget<MailboxController> {
final _imagePaths = Get.find<ImagePaths>();
final _responsiveUtils = Get.find<ResponsiveUtils>();
@override
Widget build(BuildContext context) {
return _buildBodyMailbox(context);
}
Widget _buildBodyMailbox(BuildContext context) {
return SafeArea(
top: _responsiveUtils.isMobile(context) ? true : false,
bottom: false,
left: false,
right: false,
child: ClipRRect(
borderRadius: BorderRadius.only(
topRight: Radius.circular(_responsiveUtils.isMobile(context) ? 14 : 0),
topLeft: Radius.circular(_responsiveUtils.isMobile(context) ? 14 : 0)),
child: Drawer(
child: Scaffold(
backgroundColor: _responsiveUtils.isDesktop(context) ? AppColor.colorBgDesktop : Colors.white,
body: Column(
children: [
if (_responsiveUtils.isDesktop(context))
Container(
color: Colors.white,
padding: EdgeInsets.only(left: 20, top: 20, bottom: 24),
child: (SloganBuilder(arrangedByHorizontal: true)
..setSloganText(AppLocalizations.of(context).app_name)
..setSloganTextAlign(TextAlign.center)
..setSloganTextStyle(TextStyle(color: Colors.black, fontSize: 25, fontWeight: FontWeight.bold))
..setSizeLogo(28)
..setLogo(_imagePaths.icLogoTMail))
.build()),
if (!_responsiveUtils.isDesktop(context)) _buildHeaderMailbox(context),
if (_responsiveUtils.isDesktop(context))
Row(children: [
Expanded(child: Container(
padding: EdgeInsets.only(top: 16, left: 20),
color: AppColor.colorBgDesktop,
alignment: Alignment.centerLeft,
child: (ButtonBuilder(_imagePaths.icCompose)
..key(Key('button_compose_email'))
..decoration(BoxDecoration(borderRadius: BorderRadius.circular(25), color: AppColor.colorTextButton))
..paddingIcon(EdgeInsets.only(right: 8))
..iconColor(Colors.white)
..maxWidth(140)
..size(20)
..radiusSplash(10)
..padding(EdgeInsets.symmetric(vertical: 13))
..textStyle(TextStyle(fontSize: 15, color: Colors.white, fontWeight: FontWeight.w500))
..onPressActionClick(() => controller.mailboxDashBoardController.composeEmailAction())
..text(AppLocalizations.of(context).compose, isVertical: false))
.build())
),
Obx(() {
if (controller.isSearchActive()) {
return controller.listMailboxSearched.isNotEmpty
? Padding(
padding: EdgeInsets.only(top: 16),
child: _buildEditMailboxButton(context, controller.isSelectionEnabled()))
: SizedBox.shrink();
} else {
return Padding(
padding: EdgeInsets.only(top: 16),
child: _buildEditMailboxButton(context, controller.isSelectionEnabled()));
}
})
]),
Obx(() => !controller.isSearchActive() && _responsiveUtils.isDesktop(context)
? Row(children: [
Expanded(child: _buildSearchBarWidget(context)),
buildIconWeb(
icon: SvgPicture.asset(_imagePaths.icAddNewFolder, color: AppColor.colorTextButton, fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).new_mailbox,
onTap: () => controller.goToCreateNewMailboxView()),
])
: SizedBox.shrink()),
Obx(() => controller.isSearchActive() ? _buildInputSearchFormWidget(context) : SizedBox.shrink()),
Expanded(child: Obx(() => Container(
color: _responsiveUtils.isDesktop(context)
? Colors.transparent
: controller.isSearchActive() ? Colors.white : AppColor.colorBgMailbox,
child: RefreshIndicator(
color: AppColor.primaryColor,
onRefresh: () async => controller.refreshAllMailbox(),
child: controller.isSearchActive()
? _buildListMailboxSearched(context, controller.listMailboxSearched)
: _buildListMailbox(context)),
))),
Obx(() => controller.isSelectionEnabled()
? _buildOptionSelectionMailbox(context)
: SizedBox.shrink()),
]
),
)
)
)
);
}
Widget _buildHeaderMailbox(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(
top: _responsiveUtils.isMobile(context) ? 14 : 30,
bottom: 10),
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
!_responsiveUtils.isDesktop(context) && !_responsiveUtils.isTabletLarge(context)
? _buildCloseScreenButton(context)
: SizedBox(width: 50),
Obx(() {
if (controller.isSearchActive()) {
return controller.listMailboxSearched.isNotEmpty
? SizedBox(width: controller.isSelectionEnabled() ? 49 : 40)
: SizedBox.shrink();
} else {
return SizedBox(width: controller.isSelectionEnabled() ? 49 : 40);
}
}),
Expanded(child: Text(
AppLocalizations.of(context).folders,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20, color: AppColor.colorNameEmail, fontWeight: FontWeight.w700))),
Obx(() {
if (controller.isSearchActive()) {
return controller.listMailboxSearched.isNotEmpty
? _buildEditMailboxButton(context, controller.isSelectionEnabled())
: SizedBox(width: 25);
} else {
return _buildEditMailboxButton(context, controller.isSelectionEnabled());
}
}),
_buildAddNewFolderButton(context),
])),
Divider(color: AppColor.colorDividerMailbox, height: 0.5, thickness: 0.2),
]
);
}
Widget _buildCloseScreenButton(BuildContext context) {
return Padding(
padding: EdgeInsets.only(left: 16, right: 16),
child: IconButton(
key: Key('mailbox_close_button'),
onPressed: () => controller.closeMailboxScreen(context),
icon: SvgPicture.asset(_imagePaths.icCloseMailbox, width: 30, height: 30, fit: BoxFit.fill)));
}
Widget _buildAddNewFolderButton(BuildContext context) {
return Padding(
padding: EdgeInsets.only(right: 10),
child: IconButton(
key: Key('create_new_mailbox_button'),
onPressed: () => controller.goToCreateNewMailboxView(),
icon: SvgPicture.asset(_imagePaths.icAddNewFolder, width: 30, height: 30, fit: BoxFit.fill)));
}
Widget _buildEditMailboxButton(BuildContext context, bool isSelectionEnabled) {
return Material(
shape: CircleBorder(),
color: Colors.transparent,
child: TextButton(
child: Text(
!isSelectionEnabled ? AppLocalizations.of(context).edit : AppLocalizations.of(context).cancel,
style: TextStyle(fontSize: 17, color: AppColor.colorTextButton)),
onPressed: () => !isSelectionEnabled
? controller.enableSelectionMailbox()
: controller.disableSelectionMailbox()
)
);
}
Widget _buildUserInformationWidget(BuildContext context) {
return Padding(
padding: EdgeInsets.only(left: 16, top: 8.0, right: 16),
child: Obx(() => (UserInformationWidgetBuilder(
_imagePaths,
context,
controller.mailboxDashBoardController.userProfile.value)
..addOnLogoutAction(() => controller.mailboxDashBoardController.logoutAction()))
.build()));
}
Widget _buildSearchBarWidget(BuildContext context) {
return Padding(
padding: EdgeInsets.only(top: _responsiveUtils.isDesktop(context) ? 16 : 12, bottom: 16, left: 16, right: 16),
child: (SearchBarView(_imagePaths)
..hintTextSearch(AppLocalizations.of(context).hint_search_mailboxes)
..addOnOpenSearchViewAction(() => controller.enableSearch()))
.build());
}
Widget _buildLoadingView() {
return Obx(() => controller.viewState.value.fold(
(failure) => SizedBox.shrink(),
(success) => success is LoadingState
? Center(child: Padding(
padding: EdgeInsets.only(top: 16),
child: SizedBox(
width: 24,
height: 24,
child: CupertinoActivityIndicator(color: AppColor.colorTextButton))))
: SizedBox.shrink()));
}
Widget _buildListMailbox(BuildContext context) {
return ListView(
controller: controller.mailboxListScrollController,
key: PageStorageKey('mailbox_list'),
primary: false,
shrinkWrap: true,
padding: EdgeInsets.zero,
children: [
Obx(() => (controller.isSelectionEnabled() && _responsiveUtils.isMobileDevice(context) && _responsiveUtils.isLandscape(context))
|| _responsiveUtils.isDesktop(context) ? SizedBox.shrink() : _buildUserInformationWidget(context)),
Obx(() => (controller.isSelectionEnabled() && _responsiveUtils.isMobileDevice(context) && _responsiveUtils.isLandscape(context))
|| _responsiveUtils.isDesktop(context) ? SizedBox.shrink() : _buildLineSpaceUserInformation()),
if (!_responsiveUtils.isDesktop(context)) _buildSearchBarWidget(context),
_buildLoadingView(),
Obx(() => controller.defaultMailboxTree.value.root.childrenItems?.isNotEmpty ?? false
? Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: Colors.white),
margin: EdgeInsets.only(left: 16, right: 16, top: 4),
child: _buildDefaultMailbox(context))
: SizedBox.shrink()),
Obx(() => controller.folderMailboxTree.value.root.childrenItems?.isNotEmpty ?? false
? Padding(
padding: EdgeInsets.only(left: 25, top: 26, bottom: 12),
child: Text(
AppLocalizations.of(context).folders,
maxLines: 1,
style: TextStyle(fontSize: 20, color: AppColor.colorNameEmail, fontWeight: FontWeight.w600)))
: SizedBox.shrink()),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: Colors.white),
margin: EdgeInsets.only(left: 16, right: 16, bottom: 30),
child: _buildFolderMailbox(context),
),
Obx(() {
if (controller.mailboxDashBoardController.appInformation.value != null) {
return _buildVersionInformation(context, controller.mailboxDashBoardController.appInformation.value!);
} else {
return SizedBox.shrink();
}
}),
]
);
}
Widget _buildLineSpaceUserInformation() {
return Padding(
padding: EdgeInsets.only(top: 16),
child: Divider(color: AppColor.colorDividerMailbox, height: 0.5, thickness: 0.2));
}
Widget _buildDefaultMailbox(BuildContext context) {
return Obx(() => controller.defaultMailboxTree.value.root.childrenItems?.isNotEmpty ?? false
? Transform(
transform: Matrix4.translationValues(-4.0, 0.0, 0.0),
child: Padding(
padding: EdgeInsets.only(top: 10, bottom: 10),
child: TreeView(
startExpanded: false,
key: Key('default_mailbox_list'),
children: _buildListChildTileWidget(context, controller.defaultMailboxTree.value.root)))
)
: SizedBox.shrink()
);
}
Widget _buildFolderMailbox(BuildContext context) {
return Obx(() => controller.folderMailboxTree.value.root.childrenItems?.isNotEmpty ?? false
? Transform(
transform: Matrix4.translationValues(-4.0, 0.0, 0.0),
child: Padding(
padding: EdgeInsets.only(top: 10, bottom: 10),
child: TreeView(
startExpanded: false,
key: Key('folder_mailbox_list'),
children: _buildListChildTileWidget(context, controller.folderMailboxTree.value.root)))
)
: SizedBox.shrink()
);
}
List<Widget> _buildListChildTileWidget(BuildContext context, MailboxNode parentNode) {
return parentNode.childrenItems
?.map((mailboxNode) => mailboxNode.hasChildren()
? Padding(
padding: EdgeInsets.only(left: 16),
child: TreeViewChild(
context,
key: Key('children_tree_mailbox_child'),
isExpanded: mailboxNode.expandMode == ExpandMode.EXPAND,
parent: Obx(() => (MailBoxFolderTileBuilder(
context,
_imagePaths,
mailboxNode,
allSelectMode: controller.currentSelectMode.value)
..addOnOpenMailboxFolderClick((mailboxNode) => controller.openMailbox(context, mailboxNode.item))
..addOnExpandFolderActionClick((mailboxNode) => controller.toggleMailboxFolder(mailboxNode))
..addOnSelectMailboxFolderClick((mailboxNode) => controller.selectMailboxNode(mailboxNode)))
.build()),
children: _buildListChildTileWidget(context, mailboxNode)
).build())
: Padding(
padding: EdgeInsets.only(left: 16),
child: Obx(() => (MailBoxFolderTileBuilder(
context,
_imagePaths,
mailboxNode,
allSelectMode: controller.currentSelectMode.value)
..addOnOpenMailboxFolderClick((mailboxNode) => controller.openMailbox(context, mailboxNode.item))
..addOnSelectMailboxFolderClick((mailboxNode) => controller.selectMailboxNode(mailboxNode)))
.build(),
)
)
).toList() ?? <Widget>[];
}
Widget _buildInputSearchFormWidget(BuildContext context) {
return Padding(
padding: EdgeInsets.only(top: 16, bottom: 16),
child: Row(
children: [
_buildBackSearchButton(context),
Expanded(child: (SearchAppBarWidget(
context,
_imagePaths,
_responsiveUtils,
controller.searchQuery.value,
controller.searchFocus,
controller.searchInputController,
hasBackButton: false,
hasSearchButton: true)
..addPadding(EdgeInsets.zero)
..setMargin(EdgeInsets.only(right: 16))
..addDecoration(BoxDecoration(borderRadius: BorderRadius.circular(12), color: AppColor.colorBgSearchBar))
..addIconClearText(SvgPicture.asset(_imagePaths.icClearTextSearch, width: 20, height: 20, fit: BoxFit.fill))
..setHintText(AppLocalizations.of(context).hint_search_mailboxes)
..addOnClearTextSearchAction(() => controller.clearSearchText())
..addOnTextChangeSearchAction((query) => controller.searchMailbox(query))
..addOnSearchTextAction((query) => controller.searchMailbox(query)))
.build())
]
)
);
}
Widget _buildBackSearchButton(BuildContext context) {
return Padding(
padding: EdgeInsets.only(left: 5),
child: Material(
shape: CircleBorder(),
color: Colors.transparent,
child: IconButton(
splashRadius: 20,
color: AppColor.colorTextButton,
icon: SvgPicture.asset(_imagePaths.icBack, width: 20, height: 20, color: AppColor.colorTextButton, fit: BoxFit.fill),
onPressed: () => controller.disableSearch(context)
)
));
}
Widget _buildListMailboxSearched(BuildContext context, List<PresentationMailbox> listMailbox) {
return Container(
margin: _responsiveUtils.isDesktop(context)
? EdgeInsets.only(left: 16, right: 16)
: EdgeInsets.zero,
decoration: _responsiveUtils.isDesktop(context)
? BoxDecoration(borderRadius: BorderRadius.circular(14), color: Colors.white)
: null,
child: ListView.builder(
padding: EdgeInsets.only(left: 16, right: 8),
key: Key('list_mailbox_searched'),
itemCount: listMailbox.length,
shrinkWrap: true,
primary: false,
itemBuilder: (context, index) => Obx(() => (MailboxSearchTileBuilder(
_imagePaths,
listMailbox[index],
allSelectMode: controller.currentSelectMode.value,
lastMailbox: controller.listMailboxSearched.last)
..addOnOpenMailboxAction((mailbox) => controller.openMailbox(context, mailbox))
..addOnSelectMailboxActionClick((mailbox) => controller.selectMailbox(context, mailbox)))
.build()))
);
}
Widget _buildOptionSelectionMailbox(BuildContext context) {
if (_responsiveUtils.isDesktop(context)) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
boxShadow: [BoxShadow(color: AppColor.colorEmailAddressTag, spreadRadius: 1, blurRadius: 1, offset: Offset(0, 0.5))],
color: Colors.white),
margin: EdgeInsets.only(left: 10, bottom: 10, right: 10),
padding: EdgeInsets.all(8),
child: (BottomBarSelectionMailboxWidget(context, _imagePaths, controller.listMailboxSelected)
..addOnMailboxActionsClick((actions, listMailboxSelected) => controller.pressMailboxSelectionAction(context, actions, listMailboxSelected)))
.build(),
);
} else {
return Column(children: [
Divider(color: AppColor.lineItemListColor, height: 1, thickness: 0.2),
Padding(
padding: EdgeInsets.only(bottom: 30, top: 5),
child: (BottomBarSelectionMailboxWidget(context, _imagePaths, controller.listMailboxSelected)
..addOnMailboxActionsClick((actions, listMailboxSelected) => controller.pressMailboxSelectionAction(context, actions, listMailboxSelected)))
.build()
)
]);
}
}
Widget _buildVersionInformation(BuildContext context, PackageInfo packageInfo) {
return Container(
padding: EdgeInsets.symmetric(vertical: 16, horizontal: 16),
margin: EdgeInsets.only(bottom: 30),
child: Text(
'${AppLocalizations.of(context).version} ${packageInfo.version}',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16, color: AppColor.colorContentEmail, fontWeight: FontWeight.w500),
),
);
}
}
@@ -0,0 +1,40 @@
import 'package:flutter/cupertino.dart';
import 'package:model/mailbox/expand_mode.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_categories_expand_mode.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
enum MailboxCategories {
exchange,
folders,
}
extension MailboxCategoriessExtension on MailboxCategories {
String get keyValue {
switch(this) {
case MailboxCategories.exchange:
return 'exchange';
case MailboxCategories.folders:
return 'folders';
}
}
String getTitle(BuildContext context) {
switch(this) {
case MailboxCategories.exchange:
return AppLocalizations.of(context).exchange;
case MailboxCategories.folders:
return AppLocalizations.of(context).folders;
}
}
ExpandMode getExpandMode(MailboxCategoriesExpandMode categoriesExpandMode) {
switch(this) {
case MailboxCategories.exchange:
return categoriesExpandMode.defaultMailbox;
case MailboxCategories.folders:
return categoriesExpandMode.folderMailbox;
}
}
}
@@ -0,0 +1,17 @@
import 'package:equatable/equatable.dart';
import 'package:model/mailbox/expand_mode.dart';
class MailboxCategoriesExpandMode with EquatableMixin {
ExpandMode defaultMailbox;
ExpandMode folderMailbox;
MailboxCategoriesExpandMode({required this.defaultMailbox, required this.folderMailbox});
factory MailboxCategoriesExpandMode.initial() {
return MailboxCategoriesExpandMode(defaultMailbox: ExpandMode.EXPAND, folderMailbox: ExpandMode.EXPAND);
}
@override
List<Object?> get props => [defaultMailbox, folderMailbox];
}
@@ -18,6 +18,7 @@ class MailBoxFolderTileBuilder {
final ImagePaths _imagePaths; final ImagePaths _imagePaths;
final SelectMode allSelectMode; final SelectMode allSelectMode;
final MailboxDisplayed mailboxDisplayed; final MailboxDisplayed mailboxDisplayed;
final MailboxNode? lastNode;
OnExpandFolderActionClick? _onExpandFolderActionClick; OnExpandFolderActionClick? _onExpandFolderActionClick;
OnOpenMailboxFolderClick? _onOpenMailboxFolderClick; OnOpenMailboxFolderClick? _onOpenMailboxFolderClick;
@@ -30,6 +31,7 @@ class MailBoxFolderTileBuilder {
{ {
this.allSelectMode = SelectMode.INACTIVE, this.allSelectMode = SelectMode.INACTIVE,
this.mailboxDisplayed = MailboxDisplayed.mailbox, this.mailboxDisplayed = MailboxDisplayed.mailbox,
this.lastNode,
} }
); );
@@ -52,7 +54,6 @@ class MailBoxFolderTileBuilder {
highlightColor: Colors.transparent), highlightColor: Colors.transparent),
child: Container( child: Container(
key: Key('mailbox_folder_tile'), key: Key('mailbox_folder_tile'),
alignment: Alignment.center,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(0), borderRadius: BorderRadius.circular(0),
color: Colors.white color: Colors.white
@@ -70,21 +71,26 @@ class MailBoxFolderTileBuilder {
: _buildMailboxIcon(), : _buildMailboxIcon(),
title: _buildTitleFolderItem(), title: _buildTitleFolderItem(),
trailing: _mailboxNode.hasChildren() trailing: _mailboxNode.hasChildren()
? Padding( ? Transform(
padding: EdgeInsets.only(right: 0, left: 16), transform: Matrix4.translationValues(8.0, 0.0, 0.0),
child: buildIconWeb( child: buildIconWeb(
icon: SvgPicture.asset( icon: SvgPicture.asset(
_mailboxNode.expandMode == ExpandMode.EXPAND ? _imagePaths.icExpandFolder : _imagePaths.icFolderArrow, _mailboxNode.expandMode == ExpandMode.EXPAND ? _imagePaths.icExpandFolder : _imagePaths.icCollapseFolder,
color: AppColor.colorArrowUserMailbox, color: _mailboxNode.expandMode == ExpandMode.EXPAND ? AppColor.colorExpandMailbox : AppColor.colorCollapseMailbox,
fit: BoxFit.fill), fit: BoxFit.fill),
splashRadius: 15, splashRadius: 15,
tooltip: _mailboxNode.expandMode == ExpandMode.EXPAND ? AppLocalizations.of(_context).collapse : AppLocalizations.of(_context).expand, tooltip: _mailboxNode.expandMode == ExpandMode.EXPAND ? AppLocalizations.of(_context).collapse : AppLocalizations.of(_context).expand,
onTap: () => _onExpandFolderActionClick?.call(_mailboxNode))) onTap: () => _onExpandFolderActionClick?.call(_mailboxNode)))
: null : _mailboxNode.item.getCountUnReadEmails().isNotEmpty
&& mailboxDisplayed == MailboxDisplayed.mailbox
&& !_mailboxNode.hasChildren()
? Padding(padding: EdgeInsets.only(right: 12), child: _buildCounter())
: SizedBox.shrink()
), ),
Padding( if (lastNode?.item.id != _mailboxNode.item.id)
padding: EdgeInsets.only(left: allSelectMode == SelectMode.ACTIVE ? 50 : 45), Padding(
child: Divider(color: AppColor.lineItemListColor, height: 0.5, thickness: 0.2)), padding: EdgeInsets.only(left: allSelectMode == SelectMode.ACTIVE ? 50 : 35),
child: Divider(color: AppColor.lineItemListColor, height: 0.5, thickness: 0.2)),
]) ])
) )
) )
@@ -96,70 +102,48 @@ class MailBoxFolderTileBuilder {
children: [ children: [
if (allSelectMode == SelectMode.ACTIVE) if (allSelectMode == SelectMode.ACTIVE)
Transform( Transform(
transform: Matrix4.translationValues(-16.0, 0.0, 0.0), transform: Matrix4.translationValues(-24.0, 0.0, 0.0),
child: _buildMailboxIcon()), child: _buildMailboxIcon()),
Expanded(child: Transform( Expanded(child: Transform(
transform: Matrix4.translationValues(-10.0, 0.0, 0.0), transform: Matrix4.translationValues(allSelectMode == SelectMode.ACTIVE ? -16.0 : -20.0, 0.0, 0.0),
child: Text( child: Text(
'${_mailboxNode.item.name?.name ?? ''}', '${_mailboxNode.item.name?.name ?? ''}',
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(fontSize: 15, color: AppColor.colorNameEmail, fontWeight: FontWeight.normal),
fontSize: 15,
color: AppColor.colorNameEmail),
))), ))),
if (_mailboxNode.item.getCountUnReadEmails().isNotEmpty && mailboxDisplayed == MailboxDisplayed.mailbox) if (_mailboxNode.item.getCountUnReadEmails().isNotEmpty && mailboxDisplayed == MailboxDisplayed.mailbox && _mailboxNode.hasChildren())
!_mailboxNode.hasChildren() Transform(transform: Matrix4.translationValues(30.0, 0.0, 0.0), child: _buildCounter())
? _buildCounter()
: Transform(
transform: Matrix4.translationValues(40.0, 0.0, 0.0),
child: _buildCounter())
], ],
); );
} }
Widget _buildCounter() { Widget _buildCounter() {
return Container( return Text(
margin: EdgeInsets.only(left: 8, right: _mailboxNode.hasChildren() ? 0 : 16), '${_mailboxNode.item.getCountUnReadEmails()}',
padding: EdgeInsets.only(left: 8, right: 8, top: 2.5, bottom: 2.5), maxLines: 1,
decoration:BoxDecoration( overflow: TextOverflow.ellipsis,
borderRadius: BorderRadius.circular(8), style: TextStyle(fontSize: 13, color: Colors.black, fontWeight: FontWeight.normal),
color: AppColor.backgroundCounterMailboxColor), );
child: Text(
'${_mailboxNode.item.getCountUnReadEmails()} ${AppLocalizations.of(_context).unread_email_notification}',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 12, color: AppColor.colorNameEmail),
));
} }
Widget _buildMailboxIcon() { Widget _buildMailboxIcon() {
return Padding( return SvgPicture.asset(
padding: EdgeInsets.only( '${_mailboxNode.item.getMailboxIcon(_imagePaths)}',
left: allSelectMode == SelectMode.ACTIVE ? 0 : 8, width: 28,
right: allSelectMode == SelectMode.ACTIVE ? 8 : 0), height: 28,
child: SvgPicture.asset( fit: BoxFit.fill
'${_mailboxNode.item.getMailboxIcon(_imagePaths)}',
width: 28,
height: 28,
fit: BoxFit.fill
)
); );
} }
Widget _buildSelectModeIcon() { Widget _buildSelectModeIcon() {
return Material( return Transform(
borderRadius: BorderRadius.circular(10), transform: Matrix4.translationValues(-10.0, 0.0, 0.0),
color: Colors.transparent, child: buildIconWeb(
child: IconButton(
padding: EdgeInsets.zero,
icon: SvgPicture.asset( icon: SvgPicture.asset(
_mailboxNode.selectMode == SelectMode.ACTIVE ? _imagePaths.icSelected : _imagePaths.icUnSelected, _mailboxNode.selectMode == SelectMode.ACTIVE ? _imagePaths.icSelected : _imagePaths.icUnSelected,
width: 20,
height: 20,
fit: BoxFit.fill), fit: BoxFit.fill),
onPressed: () => _onSelectMailboxFolderClick?.call(_mailboxNode) splashRadius: 15,
) onTap: () => _onSelectMailboxFolderClick?.call(_mailboxNode)));
);
} }
} }
@@ -3,31 +3,26 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:model/model.dart'; import 'package:model/model.dart';
import 'package:tmail_ui_user/features/mailbox/domain/extensions/presentation_mailbox_extension.dart'; import 'package:tmail_ui_user/features/mailbox/domain/extensions/presentation_mailbox_extension.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_displayed.dart';
typedef OnOpenMailboxActionClick = void Function(PresentationMailbox); typedef OnOpenMailboxActionClick = void Function(PresentationMailbox);
typedef OnSelectMailboxActionClick = void Function(PresentationMailbox); typedef OnSelectMailboxActionClick = void Function(PresentationMailbox);
class MailboxTileBuilder { class MailboxSearchTileBuilder {
final PresentationMailbox _presentationMailbox; final PresentationMailbox _presentationMailbox;
final PresentationMailbox? lastMailbox;
final SelectMode allSelectMode; final SelectMode allSelectMode;
final ImagePaths _imagePaths; final ImagePaths _imagePaths;
final MailboxDisplayed mailboxDisplayed;
final bool isLastElement;
final bool isSearchActive;
OnOpenMailboxActionClick? _onOpenMailboxActionClick; OnOpenMailboxActionClick? _onOpenMailboxActionClick;
OnSelectMailboxActionClick? _onSelectMailboxActionClick; OnSelectMailboxActionClick? _onSelectMailboxActionClick;
MailboxTileBuilder( MailboxSearchTileBuilder(
this._imagePaths, this._imagePaths,
this._presentationMailbox, this._presentationMailbox,
{ {
this.allSelectMode = SelectMode.INACTIVE, this.allSelectMode = SelectMode.INACTIVE,
this.mailboxDisplayed = MailboxDisplayed.mailbox, this.lastMailbox,
this.isLastElement = false,
this.isSearchActive = false,
} }
); );
@@ -62,30 +57,23 @@ class MailboxTileBuilder {
leading: allSelectMode == SelectMode.ACTIVE leading: allSelectMode == SelectMode.ACTIVE
? _buildSelectModeIcon() ? _buildSelectModeIcon()
: _buildMailboxIcon(), : _buildMailboxIcon(),
title: Transform( title: Row(children: [
transform: Matrix4.translationValues(-10.0, 0.0, 0.0),
child: Row(children: [
if (allSelectMode == SelectMode.ACTIVE) if (allSelectMode == SelectMode.ACTIVE)
Transform( Transform(
transform: Matrix4.translationValues(-10.0, 0.0, 0.0), transform: Matrix4.translationValues(-24.0, 0.0, 0.0),
child: _buildMailboxIcon()), child: _buildMailboxIcon()),
Expanded(child: Text( Expanded(child: Transform(
'${_presentationMailbox.name?.name ?? ''}', transform: Matrix4.translationValues(allSelectMode == SelectMode.ACTIVE ? -16.0 : -20.0, 0.0, 0.0),
maxLines: 1, child: Text(
overflow:TextOverflow.ellipsis, '${_presentationMailbox.name?.name ?? ''}',
style: TextStyle(fontSize: isSearchActive ? 17 : 15, color: AppColor.colorNameEmail), maxLines: 1,
)), overflow:TextOverflow.ellipsis,
if (mailboxDisplayed == MailboxDisplayed.mailbox && !isSearchActive) style: TextStyle(fontSize: 17, color: AppColor.colorNameEmail, fontWeight: FontWeight.normal),
Transform( ))),
transform: Matrix4.translationValues(40.0, 0.0, 0.0), ]),
child: Text( subtitle: _presentationMailbox.mailboxPath?.isNotEmpty == true
'${_presentationMailbox.getCountUnReadEmails()}',
maxLines: 1,
style: TextStyle(fontSize: 13, color: AppColor.colorNameEmail)))
])),
subtitle: isSearchActive && _presentationMailbox.mailboxPath?.isNotEmpty == true
? Transform( ? Transform(
transform: Matrix4.translationValues(-10.0, 0.0, 0.0), transform: Matrix4.translationValues(allSelectMode == SelectMode.ACTIVE ? 12.0 : -20.0, 0.0, 0.0),
child: Text( child: Text(
_presentationMailbox.mailboxPath ?? '', _presentationMailbox.mailboxPath ?? '',
maxLines: 1, maxLines: 1,
@@ -94,18 +82,8 @@ class MailboxTileBuilder {
), ),
) )
: null, : null,
trailing: (mailboxDisplayed == MailboxDisplayed.mailbox && !isSearchActive)
? Transform(
transform: Matrix4.translationValues(8.0, 0.0, 0.0),
child: IconButton(
color: AppColor.primaryColor,
icon: SvgPicture.asset(_imagePaths.icFolderArrow, color: AppColor.colorArrowUserMailbox, fit: BoxFit.fill),
onPressed: () => _onOpenMailboxActionClick?.call(_presentationMailbox)
)
)
: null
), ),
if (!isLastElement) if (lastMailbox?.id != _presentationMailbox.id)
Padding( Padding(
padding: EdgeInsets.only(left: allSelectMode == SelectMode.ACTIVE ? 50 : 45), padding: EdgeInsets.only(left: allSelectMode == SelectMode.ACTIVE ? 50 : 45),
child: Divider(color: AppColor.lineItemListColor, height: 0.5, thickness: 0.2)), child: Divider(color: AppColor.lineItemListColor, height: 0.5, thickness: 0.2)),
@@ -116,32 +94,22 @@ class MailboxTileBuilder {
} }
Widget _buildMailboxIcon() { Widget _buildMailboxIcon() {
return Padding( return SvgPicture.asset(
padding: EdgeInsets.only( '${_presentationMailbox.getMailboxIcon(_imagePaths)}',
left: allSelectMode == SelectMode.ACTIVE ? 4 : 8, width: 28,
right: allSelectMode == SelectMode.ACTIVE ? 4 : 0), height: 28,
child: SvgPicture.asset( fit: BoxFit.fill
'${_presentationMailbox.getMailboxIcon(_imagePaths)}',
width: 28,
height: 28,
fit: BoxFit.fill
)
); );
} }
Widget _buildSelectModeIcon() { Widget _buildSelectModeIcon() {
return Material( return Transform(
borderRadius: BorderRadius.circular(10), transform: Matrix4.translationValues(-10.0, 0.0, 0.0),
color: Colors.transparent, child: buildIconWeb(
child: IconButton(
padding: EdgeInsets.zero,
icon: SvgPicture.asset( icon: SvgPicture.asset(
_presentationMailbox.selectMode == SelectMode.ACTIVE ? _imagePaths.icSelected : _imagePaths.icUnSelected, _presentationMailbox.selectMode == SelectMode.ACTIVE ? _imagePaths.icSelected : _imagePaths.icUnSelected,
width: 20,
height: 20,
fit: BoxFit.fill), fit: BoxFit.fill),
onPressed: () => _onSelectMailboxActionClick?.call(_presentationMailbox) splashRadius: 15,
) onTap: () => _onSelectMailboxActionClick?.call(_presentationMailbox)));
);
} }
} }
@@ -75,7 +75,7 @@ class UserInformationWidgetBuilder {
Transform( Transform(
transform: Matrix4.translationValues(14.0, 0.0, 0.0), transform: Matrix4.translationValues(14.0, 0.0, 0.0),
child: IconButton( child: IconButton(
icon: SvgPicture.asset(_imagePaths.icNextArrow, width: 7, height: 12, fit: BoxFit.fill, color: AppColor.colorArrowUserMailbox), icon: SvgPicture.asset(_imagePaths.icCollapseFolder, fit: BoxFit.fill, color: AppColor.colorCollapseMailbox),
onPressed: () => {})) onPressed: () => {}))
]), ]),
); );
@@ -168,7 +168,7 @@ class MailboxCreatorView extends GetWidget<MailboxCreatorController> {
transform: Matrix4.translationValues(4.0, 0.0, 0.0), transform: Matrix4.translationValues(4.0, 0.0, 0.0),
child: IconButton( child: IconButton(
color: AppColor.primaryColor, color: AppColor.primaryColor,
icon: SvgPicture.asset(_imagePaths.icFolderArrow, color: AppColor.colorArrowUserMailbox, fit: BoxFit.fill), icon: SvgPicture.asset(_imagePaths.icCollapseFolder, color: AppColor.colorCollapseMailbox, fit: BoxFit.fill),
onPressed: () => controller.selectMailboxLocation(context) onPressed: () => controller.selectMailboxLocation(context)
)) ))
), ),
@@ -2,8 +2,7 @@ import 'package:core/core.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/mixin/network_connection_mixin.dart'; import 'package:tmail_ui_user/features/base/mixin/network_connection_mixin.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart' import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart';
if (dart.library.html) 'package:tmail_ui_user/features/composer/presentation/composer_view_web.dart';
import 'package:tmail_ui_user/features/email/presentation/email_view.dart'; import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_view.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_view.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
@@ -23,9 +22,10 @@ class MailboxDashBoardView extends GetWidget<MailboxDashBoardController> with Ne
key: controller.scaffoldKey, key: controller.scaffoldKey,
drawer: ResponsiveWidget( drawer: ResponsiveWidget(
responsiveUtils: _responsiveUtils, responsiveUtils: _responsiveUtils,
mobile: Container(child: MailboxView(), mobile: _responsiveUtils.isPortrait(context)
width: _responsiveUtils.isPortrait(context) ? _responsiveUtils.getSizeScreenWidth(context) : _responsiveUtils.getSizeScreenWidth(context) / 2), ? SizedBox(child: MailboxView(), width: double.infinity)
tablet: Container(child: MailboxView(), width: _responsiveUtils.getSizeScreenWidth(context) / 2), : SizedBox(child: MailboxView(), width: _responsiveUtils.defaultSizeDrawerWidthMobileTablet),
tablet: SizedBox(child: MailboxView(), width: _responsiveUtils.defaultSizeDrawerWidthMobileTablet),
tabletLarge: SizedBox.shrink(), tabletLarge: SizedBox.shrink(),
desktop: SizedBox.shrink() desktop: SizedBox.shrink()
), ),
@@ -33,8 +33,8 @@ class MailboxDashBoardView extends GetWidget<MailboxDashBoardController> with Ne
body: Stack(children: [ body: Stack(children: [
ResponsiveWidget( ResponsiveWidget(
responsiveUtils: _responsiveUtils, responsiveUtils: _responsiveUtils,
desktop: _buildDesktopView(context), desktop: _buildLargeScreenView(context),
tabletLarge: _buildTabletLargeView(context), tabletLarge: _buildLargeScreenView(context),
tablet: ThreadView(), tablet: ThreadView(),
mobile: ThreadView() mobile: ThreadView()
), ),
@@ -84,8 +84,8 @@ class MailboxDashBoardView extends GetWidget<MailboxDashBoardController> with Ne
} }
} }
Widget _buildDesktopView(BuildContext context) { Widget _buildLargeScreenView(BuildContext context) {
if (controller.isDrawerOpen && _responsiveUtils.isDesktop(context)) { if (controller.isDrawerOpen && (_responsiveUtils.isDesktop(context) || _responsiveUtils.isTabletLarge(context))) {
WidgetsBinding.instance?.addPostFrameCallback((_) { WidgetsBinding.instance?.addPostFrameCallback((_) {
controller.closeDrawer(); controller.closeDrawer();
}); });
@@ -95,26 +95,8 @@ class MailboxDashBoardView extends GetWidget<MailboxDashBoardController> with Ne
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded(flex: 1, child: MailboxView()), SizedBox(child: MailboxView(), width: _responsiveUtils.defaultSizeDrawerWidthMobileTablet),
Expanded(flex: 3, child: _buildThreadAndEmailContainer(context)), Expanded(child: _buildThreadAndEmailContainer(context))
],
),
);
}
Widget _buildTabletLargeView(BuildContext context) {
if (controller.isDrawerOpen && _responsiveUtils.isTabletLarge(context)) {
WidgetsBinding.instance?.addPostFrameCallback((_) {
controller.closeDrawer();
});
}
return Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(flex: 2, child: MailboxView()),
Expanded(flex: 4, child: _buildThreadAndEmailContainer(context)),
], ],
), ),
); );
@@ -0,0 +1,121 @@
import 'package:core/core.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/mixin/network_connection_mixin.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_view_web.dart';
import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_view_web.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/setting/presentation/model/app_setting.dart';
import 'package:tmail_ui_user/features/setting/presentation/model/reading_pane.dart';
import 'package:tmail_ui_user/features/thread/presentation/thread_view.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart';
class MailboxDashBoardView extends GetWidget<MailboxDashBoardController> with NetworkConnectionMixin {
final _responsiveUtils = Get.find<ResponsiveUtils>();
@override
Widget build(BuildContext context) {
return Scaffold(
key: controller.scaffoldKey,
drawer: ResponsiveWidget(
responsiveUtils: _responsiveUtils,
mobile: Container(child: MailboxView(),
width: _responsiveUtils.isPortrait(context) ? _responsiveUtils.getSizeScreenWidth(context) : _responsiveUtils.getSizeScreenWidth(context) / 2),
tablet: Container(child: MailboxView(), width: _responsiveUtils.getSizeScreenWidth(context) / 2),
tabletLarge: SizedBox.shrink(),
desktop: SizedBox.shrink()
),
drawerEnableOpenDragGesture: !_responsiveUtils.isDesktop(context),
body: Stack(children: [
ResponsiveWidget(
responsiveUtils: _responsiveUtils,
desktop: _buildDesktopView(context),
tabletLarge: _buildTabletLargeView(context),
tablet: ThreadView(),
mobile: ThreadView()
),
Obx(() => controller.dashBoardAction == DashBoardAction.compose
? ComposerView()
: SizedBox.shrink()),
Obx(() => controller.isNetworkConnectionAvailable()
? SizedBox.shrink()
: Align(alignment: Alignment.bottomCenter, child: buildNetworkConnectionWidget(context))),
]),
);
}
Widget _buildThreadAndEmailContainer(BuildContext context) {
switch(AppSetting.readingPane) {
case ReadingPane.noSplit:
return Obx(() {
switch(controller.routePath.value) {
case AppRoutes.THREAD:
return ThreadView();
case AppRoutes.EMAIL:
return EmailView();
default:
return SizedBox.shrink();
}
});
case ReadingPane.rightOfInbox:
if (_responsiveUtils.isDesktop(context)) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(flex: 1, child: ThreadView()),
Expanded(flex: 2, child: EmailView()),
],
);
} else {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(flex: 1, child: ThreadView()),
Expanded(flex: 1, child: EmailView()),
],
);
}
default:
return SizedBox.shrink();
}
}
Widget _buildDesktopView(BuildContext context) {
if (controller.isDrawerOpen && _responsiveUtils.isDesktop(context)) {
WidgetsBinding.instance?.addPostFrameCallback((_) {
controller.closeDrawer();
});
}
return Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(flex: 1, child: MailboxView()),
Expanded(flex: 3, child: _buildThreadAndEmailContainer(context)),
],
),
);
}
Widget _buildTabletLargeView(BuildContext context) {
if (controller.isDrawerOpen && _responsiveUtils.isTabletLarge(context)) {
WidgetsBinding.instance?.addPostFrameCallback((_) {
controller.closeDrawer();
});
}
return Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(flex: 2, child: MailboxView()),
Expanded(flex: 4, child: _buildThreadAndEmailContainer(context)),
],
),
);
}
}
@@ -1,5 +1,6 @@
import 'package:core/core.dart'; import 'package:core/core.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@@ -30,48 +31,61 @@ class ThreadView extends GetWidget<ThreadController> with UserSettingPopupMenuMi
child: Scaffold( child: Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
backgroundColor: _responsiveUtils.isDesktop(context) ? AppColor.colorBgDesktop : Colors.white, backgroundColor: _responsiveUtils.isDesktop(context) ? AppColor.colorBgDesktop : Colors.white,
body: SafeArea( body: Row(children: [
right: _responsiveUtils.isMobileDevice(context) && _responsiveUtils.isLandscape(context), if (!kIsWeb && !_responsiveUtils.isMobile(context))
left: _responsiveUtils.isMobileDevice(context) && _responsiveUtils.isLandscape(context), VerticalDivider(color: AppColor.lineItemListColor, width: 1, thickness: 0.2),
child: Column( Expanded(child: SafeArea(
crossAxisAlignment: CrossAxisAlignment.start, right: _responsiveUtils.isMobile(context) && _responsiveUtils.isLandscape(context),
children: [ left: _responsiveUtils.isMobile(context) && _responsiveUtils.isLandscape(context),
if (_responsiveUtils.isDesktop(context)) child: Column(
Container( crossAxisAlignment: CrossAxisAlignment.start,
color: Colors.white, children: [
padding: EdgeInsets.only(right: 10, top: 16, bottom: 10), if (_responsiveUtils.isDesktop(context))
child: _buildHeader(context)), Container(
_buildSearchInputFormForMobile(context), color: Colors.white,
_buildSearchButtonViewForMobile(context), padding: EdgeInsets.only(right: 10, top: 16, bottom: 10, left: 32),
Obx(() => controller.isMailboxTrash && controller.emailList.isNotEmpty && !controller.isSearchActive() child: _buildHeader(context)),
? _buildEmptyTrashButton(context) Padding(
: SizedBox.shrink()), padding: EdgeInsets.only(
Expanded(child: Container( left: kIsWeb && (_responsiveUtils.isDesktop(context) || _responsiveUtils.isTabletLarge(context)) ? 32 : 0),
color: AppColor.colorBgDesktop, child: _buildSearchInputFormForMobile(context)),
margin: _responsiveUtils.isDesktop(context) ? EdgeInsets.all(16) : EdgeInsets.zero, Container(
child: Stack(children: [ color: kIsWeb ? AppColor.colorBgDesktop : Colors.white,
Container( padding: EdgeInsets.only(
alignment: Alignment.center, left: kIsWeb && (_responsiveUtils.isDesktop(context) || _responsiveUtils.isTabletLarge(context)) ? 32 : 0),
decoration: BoxDecoration( child: _buildSearchButtonViewForMobile(context)),
borderRadius: _responsiveUtils.isDesktop(context) ? BorderRadius.circular(20) : null, Obx(() => controller.isMailboxTrash && controller.emailList.isNotEmpty && !controller.isSearchActive()
border: _responsiveUtils.isDesktop(context) ? Border.all(color: AppColor.colorBorderBodyThread, width: 1) : null, ? _buildEmptyTrashButton(context)
color: Colors.white), : SizedBox.shrink()),
child: Column( Expanded(child: Container(
crossAxisAlignment: CrossAxisAlignment.start, padding: EdgeInsets.only(
children: [ left: kIsWeb && (_responsiveUtils.isDesktop(context) || _responsiveUtils.isTabletLarge(context)) ? 32 : 0),
_buildStatusResultSearch(context), color: kIsWeb ? AppColor.colorBgDesktop : Colors.white,
_buildLoadingView(), margin: _responsiveUtils.isDesktop(context) ? EdgeInsets.all(16) : EdgeInsets.zero,
Expanded(child: _buildListEmail(context)), child: Stack(children: [
_buildLoadingViewLoadMore(), Container(
] alignment: Alignment.center,
) decoration: BoxDecoration(
), borderRadius: _responsiveUtils.isDesktop(context) ? BorderRadius.circular(20) : null,
_buildSuggestionBox(context) border: _responsiveUtils.isDesktop(context) ? Border.all(color: AppColor.colorBorderBodyThread, width: 1) : null,
]))), color: Colors.white),
_buildListButtonSelectionForMobile(context), child: Column(
] crossAxisAlignment: CrossAxisAlignment.start,
) children: [
), _buildStatusResultSearch(context),
_buildLoadingView(),
Expanded(child: _buildListEmail(context)),
_buildLoadingViewLoadMore(),
]
)
),
_buildSuggestionBox(context)
]))),
_buildListButtonSelectionForMobile(context),
]
)
))
]),
floatingActionButton: _buildFloatingButtonCompose(context), floatingActionButton: _buildFloatingButtonCompose(context),
), ),
); );
@@ -247,7 +261,8 @@ class ThreadView extends GetWidget<ThreadController> with UserSettingPopupMenuMi
Widget _buildSearchButtonViewForMobile(BuildContext context) { Widget _buildSearchButtonViewForMobile(BuildContext context) {
return Obx(() { return Obx(() {
if (!controller.isSearchActive() && !_responsiveUtils.isDesktop(context)) { if (!controller.isSearchActive() && !_responsiveUtils.isDesktop(context)) {
return Padding( return Container(
color: Colors.white,
padding: EdgeInsets.only(left: 16, right: 16, bottom: 10), padding: EdgeInsets.only(left: 16, right: 16, bottom: 10),
child: (SearchBarView(_imagePaths) child: (SearchBarView(_imagePaths)
..hintTextSearch(AppLocalizations.of(context).hint_search_emails) ..hintTextSearch(AppLocalizations.of(context).hint_search_emails)
@@ -327,7 +342,7 @@ class ThreadView extends GetWidget<ThreadController> with UserSettingPopupMenuMi
controller.mailboxDashBoardController.searchInputController, controller.mailboxDashBoardController.searchInputController,
suggestionSearch: controller.mailboxDashBoardController.suggestionSearch,) suggestionSearch: controller.mailboxDashBoardController.suggestionSearch,)
..addDecoration(BoxDecoration(color: Colors.white)) ..addDecoration(BoxDecoration(color: Colors.white))
..setMargin(EdgeInsets.only(right: 10)) ..setMargin(EdgeInsets.only(right: 10, top: _responsiveUtils.isTabletLarge(context) ? 32 : 0))
..setHintText(AppLocalizations.of(context).search_mail) ..setHintText(AppLocalizations.of(context).search_mail)
..addOnCancelSearchPressed(() => controller.disableSearch()) ..addOnCancelSearchPressed(() => controller.disableSearch())
..addOnClearTextSearchAction(() => controller.mailboxDashBoardController.clearSearchText()) ..addOnClearTextSearchAction(() => controller.mailboxDashBoardController.clearSearchText())
@@ -515,8 +530,6 @@ class ThreadView extends GetWidget<ThreadController> with UserSettingPopupMenuMi
margin: _responsiveUtils.isDesktop(context) margin: _responsiveUtils.isDesktop(context)
? EdgeInsets.only(top: 16, bottom: 16) ? EdgeInsets.only(top: 16, bottom: 16)
: EdgeInsets.zero, : EdgeInsets.zero,
width: double.infinity,
height: double.infinity,
alignment: Alignment.center, alignment: Alignment.center,
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
color: Colors.white, color: Colors.white,
@@ -1090,4 +1090,11 @@ class AppLocalizations {
'Maximum files size', 'Maximum files size',
name: 'maximum_files_size'); name: 'maximum_files_size');
} }
String get exchange {
return Intl.message(
'Exchange',
name: 'exchange'
);
}
} }
+2 -1
View File
@@ -12,7 +12,8 @@ import 'package:tmail_ui_user/features/login/presentation/login_view.dart' defer
import 'package:tmail_ui_user/features/mailbox_creator/presentation/mailbox_creator_bindings.dart'; import 'package:tmail_ui_user/features/mailbox_creator/presentation/mailbox_creator_bindings.dart';
import 'package:tmail_ui_user/features/mailbox_creator/presentation/mailbox_creator_view.dart' deferred as mailbox_creator; import 'package:tmail_ui_user/features/mailbox_creator/presentation/mailbox_creator_view.dart' deferred as mailbox_creator;
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_bindings.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_bindings.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_view.dart' deferred as mailbox_dashBoard; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_view.dart'
if (dart.library.html) 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart' deferred as mailbox_dashBoard;
import 'package:tmail_ui_user/features/session/presentation/session_page_bindings.dart'; import 'package:tmail_ui_user/features/session/presentation/session_page_bindings.dart';
import 'package:tmail_ui_user/features/session/presentation/session_view.dart' deferred as session; import 'package:tmail_ui_user/features/session/presentation/session_view.dart' deferred as session;
import 'package:tmail_ui_user/main/pages/deferred_widget.dart'; import 'package:tmail_ui_user/main/pages/deferred_widget.dart';