TF-3260 Load & Display App Grid Linagora Ecosystem
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
+54
-40
@@ -2,60 +2,74 @@ import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_portal/flutter_portal.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/app_grid_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/linagora_ecosystem/app_linagora_ecosystem.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_grid_dashboard_overlay.dart';
|
||||
import 'package:tmail_ui_user/main/utils/app_utils.dart';
|
||||
|
||||
class AppGridDashboardIcon extends StatelessWidget {
|
||||
class AppGridDashboardIcon extends StatefulWidget {
|
||||
|
||||
final ImagePaths imagePaths;
|
||||
final AppGridDashboardController appGridController;
|
||||
final VoidCallback? onShowAppDashboardAction;
|
||||
final List<AppLinagoraEcosystem> linagoraApps;
|
||||
|
||||
const AppGridDashboardIcon({
|
||||
super.key,
|
||||
required this.imagePaths,
|
||||
required this.appGridController,
|
||||
this.onShowAppDashboardAction,
|
||||
required this.linagoraApps,
|
||||
});
|
||||
|
||||
@override
|
||||
State<AppGridDashboardIcon> createState() => _AppGridDashboardIconState();
|
||||
}
|
||||
|
||||
class _AppGridDashboardIconState extends State<AppGridDashboardIcon> {
|
||||
|
||||
final ValueNotifier<bool> _isExpandedNotifier = ValueNotifier<bool>(false);
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_isExpandedNotifier.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Obx(() {
|
||||
final isAppGridOpen = appGridController.isAppGridDashboardOverlayOpen.value;
|
||||
return PortalTarget(
|
||||
visible: isAppGridOpen,
|
||||
portalFollower: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: appGridController.toggleAppGridDashboard
|
||||
),
|
||||
child: PortalTarget(
|
||||
anchor: Aligned(
|
||||
follower: AppUtils.isDirectionRTL(context)
|
||||
? Alignment.topLeft
|
||||
: Alignment.topRight,
|
||||
target: AppUtils.isDirectionRTL(context)
|
||||
? Alignment.bottomLeft
|
||||
: Alignment.bottomRight
|
||||
return ValueListenableBuilder(
|
||||
valueListenable: _isExpandedNotifier,
|
||||
builder: (context, isExpanded, child) {
|
||||
return PortalTarget(
|
||||
visible: isExpanded,
|
||||
portalFollower: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: _toggleAppGridDashboard,
|
||||
),
|
||||
portalFollower: Obx(() {
|
||||
final listApps = appGridController.linagoraApplications.value;
|
||||
if (listApps?.apps.isNotEmpty == true) {
|
||||
return AppDashboardOverlay(listApps!);
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
}),
|
||||
visible: isAppGridOpen,
|
||||
child: TMailButtonWidget.fromIcon(
|
||||
icon: imagePaths.icAppDashboard,
|
||||
backgroundColor: Colors.transparent,
|
||||
iconSize: 30,
|
||||
padding: const EdgeInsets.all(6),
|
||||
onTapActionCallback: onShowAppDashboardAction,
|
||||
child: PortalTarget(
|
||||
anchor: Aligned(
|
||||
follower: AppUtils.isDirectionRTL(context)
|
||||
? Alignment.topLeft
|
||||
: Alignment.topRight,
|
||||
target: AppUtils.isDirectionRTL(context)
|
||||
? Alignment.bottomLeft
|
||||
: Alignment.bottomRight,
|
||||
),
|
||||
portalFollower: AppDashboardOverlay(
|
||||
listLinagoraApp: widget.linagoraApps,
|
||||
imagePaths: widget.imagePaths,
|
||||
),
|
||||
visible: isExpanded,
|
||||
child: TMailButtonWidget.fromIcon(
|
||||
icon: widget.imagePaths.icAppDashboard,
|
||||
backgroundColor: Colors.transparent,
|
||||
iconSize: 30,
|
||||
padding: const EdgeInsets.all(6),
|
||||
onTapActionCallback: _toggleAppGridDashboard,
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
});
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _toggleAppGridDashboard() {
|
||||
_isExpandedNotifier.value = !_isExpandedNotifier.value;
|
||||
}
|
||||
}
|
||||
|
||||
+19
-36
@@ -1,64 +1,47 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/views/image/image_loader_mixin.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/launcher_application_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/link_browser_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/app_dashboard/linagora_app.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/linagora_ecosystem/app_linagora_ecosystem.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/styles/app_grid_dashboard_style.dart';
|
||||
import 'package:tmail_ui_user/main/utils/app_utils.dart';
|
||||
|
||||
class AppGridDashboardItem extends StatelessWidget {
|
||||
final LinagoraApp app;
|
||||
class AppGridDashboardItem extends StatelessWidget
|
||||
with LauncherApplicationMixin, ImageLoaderMixin {
|
||||
|
||||
AppGridDashboardItem(this.app, {Key? key}) : super(key: key);
|
||||
final AppLinagoraEcosystem app;
|
||||
final ImagePaths imagePaths;
|
||||
|
||||
final ImagePaths _imagePaths = Get.find<ImagePaths>();
|
||||
const AppGridDashboardItem({
|
||||
Key? key,
|
||||
required this.app,
|
||||
required this.imagePaths,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LinkBrowserWidget(
|
||||
uri: app.appUri,
|
||||
uri: app.appRedirectLink!,
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () => AppUtils.launchLink(app.appUri.toString()),
|
||||
onTap: () => launchApplication(uri: app.appRedirectLink),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(16)),
|
||||
hoverColor: AppColor.colorBgMailboxSelected,
|
||||
child: Container(
|
||||
width: AppGridDashboardStyle.hoverIconSize,
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Column(children: [
|
||||
if (app.iconName?.isNotEmpty == true)
|
||||
app.iconName!.endsWith("svg")
|
||||
? SvgPicture.asset(
|
||||
_imagePaths.getConfigurationImagePath(app.iconName!),
|
||||
width: AppGridDashboardStyle.iconSize,
|
||||
height: AppGridDashboardStyle.iconSize,
|
||||
fit: BoxFit.fill)
|
||||
: Image.asset(
|
||||
_imagePaths.getConfigurationImagePath(app.iconName!),
|
||||
width: AppGridDashboardStyle.iconSize,
|
||||
height: AppGridDashboardStyle.iconSize,
|
||||
fit: BoxFit.fill)
|
||||
else if (app.publicIconUri != null)
|
||||
Image.network(
|
||||
app.publicIconUri.toString(),
|
||||
width: AppGridDashboardStyle.iconSize,
|
||||
height: AppGridDashboardStyle.iconSize,
|
||||
fit: BoxFit.fill,
|
||||
errorBuilder: (_, error, stackTrace) {
|
||||
return Container(
|
||||
width: AppGridDashboardStyle.iconSize,
|
||||
height: AppGridDashboardStyle.iconSize,
|
||||
color: AppColor.textFieldHintColor,
|
||||
);
|
||||
}
|
||||
if (app.getIconPath(imagePaths) != null)
|
||||
buildImage(
|
||||
imagePath: app.getIconPath(imagePaths)!,
|
||||
imageSize: AppGridDashboardStyle.iconSize,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
child: Text(
|
||||
app.appName,
|
||||
app.appName ?? '',
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
||||
+13
-7
@@ -1,12 +1,18 @@
|
||||
import 'package:core/presentation/resources/image_paths.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/domain/linagora_ecosystem/app_linagora_ecosystem.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/styles/app_grid_dashboard_style.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;
|
||||
final List<AppLinagoraEcosystem> listLinagoraApp;
|
||||
final ImagePaths imagePaths;
|
||||
|
||||
const AppDashboardOverlay(this._linagoraApplications, {Key? key}) : super(key: key);
|
||||
const AppDashboardOverlay({
|
||||
Key? key,
|
||||
required this.listLinagoraApp,
|
||||
required this.imagePaths,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -20,17 +26,17 @@ class AppDashboardOverlay extends StatelessWidget {
|
||||
boxShadow: AppGridDashboardStyle.cardShadow
|
||||
),
|
||||
padding: AppGridDashboardStyle.padding,
|
||||
child: Wrap(children: _linagoraApplications.apps
|
||||
.map((app) => AppGridDashboardItem(app))
|
||||
child: Wrap(children: listLinagoraApp
|
||||
.map((app) => AppGridDashboardItem(app: app, imagePaths: imagePaths))
|
||||
.toList()),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
double get _widthAppGrid {
|
||||
if (_linagoraApplications.apps.length >= 3) {
|
||||
if (listLinagoraApp.length >= 3) {
|
||||
return AppGridDashboardStyle.hoverIconSize * 3 + AppGridDashboardStyle.padding.horizontal;
|
||||
} else if (_linagoraApplications.apps.length == 2) {
|
||||
} else if (listLinagoraApp.length == 2) {
|
||||
return AppGridDashboardStyle.hoverIconSize * 2 + AppGridDashboardStyle.padding.horizontal;
|
||||
} else {
|
||||
return AppGridDashboardStyle.hoverIconSize + AppGridDashboardStyle.padding.horizontal;
|
||||
|
||||
+19
-36
@@ -1,60 +1,43 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/views/text/slogan_builder.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:external_app_launcher/external_app_launcher.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get_core/get_core.dart';
|
||||
import 'package:get/get_instance/get_instance.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/app_dashboard/linagora_app.dart';
|
||||
import 'package:url_launcher/url_launcher.dart' as launcher;
|
||||
import 'package:tmail_ui_user/features/base/mixin/launcher_application_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/linagora_ecosystem/app_linagora_ecosystem.dart';
|
||||
|
||||
class AppListDashboardItem extends StatelessWidget {
|
||||
class AppListDashboardItem extends StatelessWidget with LauncherApplicationMixin {
|
||||
|
||||
final LinagoraApp app;
|
||||
final AppLinagoraEcosystem app;
|
||||
final ImagePaths imagePaths;
|
||||
|
||||
const AppListDashboardItem(this.app, {Key? key}) : super(key: key);
|
||||
const AppListDashboardItem({
|
||||
super.key,
|
||||
required this.app,
|
||||
required this.imagePaths,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final imagePaths = Get.find<ImagePaths>();
|
||||
return SloganBuilder(
|
||||
sizeLogo: 32,
|
||||
paddingText: const EdgeInsetsDirectional.only(start: 12),
|
||||
text: app.appName,
|
||||
textAlign: TextAlign.center,
|
||||
textStyle: const TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: AppColor.colorNameEmail),
|
||||
logo: app.iconName?.isNotEmpty == true
|
||||
? imagePaths.getConfigurationImagePath(app.iconName!)
|
||||
: null,
|
||||
publicLogoUri: app.publicIconUri,
|
||||
onTapCallback: () => _openApp(context, app),
|
||||
logo: app.getIconPath(imagePaths),
|
||||
onTapCallback: _handleOpenApp,
|
||||
padding: const EdgeInsetsDirectional.symmetric(vertical: 12, horizontal: 20),
|
||||
hoverColor: AppColor.colorBgMailboxSelected
|
||||
);
|
||||
}
|
||||
|
||||
void _openApp(BuildContext context, LinagoraApp app) async {
|
||||
if (PlatformInfo.isWeb) {
|
||||
if (await launcher.canLaunchUrl(app.appUri)) {
|
||||
await launcher.launchUrl(app.appUri);
|
||||
}
|
||||
} else if (Platform.isAndroid && app.androidPackageId?.isNotEmpty == true) {
|
||||
await LaunchApp.openApp(androidPackageName: app.androidPackageId);
|
||||
} else if (Platform.isIOS && app.iosUrlScheme?.isNotEmpty == true) {
|
||||
await LaunchApp.openApp(
|
||||
iosUrlScheme: '${app.iosUrlScheme}://',
|
||||
appStoreLink: app.iosAppStoreLink
|
||||
);
|
||||
} else {
|
||||
if (await launcher.canLaunchUrl(app.appUri)) {
|
||||
await launcher.launchUrl(
|
||||
app.appUri,
|
||||
mode: launcher.LaunchMode.externalApplication
|
||||
);
|
||||
}
|
||||
}
|
||||
Future<void> _handleOpenApp() async {
|
||||
await launchApplication(
|
||||
androidPackageId: app.androidPackageId,
|
||||
iosScheme: app.iosUrlScheme,
|
||||
iosStoreLink: app.iosAppStoreLink,
|
||||
uri: app.appRedirectLink,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+23
-21
@@ -4,6 +4,7 @@ import 'package:core/presentation/utils/responsive_utils.dart';
|
||||
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
||||
import 'package:core/presentation/views/image/avatar_builder.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:model/support/contact_support_capability.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/contact_support_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/application_logo_with_text_widget.dart';
|
||||
@@ -11,7 +12,6 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/styles/navigation_bar_style.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_grid_dashboard_icon.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/utils/app_config.dart';
|
||||
|
||||
class NavigationBarWidget extends StatelessWidget {
|
||||
|
||||
@@ -21,7 +21,6 @@ class NavigationBarWidget extends StatelessWidget {
|
||||
final Widget? searchForm;
|
||||
final AppGridDashboardController? appGridController;
|
||||
final VoidCallback? onTapApplicationLogoAction;
|
||||
final VoidCallback? onShowAppDashboardAction;
|
||||
final OnTapAvatarActionWithPositionClick? onTapAvatarAction;
|
||||
final OnTapContactSupportAction? onTapContactSupportAction;
|
||||
|
||||
@@ -32,7 +31,6 @@ class NavigationBarWidget extends StatelessWidget {
|
||||
this.contactSupportCapability,
|
||||
this.searchForm,
|
||||
this.appGridController,
|
||||
this.onShowAppDashboardAction,
|
||||
this.onTapApplicationLogoAction,
|
||||
this.onTapAvatarAction,
|
||||
this.onTapContactSupportAction,
|
||||
@@ -74,15 +72,17 @@ class NavigationBarWidget extends StatelessWidget {
|
||||
tooltipMessage: AppLocalizations.of(context).getHelpOrReportABug,
|
||||
onTapActionCallback: () => onTapContactSupportAction?.call(contactSupportCapability!),
|
||||
),
|
||||
if (AppConfig.appGridDashboardAvailable && appGridController != null)
|
||||
Padding(
|
||||
padding: const EdgeInsetsDirectional.only(end: 16),
|
||||
child: AppGridDashboardIcon(
|
||||
imagePaths: imagePaths,
|
||||
appGridController: appGridController!,
|
||||
onShowAppDashboardAction: onShowAppDashboardAction,
|
||||
),
|
||||
),
|
||||
if (appGridController != null)
|
||||
Obx(() {
|
||||
if (appGridController!.listLinagoraApp.isNotEmpty) {
|
||||
return AppGridDashboardIcon(
|
||||
imagePaths: imagePaths,
|
||||
linagoraApps: appGridController!.listLinagoraApp,
|
||||
);
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
}),
|
||||
const SizedBox(width: 16),
|
||||
(AvatarBuilder()
|
||||
..text(avatarUserName)
|
||||
..backgroundColor(Colors.white)
|
||||
@@ -114,15 +114,17 @@ class NavigationBarWidget extends StatelessWidget {
|
||||
tooltipMessage: AppLocalizations.of(context).getHelpOrReportABug,
|
||||
onTapActionCallback: () => onTapContactSupportAction?.call(contactSupportCapability!),
|
||||
),
|
||||
if (AppConfig.appGridDashboardAvailable && appGridController != null)
|
||||
Padding(
|
||||
padding: const EdgeInsetsDirectional.only(end: 16),
|
||||
child: AppGridDashboardIcon(
|
||||
imagePaths: imagePaths,
|
||||
appGridController: appGridController!,
|
||||
onShowAppDashboardAction: onShowAppDashboardAction,
|
||||
),
|
||||
),
|
||||
if (appGridController != null)
|
||||
Obx(() {
|
||||
if (appGridController!.listLinagoraApp.isNotEmpty) {
|
||||
return AppGridDashboardIcon(
|
||||
imagePaths: imagePaths,
|
||||
linagoraApps: appGridController!.listLinagoraApp,
|
||||
);
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
}),
|
||||
const SizedBox(width: 16),
|
||||
(AvatarBuilder()
|
||||
..text(avatarUserName)
|
||||
..backgroundColor(Colors.white)
|
||||
|
||||
Reference in New Issue
Block a user