TF-3758 Update app grid in left menu on mobile
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
@@ -251,6 +251,9 @@ extension AppColor on Color {
|
||||
static const warningColor = Color(0xFFFFC107);
|
||||
static const primaryMain = Color(0xFF0A84FF);
|
||||
static const m3LayerDarkOutline = Color(0xFF938F99);
|
||||
static const blackAlpha40 = Color.fromRGBO(0, 0, 0, 0.4);
|
||||
static const blackAlpha20 = Color.fromRGBO(0, 0, 0, 0.2);
|
||||
static const textPrimary = Color(0xFF424244);
|
||||
|
||||
static const mapGradientColor = [
|
||||
[Color(0xFF21D4FD), Color(0xFFB721FF)],
|
||||
|
||||
@@ -234,6 +234,15 @@ class ThemeUtils {
|
||||
color: color ??AppColor.primaryMain,
|
||||
);
|
||||
|
||||
static TextStyle textStyleAppShortcut() => const TextStyle(
|
||||
fontFamily: ConstantsUI.fontApp,
|
||||
fontWeight: FontWeight.normal,
|
||||
letterSpacing: 0.0,
|
||||
fontSize: 12,
|
||||
height: 22.5 / 12,
|
||||
color: AppColor.textPrimary,
|
||||
);
|
||||
|
||||
static TextSelectionThemeData get _textSelectionTheme {
|
||||
return const TextSelectionThemeData(
|
||||
cursorColor: AppColor.primaryColor,
|
||||
|
||||
@@ -37,12 +37,7 @@ mixin ImageLoaderMixin {
|
||||
},
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
logError('ImageLoaderMixin::buildImage:Exception = $error');
|
||||
return Container(
|
||||
width: imageSize ?? 150,
|
||||
height: imageSize ?? 150,
|
||||
alignment: Alignment.center,
|
||||
child: const Icon(Icons.error_outline),
|
||||
);
|
||||
return buildNoImage(imageSize ?? 150);
|
||||
},
|
||||
);
|
||||
} else if (isImageSVG(imagePath)) {
|
||||
@@ -61,6 +56,15 @@ mixin ImageLoaderMixin {
|
||||
}
|
||||
}
|
||||
|
||||
Widget buildNoImage(double imageSize) {
|
||||
return Container(
|
||||
width: imageSize,
|
||||
height: imageSize,
|
||||
alignment: Alignment.center,
|
||||
child: const Icon(Icons.error_outline),
|
||||
);
|
||||
}
|
||||
|
||||
bool isImageNetworkLink(String imagePath) {
|
||||
return imagePath.startsWith('http') == true ||
|
||||
imagePath.startsWith('https') == true;
|
||||
|
||||
@@ -5,12 +5,14 @@ import 'package:flutter/material.dart';
|
||||
class UserAvatarBuilder extends StatelessWidget {
|
||||
final String username;
|
||||
final double? size;
|
||||
final EdgeInsetsGeometry? padding;
|
||||
final VoidCallback? onTapAction;
|
||||
|
||||
const UserAvatarBuilder({
|
||||
Key? key,
|
||||
required this.username,
|
||||
this.size,
|
||||
this.padding,
|
||||
this.onTapAction,
|
||||
}) : super(key: key);
|
||||
|
||||
@@ -28,6 +30,13 @@ class UserAvatarBuilder extends StatelessWidget {
|
||||
avatarBuilder.addOnTapActionClick(onTapAction!);
|
||||
}
|
||||
|
||||
return avatarBuilder.build();
|
||||
if (padding != null) {
|
||||
return Padding(
|
||||
padding: padding!,
|
||||
child: avatarBuilder.build(),
|
||||
);
|
||||
} else {
|
||||
return avatarBuilder.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/open_app_grid_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/mixin/mailbox_widget_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_app_bar.dart';
|
||||
|
||||
abstract class BaseMailboxView extends GetWidget<MailboxController>
|
||||
with
|
||||
@@ -10,4 +12,27 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
|
||||
MailboxWidgetMixin {
|
||||
|
||||
BaseMailboxView({Key? key}) : super(key: key);
|
||||
|
||||
Widget buildMailboxAppBar() {
|
||||
return Obx(() {
|
||||
final dashboardController = controller.mailboxDashBoardController;
|
||||
final accountId = dashboardController.accountId.value;
|
||||
final username = accountId != null
|
||||
? dashboardController.getOwnEmailAddress()
|
||||
: '';
|
||||
|
||||
final linagoraApps = dashboardController
|
||||
.appGridDashboardController
|
||||
.listLinagoraApp;
|
||||
|
||||
return MailboxAppBar(
|
||||
imagePaths: controller.imagePaths,
|
||||
username: username,
|
||||
openSettingsAction: controller.mailboxDashBoardController.goToSettings,
|
||||
onOpenAppGridAction: linagoraApps.isNotEmpty
|
||||
? () => controller.openAppGrid(linagoraApps)
|
||||
: null,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/views/list/sliver_grid_delegate_fixed_height.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/app_grid/app_shortcut.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/linagora_ecosystem/app_linagora_ecosystem.dart';
|
||||
|
||||
extension OpenAppGridExtension on MailboxController {
|
||||
void openAppGrid(List<AppLinagoraEcosystem> linagoraApps) {
|
||||
log('OpenAppGridExtension::openAppGrid: length of linagoraApps = ${linagoraApps.length}');
|
||||
Get.dialog(
|
||||
Center(
|
||||
child: Dialog(
|
||||
backgroundColor: Colors.white,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(14)),
|
||||
),
|
||||
child: Container(
|
||||
width: 254,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 14),
|
||||
decoration: const BoxDecoration(
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Color(0x14000000),
|
||||
offset: Offset(0, 2),
|
||||
blurRadius: 24,
|
||||
),
|
||||
BoxShadow(
|
||||
color: Color(0x14000000),
|
||||
blurRadius: 2,
|
||||
),
|
||||
],
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.all(Radius.circular(14)),
|
||||
),
|
||||
child: GridView(
|
||||
gridDelegate: const SliverGridDelegateFixedHeight(
|
||||
height: 80.58,
|
||||
crossAxisCount: 3,
|
||||
mainAxisSpacing: 10,
|
||||
),
|
||||
shrinkWrap: true,
|
||||
physics: const ClampingScrollPhysics(),
|
||||
children: linagoraApps.map((app) {
|
||||
return AppShortcut(
|
||||
icon: app.getIconPath(imagePaths),
|
||||
label: app.appName ?? '',
|
||||
onTapAction: () => _handleOpenApp(app),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
barrierColor: AppColor.blackAlpha20,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _handleOpenApp(AppLinagoraEcosystem app) async {
|
||||
await launchApplication(
|
||||
androidPackageId: app.androidPackageId,
|
||||
iosScheme: app.iosUrlScheme,
|
||||
iosStoreLink: app.iosAppStoreLink,
|
||||
uri: app.appRedirectLink,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||
import 'package:rxdart/transformers.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_mailbox_controller.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/contact_support_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/launcher_application_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/mailbox_action_handler_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/move_action.dart';
|
||||
@@ -102,7 +103,9 @@ import 'package:tmail_ui_user/main/routes/route_utils.dart';
|
||||
import 'package:tmail_ui_user/main/utils/ios_sharing_manager.dart';
|
||||
|
||||
class MailboxController extends BaseMailboxController
|
||||
with MailboxActionHandlerMixin, ContactSupportMixin {
|
||||
with MailboxActionHandlerMixin,
|
||||
ContactSupportMixin,
|
||||
LauncherApplicationMixin {
|
||||
|
||||
final mailboxDashBoardController = Get.find<MailboxDashBoardController>();
|
||||
final isMailboxListScrollable = false.obs;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/application_version_widget.dart';
|
||||
@@ -8,11 +7,9 @@ import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/base_mailbox_view.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/widgets/app_grid_view.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/folder_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/folders_bar_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_app_bar.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_category_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_item_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_loading_bar_widget.dart';
|
||||
@@ -27,44 +24,20 @@ class MailboxView extends BaseMailboxView {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
child: Drawer(
|
||||
backgroundColor: Colors.white,
|
||||
shape: InputBorder.none,
|
||||
return Drawer(
|
||||
backgroundColor: Colors.white,
|
||||
shape: InputBorder.none,
|
||||
child: SafeArea(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(children: [
|
||||
Obx(() {
|
||||
final accountId = controller
|
||||
.mailboxDashBoardController
|
||||
.accountId
|
||||
.value;
|
||||
|
||||
final username = accountId != null
|
||||
? controller.mailboxDashBoardController.getOwnEmailAddress()
|
||||
: '';
|
||||
|
||||
return MailboxAppBar(
|
||||
username: username,
|
||||
openSettingsAction:
|
||||
controller.mailboxDashBoardController.goToSettings,
|
||||
);
|
||||
}),
|
||||
_buildHeaderMailbox(context),
|
||||
Expanded(child: Container(
|
||||
color: Colors.white,
|
||||
child: RefreshIndicator(
|
||||
color: AppColor.primaryColor,
|
||||
onRefresh: controller.refreshAllMailbox,
|
||||
child: SafeArea(
|
||||
top: false,
|
||||
right: false,
|
||||
bottom: false,
|
||||
child: _buildListMailbox(context)
|
||||
)
|
||||
),
|
||||
buildMailboxAppBar(),
|
||||
Expanded(child: RefreshIndicator(
|
||||
color: AppColor.primaryColor,
|
||||
onRefresh: controller.refreshAllMailbox,
|
||||
child: _buildListMailbox(context)
|
||||
)),
|
||||
Obx(() {
|
||||
if (controller.isSelectionEnabled()
|
||||
@@ -127,79 +100,14 @@ class MailboxView extends BaseMailboxView {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildHeaderMailbox(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: controller.responsiveUtils.isMobile(context) ? 10 : 30, bottom: 8),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsetsDirectional.only(start: 10),
|
||||
child: _buildCloseScreenButton(context)),
|
||||
SizedBox(width: controller.isSelectionEnabled() ? 49 : 40),
|
||||
Expanded(child: Text(
|
||||
AppLocalizations.of(context).folders,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(fontSize: 21, color: Colors.black, fontWeight: FontWeight.bold))),
|
||||
Obx(() => _buildEditMailboxButton(context, controller.isSelectionEnabled()))
|
||||
]
|
||||
)
|
||||
),
|
||||
if (!controller.responsiveUtils.isTabletLarge(context))
|
||||
const Divider(color: AppColor.colorDividerMailbox, height: 1),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCloseScreenButton(BuildContext context) {
|
||||
return buildIconWeb(
|
||||
icon: SvgPicture.asset(controller.imagePaths.icCircleClose, width: 28, height: 28, fit: BoxFit.fill),
|
||||
tooltip: AppLocalizations.of(context).close,
|
||||
onTap: () => controller.closeMailboxScreen(context));
|
||||
}
|
||||
|
||||
Widget _buildEditMailboxButton(BuildContext context, bool isSelectionEnabled) {
|
||||
return Padding(
|
||||
padding: const EdgeInsetsDirectional.only(end: 10),
|
||||
child: Material(
|
||||
shape: const CircleBorder(),
|
||||
color: Colors.transparent,
|
||||
child: TextButton(
|
||||
child: Text(
|
||||
!isSelectionEnabled ? AppLocalizations.of(context).select : AppLocalizations.of(context).cancel,
|
||||
style: const TextStyle(fontSize: 17, color: AppColor.colorTextButton, fontWeight: FontWeight.normal)),
|
||||
onPressed: () => !isSelectionEnabled
|
||||
? controller.enableSelectionMailbox()
|
||||
: controller.disableSelectionMailbox()
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildListMailbox(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
controller: controller.mailboxListScrollController,
|
||||
key: const PageStorageKey('mailbox_list'),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.only(bottom: 16),
|
||||
padding: const EdgeInsets.only(bottom: 16, top: 16),
|
||||
child: Column(children: [
|
||||
Obx(() => MailboxLoadingBarWidget(viewState: controller.viewState.value)),
|
||||
Obx(() {
|
||||
final linagoraApps = controller
|
||||
.mailboxDashBoardController
|
||||
.appGridDashboardController
|
||||
.listLinagoraApp;
|
||||
|
||||
if (linagoraApps.isNotEmpty) {
|
||||
return AppGridView(linagoraApps: linagoraApps);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
const SizedBox(height: 8),
|
||||
Obx(() {
|
||||
if (controller.defaultMailboxIsNotEmpty) {
|
||||
return _buildMailboxCategory(
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AppGridIcon extends StatelessWidget {
|
||||
|
||||
final String icon;
|
||||
final VoidCallback onTapAction;
|
||||
|
||||
const AppGridIcon({
|
||||
super.key,
|
||||
required this.icon,
|
||||
required this.onTapAction,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TMailButtonWidget.fromIcon(
|
||||
icon: icon,
|
||||
backgroundColor: Colors.transparent,
|
||||
iconSize: 24,
|
||||
iconColor: AppColor.blackAlpha40,
|
||||
padding: const EdgeInsets.all(8),
|
||||
onTapActionCallback: onTapAction,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:core/presentation/views/image/image_loader_mixin.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AppShortcut extends StatelessWidget with ImageLoaderMixin {
|
||||
final String? icon;
|
||||
final String label;
|
||||
final VoidCallback onTapAction;
|
||||
|
||||
const AppShortcut({
|
||||
super.key,
|
||||
required this.icon,
|
||||
required this.label,
|
||||
required this.onTapAction,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
onTap: onTapAction,
|
||||
child: Container(
|
||||
width: 78,
|
||||
height: 80.58,
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (icon != null)
|
||||
buildImage(
|
||||
imagePath: icon!,
|
||||
imageSize: 42,
|
||||
)
|
||||
else
|
||||
buildNoImage(42),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
label,
|
||||
style: ThemeUtils.textStyleAppShortcut(),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,24 @@
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/application_logo_with_text_widget.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/user_avatar_builder.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/app_grid/app_grid_icon.dart';
|
||||
|
||||
typedef OnOpenSettingsAction = void Function();
|
||||
typedef OnOpenAppGridAction = void Function();
|
||||
|
||||
class MailboxAppBar extends StatelessWidget {
|
||||
final ImagePaths imagePaths;
|
||||
final String username;
|
||||
final OnOpenSettingsAction? openSettingsAction;
|
||||
final OnOpenAppGridAction? onOpenAppGridAction;
|
||||
|
||||
const MailboxAppBar({
|
||||
super.key,
|
||||
required this.imagePaths,
|
||||
required this.username,
|
||||
this.openSettingsAction,
|
||||
this.onOpenAppGridAction,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -26,8 +33,14 @@ class MailboxAppBar extends StatelessWidget {
|
||||
children: [
|
||||
ApplicationLogoWidthTextWidget(iconSize: 22),
|
||||
const Spacer(),
|
||||
if (onOpenAppGridAction != null)
|
||||
AppGridIcon(
|
||||
icon: imagePaths.icAppDashboard,
|
||||
onTapAction: onOpenAppGridAction!,
|
||||
),
|
||||
UserAvatarBuilder(
|
||||
username: username,
|
||||
padding: const EdgeInsetsDirectional.only(start: 4),
|
||||
onTapAction: openSettingsAction,
|
||||
),
|
||||
],
|
||||
|
||||
-10
@@ -2280,19 +2280,9 @@ class MailboxDashBoardController extends ReloadableController
|
||||
|
||||
void handleOnForegroundGained() {
|
||||
log('MailboxDashBoardController::handleOnForegroundGained():');
|
||||
if (PlatformInfo.isMobile) {
|
||||
_updateTheme();
|
||||
}
|
||||
refreshActionWhenBackToApp();
|
||||
}
|
||||
|
||||
void _updateTheme() {
|
||||
ThemeUtils.setSystemDarkUIStyle();
|
||||
if (isDrawerOpen) {
|
||||
ThemeUtils.setStatusBarTransparentColor();
|
||||
}
|
||||
}
|
||||
|
||||
void updateEmailList(List<PresentationEmail> newEmailList) {
|
||||
emailsInCurrentMailbox.value = newEmailList;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user