From 9671822f78a5936d8430a449ef10d1a9a496522a Mon Sep 17 00:00:00 2001 From: dab246 Date: Tue, 9 Sep 2025 13:13:53 +0700 Subject: [PATCH] TF-3985 Display `Increase your space` button when premium is available on web desktop --- assets/images/ic_premium.svg | 24 ++++++++ .../extensions/color_extension.dart | 1 + .../presentation/resources/image_paths.dart | 1 + .../views/dialog/confirm_dialog_button.dart | 56 +++++++++++++++---- .../premium/increase_space_button_widget.dart | 41 ++++++++++++++ .../presentation/mailbox_view_web.dart | 19 +++++++ ...date_saas_premium_available_extension.dart | 16 ++++++ lib/l10n/intl_messages.arb | 10 +++- lib/main/localizations/app_localizations.dart | 7 +++ model/lib/saas/saas_account_capability.dart | 2 + 10 files changed, 165 insertions(+), 12 deletions(-) create mode 100644 assets/images/ic_premium.svg create mode 100644 lib/features/base/widget/premium/increase_space_button_widget.dart create mode 100644 lib/features/mailbox_dashboard/presentation/extensions/validate_saas_premium_available_extension.dart diff --git a/assets/images/ic_premium.svg b/assets/images/ic_premium.svg new file mode 100644 index 000000000..de7db9011 --- /dev/null +++ b/assets/images/ic_premium.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/presentation/extensions/color_extension.dart b/core/lib/presentation/extensions/color_extension.dart index 4e72c1f4e..68b941201 100644 --- a/core/lib/presentation/extensions/color_extension.dart +++ b/core/lib/presentation/extensions/color_extension.dart @@ -243,6 +243,7 @@ extension AppColor on Color { static const m3Tertiary20 = Color(0xFF71767C); static const m3Neutral70 = Color(0xFFAEAAAE); static const m3Neutral90 = Color(0xFFE6E1E5); + static const m3SysLightSecondaryBlue = Color(0xFF5C9CE6); static const grayBackgroundColor = Color(0xFFF3F6F9); static const m3SurfaceBackground = Color(0xFF1C1B1F); static const warningColor = Color(0xFFFFC107); diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart index cf39c7e4f..24f6a9d6d 100644 --- a/core/lib/presentation/resources/image_paths.dart +++ b/core/lib/presentation/resources/image_paths.dart @@ -239,6 +239,7 @@ class ImagePaths { String get icTwakeWorkplace => _getIconPath('icon_twp.png'); String get animLottieTmail => _getAnimationPath('lottie-tmail.json'); String get icExpandArrows => _getImagePath('ic_expand_arrows.svg'); + String get icPremium => _getImagePath('ic_premium.svg'); String _getImagePath(String imageName) { return AssetsPaths.images + imageName; diff --git a/core/lib/presentation/views/dialog/confirm_dialog_button.dart b/core/lib/presentation/views/dialog/confirm_dialog_button.dart index dcf166f37..20b1a8e5c 100644 --- a/core/lib/presentation/views/dialog/confirm_dialog_button.dart +++ b/core/lib/presentation/views/dialog/confirm_dialog_button.dart @@ -1,11 +1,19 @@ +import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/utils/theme_utils.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; class ConfirmDialogButton extends StatelessWidget { final String label; final Color? backgroundColor; final Color? textColor; final Color? borderColor; + final String? icon; + final double? iconSize; + final Color? iconColor; + final TextStyle? textStyle; + final double? radius; + final EdgeInsetsGeometry? padding; final VoidCallback? onTapAction; const ConfirmDialogButton({ @@ -14,6 +22,12 @@ class ConfirmDialogButton extends StatelessWidget { this.backgroundColor, this.textColor, this.borderColor, + this.icon, + this.iconSize, + this.iconColor, + this.textStyle, + this.radius, + this.padding, this.onTapAction, }); @@ -21,11 +35,11 @@ class ConfirmDialogButton extends StatelessWidget { Widget build(BuildContext context) { final outlineBorder = borderColor != null ? RoundedRectangleBorder( - borderRadius: const BorderRadius.all(Radius.circular(100)), + borderRadius: BorderRadius.all(Radius.circular(radius ?? 100)), side: BorderSide(width: 1, color: borderColor!), ) - : const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(100)), + : RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(radius ?? 100)), ); return TextButton( @@ -33,15 +47,37 @@ class ConfirmDialogButton extends StatelessWidget { backgroundColor: backgroundColor, overlayColor: Theme.of(context).colorScheme.outline.withValues(alpha: 0.08), shape: outlineBorder, - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: padding ?? const EdgeInsets.symmetric(horizontal: 10), ), onPressed: onTapAction, - child: Text( - label, - style: ThemeUtils.textStyleM3LabelLarge(color: textColor), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), + child: icon == null + ? Text( + label, + style: textStyle ?? ThemeUtils.textStyleM3LabelLarge(color: textColor), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ) + : Row( + mainAxisSize: MainAxisSize.min, + children: [ + SvgPicture.asset( + icon!, + width: iconSize ?? 14, + height: iconSize ?? 14, + fit: BoxFit.fill, + colorFilter: iconColor?.toInt() == Colors.transparent.toInt() + ? null + : iconColor?.asFilter() ?? AppColor.primaryMain.asFilter(), + ), + const SizedBox(width: 8), + Text( + label, + style: textStyle ?? ThemeUtils.textStyleM3LabelLarge(color: textColor), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ) + ], + ), ); } } diff --git a/lib/features/base/widget/premium/increase_space_button_widget.dart b/lib/features/base/widget/premium/increase_space_button_widget.dart new file mode 100644 index 000000000..c356b0b6e --- /dev/null +++ b/lib/features/base/widget/premium/increase_space_button_widget.dart @@ -0,0 +1,41 @@ +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:core/presentation/utils/theme_utils.dart'; +import 'package:core/presentation/views/dialog/confirm_dialog_button.dart'; +import 'package:flutter/material.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +class IncreaseSpaceButtonWidget extends StatelessWidget { + final ImagePaths imagePaths; + final VoidCallback onTapAction; + final EdgeInsetsGeometry? margin; + + const IncreaseSpaceButtonWidget({ + super.key, + required this.imagePaths, + required this.onTapAction, + this.margin, + }); + + @override + Widget build(BuildContext context) { + return Container( + constraints: const BoxConstraints(minWidth: 193), + height: 44, + margin: margin, + child: ConfirmDialogButton( + label: AppLocalizations.of(context).increaseYourSpace, + borderColor: AppColor.m3SysLightSecondaryBlue, + icon: imagePaths.icPremium, + iconSize: 22, + iconColor: Colors.transparent, + textStyle: ThemeUtils.textStyleM3BodyMedium.copyWith( + color: AppColor.blue700, + ), + radius: 7, + padding: const EdgeInsetsDirectional.symmetric(horizontal: 8), + onTapAction: onTapAction, + ), + ); + } +} diff --git a/lib/features/mailbox/presentation/mailbox_view_web.dart b/lib/features/mailbox/presentation/mailbox_view_web.dart index de0226924..1824717d0 100644 --- a/lib/features/mailbox/presentation/mailbox_view_web.dart +++ b/lib/features/mailbox/presentation/mailbox_view_web.dart @@ -5,8 +5,10 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:tmail_ui_user/features/base/widget/application_version_widget.dart'; +import 'package:tmail_ui_user/features/base/widget/premium/increase_space_button_widget.dart'; import 'package:tmail_ui_user/features/base/widget/scrollbar_list_view.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/base_mailbox_view.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/validate_saas_premium_available_extension.dart'; import 'package:tmail_ui_user/features/quotas/presentation/quotas_view.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; @@ -35,6 +37,23 @@ class MailboxView extends BaseMailboxView { : _buildListMailbox(context), ), const QuotasView(), + Obx(() { + final isPremiumAvailable = + controller.mailboxDashBoardController.isPremiumAvailable; + + if (isPremiumAvailable) { + return IncreaseSpaceButtonWidget( + imagePaths: controller.imagePaths, + margin: const EdgeInsetsDirectional.only( + start: 26, + bottom: 8, + ), + onTapAction: () {}, + ); + } else { + return const SizedBox.shrink(); + } + }), Container( alignment: isDesktop ? AlignmentDirectional.center diff --git a/lib/features/mailbox_dashboard/presentation/extensions/validate_saas_premium_available_extension.dart b/lib/features/mailbox_dashboard/presentation/extensions/validate_saas_premium_available_extension.dart new file mode 100644 index 000000000..dbd779522 --- /dev/null +++ b/lib/features/mailbox_dashboard/presentation/extensions/validate_saas_premium_available_extension.dart @@ -0,0 +1,16 @@ +import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart'; + +extension ValidateSaasPremiumAvailableExtension on MailboxDashBoardController { + bool get isPremiumAvailable { + if (accountId.value == null || sessionCurrent == null) { + return false; + } + + final saasAccount = sessionCurrent?.getSaaSAccountCapability( + accountId.value!, + ); + + return saasAccount?.isPremiumAvailable ?? false; + } +} diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index 0126f7589..2a85c1168 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-08-18T13:21:17.206262", + "@@last_modified": "2025-09-09T13:12:15.883838", "initializing_data": "Initializing data...", "@initializing_data": { "type": "text", @@ -4671,5 +4671,11 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "increaseYourSpace": "Increase your space", + "@increaseYourSpace": { + "type": "text", + "placeholders_order": [], + "placeholders": {} } -} +} \ No newline at end of file diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index ab0390d5f..6f3835612 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -4928,4 +4928,11 @@ class AppLocalizations { name: 'archiveMessagesFailed', ); } + + String get increaseYourSpace { + return Intl.message( + 'Increase your space', + name: 'increaseYourSpace', + ); + } } diff --git a/model/lib/saas/saas_account_capability.dart b/model/lib/saas/saas_account_capability.dart index c388438ee..15f2edccd 100644 --- a/model/lib/saas/saas_account_capability.dart +++ b/model/lib/saas/saas_account_capability.dart @@ -19,6 +19,8 @@ class SaaSAccountCapability extends CapabilityProperties { return SaaSAccountCapability.fromJson(json); } + bool get isPremiumAvailable => canUpgrade; + @override List get props => [isPaying, canUpgrade]; }