diff --git a/assets/images/ic_app_dashboard.svg b/assets/images/ic_app_dashboard.svg
new file mode 100644
index 000000000..976dadf8c
--- /dev/null
+++ b/assets/images/ic_app_dashboard.svg
@@ -0,0 +1,3 @@
+
diff --git a/env.file b/env.file
index 71638e979..8ddf1610b 100644
--- a/env.file
+++ b/env.file
@@ -1,3 +1,4 @@
SERVER_URL=http://localhost
DOMAIN_REDIRECT_URL=http://localhost:3000
-WEB_OIDC_CLIENT_ID=teammail-web
\ No newline at end of file
+WEB_OIDC_CLIENT_ID=teammail-web
+APP_GRID_AVAILABLE=supported
\ No newline at end of file
diff --git a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart
index 27b368a0c..0a0b3b558 100644
--- a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart
+++ b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart
@@ -9,6 +9,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/state/mark_as_mailbox_read
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_view_web.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_action.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/base_mailbox_dashboard_view.dart';
+import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/app_grid_dashboard_controller.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/search_controller.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/composer_overlay_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/email_receive_time_type.dart';
@@ -26,12 +27,16 @@ import 'package:tmail_ui_user/features/thread/presentation/thread_view.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
+import 'package:tmail_ui_user/main/utils/app_config.dart';
+
+import 'widgets/app_dashboard/app_grid_dashboard_overlay.dart';
class MailboxDashBoardView extends BaseMailboxDashBoardView {
MailboxDashBoardView({Key? key}) : super(key: key);
final SearchController searchController = Get.find();
+ final AppGridDashboardController appGridDashboardController = Get.find();
@override
Widget build(BuildContext context) {
@@ -259,6 +264,35 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
}
})),
const Spacer(),
+ AppConfig.appGridDashboardAvailable
+ ? Obx(() => PortalTarget(
+ visible: appGridDashboardController.isAppGridDashboardOverlayOpen.isTrue,
+ portalFollower: GestureDetector(
+ behavior: HitTestBehavior.opaque,
+ onTap: () => appGridDashboardController.toggleAppGridDashboard()),
+ child: PortalTarget(
+ child: InkWell(
+ onTapDown: (tapDownDetails) => controller.showAppDashboardAction(),
+ child: buildIconWeb(
+ icon: SvgPicture.asset(imagePaths.icAppDashboard, width: 28, height: 28, fit: BoxFit.fill),
+ )
+ ),
+ anchor: const Aligned(
+ follower: Alignment.topRight,
+ target: Alignment.bottomRight
+ ),
+ portalFollower: Obx(() {
+ if (appGridDashboardController.linagoraApplications.value != null) {
+ return AppDashboardOverlay(appGridDashboardController.linagoraApplications.value!);
+ }
+ return const SizedBox.shrink();
+ }),
+ visible: appGridDashboardController.isAppGridDashboardOverlayOpen.isTrue,
+ )
+ )
+ )
+ : const SizedBox.shrink(),
+ const SizedBox(width: 24),
Obx(() => (AvatarBuilder()
..text(controller.userProfile.value?.getAvatarText() ?? '')
..backgroundColor(Colors.white)
diff --git a/lib/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_grid_dashboard_item.dart b/lib/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_grid_dashboard_item.dart
new file mode 100644
index 000000000..6d66d6932
--- /dev/null
+++ b/lib/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_grid_dashboard_item.dart
@@ -0,0 +1,62 @@
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:core/presentation/resources/image_paths.dart';
+import 'package:core/presentation/utils/style_utils.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:get/get.dart';
+import 'package:tmail_ui_user/features/mailbox_dashboard/domain/app_dashboard/linagora_app.dart';
+import 'package:url_launcher/url_launcher.dart' as launcher;
+
+typedef OnTapCallback = void Function();
+
+class AppGridDashboardItem extends StatelessWidget {
+ final LinagoraApp app;
+
+ AppGridDashboardItem(this.app, {Key? key}) : super(key: key);
+
+ final ImagePaths _imagePaths = Get.find();
+
+ @override
+ Widget build(BuildContext context) {
+ return Padding(
+ padding: const EdgeInsets.symmetric(vertical: 8),
+ child: InkWell(
+ onTap: _openApp,
+ child: Column(children: [
+ app.iconName.endsWith("svg")
+ ? SvgPicture.asset(
+ _imagePaths.getConfigurationImagePath(app.iconName),
+ width: 56,
+ height: 56,
+ fit: BoxFit.fill)
+ : Image.asset(
+ _imagePaths.getConfigurationImagePath(app.iconName),
+ width: 56,
+ height: 56,
+ fit: BoxFit.fill),
+ Padding(
+ padding: const EdgeInsets.only(top: 8),
+ child: Text(
+ app.appName,
+ maxLines: 1,
+ textAlign: TextAlign.center,
+ softWrap: CommonTextStyle.defaultSoftWrap,
+ overflow: CommonTextStyle.defaultTextOverFlow,
+ style: const TextStyle(
+ color: AppColor.colorNameEmail,
+ fontSize: 15
+ ),
+ ),
+ ),
+ ]),
+ )
+ );
+ }
+
+ void _openApp() async {
+ final url = app.appUri;
+ if (await launcher.canLaunchUrl(url)) {
+ await launcher.launchUrl(url);
+ }
+ }
+}
diff --git a/lib/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_grid_dashboard_overlay.dart b/lib/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_grid_dashboard_overlay.dart
new file mode 100644
index 000000000..fb3f9baea
--- /dev/null
+++ b/lib/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_grid_dashboard_overlay.dart
@@ -0,0 +1,49 @@
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:core/presentation/views/list/sliver_grid_delegate_fixed_height.dart';
+import 'package:flutter/material.dart';
+import 'package:tmail_ui_user/features/mailbox_dashboard/domain/app_dashboard/linagora_applications.dart';
+import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_grid_dashboard_item.dart';
+
+class AppDashboardOverlay extends StatelessWidget {
+ final LinagoraApplications _linagoraApplications;
+
+ const AppDashboardOverlay(this._linagoraApplications, {Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return GestureDetector(
+ onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
+ child: Container(
+ width: 342,
+ height: 244,
+ decoration: BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.circular(16),
+ boxShadow: const [
+ BoxShadow(
+ color: AppColor.colorShadowComposer,
+ blurRadius: 32,
+ offset: Offset.zero),
+ BoxShadow(
+ color: AppColor.colorDropShadow,
+ blurRadius: 4,
+ offset: Offset.zero),
+ ]
+ ),
+ child: GridView.builder(
+ padding: const EdgeInsets.all(24),
+ itemBuilder: (context, i) {
+ final app = _linagoraApplications.apps[i];
+ return AppGridDashboardItem(app);
+ },
+ primary: true,
+ itemCount: _linagoraApplications.apps.length,
+ gridDelegate: const SliverGridDelegateFixedHeight(
+ height: 98,
+ crossAxisCount: 3,
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/main/utils/app_config.dart b/lib/main/utils/app_config.dart
index 7648c88f9..8f1aa31ff 100644
--- a/lib/main/utils/app_config.dart
+++ b/lib/main/utils/app_config.dart
@@ -4,4 +4,12 @@ class AppConfig {
static String get baseUrl => dotenv.get('SERVER_URL', fallback: '');
static String get domainRedirectUrl => dotenv.get('DOMAIN_REDIRECT_URL', fallback: '');
static String get webOidcClientId => dotenv.get('WEB_OIDC_CLIENT_ID', fallback: '');
+ static bool get appGridDashboardAvailable {
+ final supported = dotenv.get('APP_GRID_AVAILABLE', fallback: 'unsupported');
+ if (supported == 'supported') {
+ return true;
+ }
+ return false;
+ }
+ static String appDashboardConfigurationPath = "configurations/app_dashboard.json";
}
\ No newline at end of file