From d6e959c4d92db2172166e4ac81fe0336183e584b Mon Sep 17 00:00:00 2001 From: dab246 Date: Fri, 14 Nov 2025 17:59:21 +0700 Subject: [PATCH] TF-4145 Create paywall url from `workplaceFqdn` --- core/lib/utils/web_link_generator.dart | 3 +- core/test/utils/web_link_generator_test.dart | 184 +++++++++++++++++- .../presentation/composer_controller.dart | 6 +- .../presentation/mailbox_view_web.dart | 2 +- .../mailbox_dashboard_controller.dart | 9 +- ...lidate_storage_menu_visible_extension.dart | 7 +- .../manage_account_dashboard_controller.dart | 8 +- .../manage_account_dashboard_view.dart | 5 +- .../menu/manage_account_menu_controller.dart | 3 +- .../settings/settings_first_level_view.dart | 20 +- .../menu/settings/settings_view.dart | 5 +- .../storage/storage_controller.dart | 5 +- .../presentation/storage/storage_view.dart | 4 +- .../domain/model/paywall_url_pattern.dart | 2 +- .../presentation/paywall_controller.dart | 128 +++++------- .../presentation/quotas_controller.dart | 5 +- .../widget/quotas_banner_widget.dart | 4 +- lib/main/utils/app_utils.dart | 1 + 18 files changed, 283 insertions(+), 118 deletions(-) diff --git a/core/lib/utils/web_link_generator.dart b/core/lib/utils/web_link_generator.dart index 5798a0759..6cdb96ea8 100644 --- a/core/lib/utils/web_link_generator.dart +++ b/core/lib/utils/web_link_generator.dart @@ -1,4 +1,5 @@ -import 'package:core/core.dart'; + +import 'package:core/utils/app_logger.dart'; /// Utility class for generating web links in flat subdomain format. class WebLinkGenerator { diff --git a/core/test/utils/web_link_generator_test.dart b/core/test/utils/web_link_generator_test.dart index d93d217aa..bdf1c61cd 100644 --- a/core/test/utils/web_link_generator_test.dart +++ b/core/test/utils/web_link_generator_test.dart @@ -41,7 +41,7 @@ void main() { expect(result, 'https://charlie-settings.domain.com/'); }); - test('✅ should throw when workplaceFqdn is empty', () { + test('should throw when workplaceFqdn is empty', () { expect( () => WebLinkGenerator.generateWebLink( workplaceFqdn: '', @@ -131,6 +131,108 @@ void main() { expect(result, 'https://bob.example.app/'); }); + + test('generateWebLink should include path and no hash when hash is null', () { + final result = WebLinkGenerator.generateWebLink( + workplaceFqdn: 'alice.example.app', + slug: 'notes', + pathname: 'welcome', + hash: null, + ); + + expect(result, 'https://alice-notes.example.app/welcome'); + expect(result.contains('#'), isFalse); + }); + + test('generateWebLink should include path and no hash when hash is empty', () { + final result = WebLinkGenerator.generateWebLink( + workplaceFqdn: 'bob.example.app', + slug: 'drive', + pathname: 'folder/123', + hash: '', + ); + + expect(result, 'https://bob-drive.example.app/folder/123'); + expect(result.contains('#'), isFalse); + }); + + test('generateWebLink should return root path when pathname is null', () { + final result = WebLinkGenerator.generateWebLink( + workplaceFqdn: 'charlie.example.app', + slug: 'settings', + pathname: null, + ); + + expect(result, 'https://charlie-settings.example.app/'); + expect(result.contains('#'), isFalse); + }); + + test('generateWebLink should include path and no hash when slug is null and only pathname is provided', () { + final result = WebLinkGenerator.generateWebLink( + workplaceFqdn: 'alice.example.app', + slug: null, + pathname: 'welcome', + ); + + expect(result, 'https://alice.example.app/welcome'); + expect(result.contains('#'), isFalse); + }); + + test('generateWebLink should include path and no hash when slug is empty and only pathname is provided', () { + final result = WebLinkGenerator.generateWebLink( + workplaceFqdn: 'bob.example.app', + slug: '', + pathname: 'dashboard', + ); + + expect(result, 'https://bob.example.app/dashboard'); + expect(result.contains('#'), isFalse); + }); + + test('generateWebLink should handle multi-segment pathname with leading slash when slug is null', () { + final result = WebLinkGenerator.generateWebLink( + workplaceFqdn: 'alice.example.app', + slug: null, + pathname: '/name1/name2', + ); + + expect(result, 'https://alice.example.app/name1/name2'); + expect(result.contains('#'), isFalse); + }); + + test('generateWebLink should handle multi-segment pathname without leading slash when slug is null', () { + final result = WebLinkGenerator.generateWebLink( + workplaceFqdn: 'bob.example.app', + slug: null, + pathname: 'name1/name2', + ); + + expect(result, 'https://bob.example.app/name1/name2'); + expect(result.contains('#'), isFalse); + }); + + test('generateWebLink should handle deep multi-segment pathname with leading slash when slug is empty', () { + final result = WebLinkGenerator.generateWebLink( + workplaceFqdn: 'charlie.example.app', + slug: '', + pathname: '/a/b/c/d', + ); + + expect(result, 'https://charlie.example.app/a/b/c/d'); + expect(result.contains('#'), isFalse); + }); + + test('generateWebLink should handle deep multi-segment pathname without leading slash when slug is empty', () { + final result = WebLinkGenerator.generateWebLink( + workplaceFqdn: 'dave.example.app', + slug: '', + pathname: 'a/b/c/d', + ); + + expect(result, 'https://dave.example.app/a/b/c/d'); + expect(result.contains('#'), isFalse); + }); + test('safeGenerateWebLink should return empty string on invalid FQDN', () { final result = WebLinkGenerator.safeGenerateWebLink( workplaceFqdn: '', @@ -166,5 +268,85 @@ void main() { expect(result, 'https://example.com/'); }); + + test('safeGenerateWebLink should include path and no hash when hash is null', () { + final result = WebLinkGenerator.safeGenerateWebLink( + workplaceFqdn: 'dave.example.app', + slug: 'profile', + pathname: 'user/info', + hash: null, + ); + + expect(result, 'https://dave-profile.example.app/user/info'); + expect(result.contains('#'), isFalse); + }); + + test('safeGenerateWebLink should include path and no hash when hash is empty', () { + final result = WebLinkGenerator.safeGenerateWebLink( + workplaceFqdn: 'eve.example.app', + slug: 'docs', + pathname: 'help', + hash: '', + ); + + expect(result, 'https://eve-docs.example.app/help'); + expect(result.contains('#'), isFalse); + }); + + test('safeGenerateWebLink should return root path when pathname is null', () { + final result = WebLinkGenerator.safeGenerateWebLink( + workplaceFqdn: 'frank.example.app', + slug: 'notes', + pathname: null, + ); + + expect(result, 'https://frank-notes.example.app/'); + expect(result.contains('#'), isFalse); + }); + + test('safeGenerateWebLink should handle no slug and only pathname (slug = null)', () { + final result = WebLinkGenerator.safeGenerateWebLink( + workplaceFqdn: 'charlie.example.app', + slug: null, + pathname: 'home', + ); + + expect(result, 'https://charlie.example.app/home'); + expect(result.contains('#'), isFalse); + }); + + test('safeGenerateWebLink should handle no slug and only pathname (slug = empty string)', () { + final result = WebLinkGenerator.safeGenerateWebLink( + workplaceFqdn: 'dave.example.app', + slug: '', + pathname: 'portal', + ); + + expect(result, 'https://dave.example.app/portal'); + expect(result.contains('#'), isFalse); + }); + + test('safeGenerateWebLink should handle multi-segment pathname with leading slash and no slug', () { + final result = WebLinkGenerator.safeGenerateWebLink( + workplaceFqdn: 'eve.example.app', + slug: null, + pathname: '/x/y/z', + ); + + expect(result, 'https://eve.example.app/x/y/z'); + expect(result.contains('#'), isFalse); + }); + + test('safeGenerateWebLink should handle multi-segment pathname without leading slash and no slug', () { + final result = WebLinkGenerator.safeGenerateWebLink( + workplaceFqdn: 'frank.example.app', + slug: null, + pathname: 'x/y/z', + ); + + expect(result, 'https://frank.example.app/x/y/z'); + expect(result.contains('#'), isFalse); + }); + }); } diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index bfc96ad1a..8d9aa4a99 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -1049,7 +1049,7 @@ class ComposerController extends BaseController popBack(); if (needIncreaseMySpace) { - mailboxDashBoardController.paywallController?.navigateToPaywall(context); + mailboxDashBoardController.paywallController?.navigateToPaywall(); } else { _autoFocusFieldWhenLauncher(); } @@ -1332,7 +1332,7 @@ class ComposerController extends BaseController popBack(); if (needIncreaseMySpace) { - mailboxDashBoardController.paywallController?.navigateToPaywall(context); + mailboxDashBoardController.paywallController?.navigateToPaywall(); } else { _autoFocusFieldWhenLauncher(); } @@ -2279,7 +2279,7 @@ class ComposerController extends BaseController popBack(); if (needIncreaseMySpace) { - mailboxDashBoardController.paywallController?.navigateToPaywall(context); + mailboxDashBoardController.paywallController?.navigateToPaywall(); } else { _autoFocusFieldWhenLauncher(); } diff --git a/lib/features/mailbox/presentation/mailbox_view_web.dart b/lib/features/mailbox/presentation/mailbox_view_web.dart index abfafc0e5..cd7627232 100644 --- a/lib/features/mailbox/presentation/mailbox_view_web.dart +++ b/lib/features/mailbox/presentation/mailbox_view_web.dart @@ -62,7 +62,7 @@ class MailboxView extends BaseMailboxView { onTapAction: () => controller .mailboxDashBoardController .paywallController - ?.navigateToPaywall(context), + ?.navigateToPaywall(), ); } else { return const SizedBox.shrink(); diff --git a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart index 9901655a6..67ebc8012 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -872,12 +872,11 @@ class MailboxDashBoardController extends ReloadableController if (PlatformInfo.isMobile) { getAllSendingEmails(); _storeSessionAction(session); - } else { - paywallController = PaywallController( - ownEmailAddress: ownEmailAddress.value, - ); - paywallController?.loadPaywallUrl(); } + + paywallController = PaywallController( + ownEmailAddress: ownEmailAddress.value, + ); } void _handleMailtoURL(MailtoArguments arguments) { diff --git a/lib/features/manage_account/presentation/extensions/validate_storage_menu_visible_extension.dart b/lib/features/manage_account/presentation/extensions/validate_storage_menu_visible_extension.dart index 04daa6343..116a6029e 100644 --- a/lib/features/manage_account/presentation/extensions/validate_storage_menu_visible_extension.dart +++ b/lib/features/manage_account/presentation/extensions/validate_storage_menu_visible_extension.dart @@ -1,7 +1,6 @@ import 'package:dartz/dartz.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart'; -import 'package:tmail_ui_user/features/manage_account/presentation/extensions/validate_setting_capability_supported_extension.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/manage_account_dashboard_controller.dart'; import 'package:tmail_ui_user/features/quotas/domain/exceptions/quotas_exception.dart'; import 'package:tmail_ui_user/features/quotas/domain/extensions/list_quotas_extensions.dart'; @@ -13,9 +12,7 @@ import 'package:tmail_ui_user/main/routes/route_navigation.dart'; extension ValidateStorageMenuVisibleExtension on ManageAccountDashBoardController { void injectQuotaBindings() { - if (isStorageCapabilitySupported) { - QuotasInteractorBindings().dependencies(); - } + QuotasInteractorBindings().dependencies(); } void getQuotas(AccountId? accountId) { @@ -27,7 +24,7 @@ extension ValidateStorageMenuVisibleExtension } getQuotasInteractor = getBinding(); - if (getQuotasInteractor == null || !isStorageCapabilitySupported) { + if (getQuotasInteractor == null) { consumeState( Stream.value(Left(GetQuotasFailure(QuotasNotSupportedException))), ); diff --git a/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart b/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart index 2b4ce2b69..6b9db045a 100644 --- a/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart +++ b/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart @@ -30,6 +30,7 @@ import 'package:tmail_ui_user/features/manage_account/presentation/email_rules/b import 'package:tmail_ui_user/features/manage_account/presentation/extensions/export_trace_log_extension.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/extensions/handle_vacation_response_extension.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/extensions/vacation_response_extension.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/extensions/validate_setting_capability_supported_extension.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/extensions/validate_storage_menu_visible_extension.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/forward/bindings/forward_bindings.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/identities/identity_bindings.dart'; @@ -154,11 +155,10 @@ class ManageAccountDashBoardController extends ReloadableController paywallController = PaywallController( ownEmailAddress: ownEmailAddress.value, ); - paywallController?.loadPaywallUrl(); if (quota != null) { octetsQuota.value = quota; - } else { + } else if (isStorageCapabilitySupported) { getQuotas(accountId.value); } } @@ -194,7 +194,9 @@ class ManageAccountDashBoardController extends ReloadableController injectVacationBindings(session, accountId); injectForwardBindings(session, accountId); injectRuleFilterBindings(session, accountId); - injectQuotaBindings(); + if (isStorageCapabilitySupported) { + injectQuotaBindings(); + } } @override diff --git a/lib/features/manage_account/presentation/manage_account_dashboard_view.dart b/lib/features/manage_account/presentation/manage_account_dashboard_view.dart index 5a6ca415c..2ac66b703 100644 --- a/lib/features/manage_account/presentation/manage_account_dashboard_view.dart +++ b/lib/features/manage_account/presentation/manage_account_dashboard_view.dart @@ -25,6 +25,7 @@ import 'package:tmail_ui_user/features/manage_account/presentation/preferences/p import 'package:tmail_ui_user/features/manage_account/presentation/storage/storage_view.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/vacation/vacation_view.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/vacation/widgets/vacation_notification_message_widget.dart'; +import 'package:tmail_ui_user/features/quotas/domain/extensions/quota_extensions.dart'; class ManageAccountDashBoardView extends GetWidget { @@ -171,7 +172,9 @@ class ManageAccountDashBoardView extends GetWidget { ), ]); }), + if (PlatformInfo.isWeb) + ...[ + divider, + _buildSettingItem( + context: context, + menuItem: AccountMenuItem.keyboardShortcuts, + appLocalizations: appLocalizations, + ), + ], Obx(() { - if (controller.manageAccountDashboardController.octetsQuota.value != null) { + final octetsQuota = controller + .manageAccountDashboardController + .octetsQuota + .value; + + if (octetsQuota != null && octetsQuota.storageAvailable) { return Column(children: [ divider, _buildSettingItem( - key: const ValueKey('setting_storage'), context: context, - menuItem: AccountMenuItem.keyboardShortcuts, + menuItem: AccountMenuItem.storage, appLocalizations: appLocalizations, ), ]); diff --git a/lib/features/manage_account/presentation/menu/settings/settings_view.dart b/lib/features/manage_account/presentation/menu/settings/settings_view.dart index 78845f1c2..9bd4077e9 100644 --- a/lib/features/manage_account/presentation/menu/settings/settings_view.dart +++ b/lib/features/manage_account/presentation/menu/settings/settings_view.dart @@ -18,6 +18,7 @@ import 'package:tmail_ui_user/features/manage_account/presentation/preferences/p import 'package:tmail_ui_user/features/manage_account/presentation/storage/storage_view.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/vacation/vacation_view.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/vacation/widgets/vacation_notification_message_widget.dart'; +import 'package:tmail_ui_user/features/quotas/domain/extensions/quota_extensions.dart'; class SettingsView extends GetWidget { const SettingsView({Key? key}) : super(key: key); @@ -141,7 +142,9 @@ class SettingsView extends GetWidget { case AccountMenuItem.notification: return const NotificationView(); case AccountMenuItem.storage: - if (controller.manageAccountDashboardController.isStorageCapabilitySupported) { + if (controller.manageAccountDashboardController.octetsQuota.value != null && + controller.manageAccountDashboardController.octetsQuota.value?.storageAvailable == true && + controller.manageAccountDashboardController.isStorageCapabilitySupported) { return const StorageView(); } else { return const SizedBox.shrink(); diff --git a/lib/features/manage_account/presentation/storage/storage_controller.dart b/lib/features/manage_account/presentation/storage/storage_controller.dart index 722a3818b..9cc690669 100644 --- a/lib/features/manage_account/presentation/storage/storage_controller.dart +++ b/lib/features/manage_account/presentation/storage/storage_controller.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/manage_account_dashboard_controller.dart'; @@ -17,7 +16,7 @@ class StorageController extends BaseController with SaaSPremiumMixin { return isPremiumAvailable(accountId: accountId, session: session); } - void onUpgradeStorage(BuildContext context) { - dashBoardController.paywallController?.navigateToPaywall(context); + void onUpgradeStorage() { + dashBoardController.paywallController?.navigateToPaywall(); } } diff --git a/lib/features/manage_account/presentation/storage/storage_view.dart b/lib/features/manage_account/presentation/storage/storage_view.dart index 3f532558b..e7c1a692a 100644 --- a/lib/features/manage_account/presentation/storage/storage_view.dart +++ b/lib/features/manage_account/presentation/storage/storage_view.dart @@ -89,8 +89,8 @@ class StorageView extends GetWidget with AppLoaderMixin { return UpgradeStorageWidget( imagePaths: controller.imagePaths, isMobile: isMobile, - onUpgradeStorageAction: () => - controller.onUpgradeStorage(context), + onUpgradeStorageAction: + controller.onUpgradeStorage, ); } else { return const SizedBox.shrink(); diff --git a/lib/features/paywall/domain/model/paywall_url_pattern.dart b/lib/features/paywall/domain/model/paywall_url_pattern.dart index a237e5224..581a54aac 100644 --- a/lib/features/paywall/domain/model/paywall_url_pattern.dart +++ b/lib/features/paywall/domain/model/paywall_url_pattern.dart @@ -13,7 +13,7 @@ class PaywallUrlPattern with EquatableMixin { final mailAddress = _getMailAddress(ownerEmail: ownerEmail); return PaywallUtils.buildPaywallUrlFromTemplate( template: pattern, - localPart: mailAddress?.localPart, + localPart: mailAddress?.localPart.replaceAll('.', ''), domainName: domainName ?? mailAddress?.domain.domainName, ); } diff --git a/lib/features/paywall/presentation/paywall_controller.dart b/lib/features/paywall/presentation/paywall_controller.dart index 717489b22..235b4dc6c 100644 --- a/lib/features/paywall/presentation/paywall_controller.dart +++ b/lib/features/paywall/presentation/paywall_controller.dart @@ -17,56 +17,34 @@ import 'package:tmail_ui_user/main/utils/app_utils.dart'; class PaywallController extends BaseController { final String ownEmailAddress; - PaywallUrlPattern? paywallUrlPattern; - bool isRetryGetPaywallUrl = false; - PaywallController({required this.ownEmailAddress}); - void loadPaywallUrl() { + void _loadPaywallUrl() { final getPaywallUrlInteractor = getBinding(); final jmapUrl = dynamicUrlInterceptors.jmapUrl; if (getPaywallUrlInteractor != null && jmapUrl != null) { consumeState(getPaywallUrlInteractor.execute(jmapUrl)); } else { - paywallUrlPattern = null; - if (isRetryGetPaywallUrl) { - _showMessagePaywallUrlNotAvailable(); - isRetryGetPaywallUrl = false; - } + _loadPaywallUrlFailure(); } } - void loadPaywallUrlSuccess(PaywallUrlPattern newPattern) { - paywallUrlPattern = newPattern; - if (isRetryGetPaywallUrl) { - isRetryGetPaywallUrl = false; - final qualifiedPaywall = getPaywallUrl(paywallUrlPattern!); - AppUtils.launchLink(qualifiedPaywall); - } + void _loadPaywallUrlSuccess(PaywallUrlPattern newPattern) { + _redirectPaywallPage(newPattern); } - void loadPaywallUrlFailure() { - paywallUrlPattern = null; - if (isRetryGetPaywallUrl) { - _showMessagePaywallUrlNotAvailable(); - isRetryGetPaywallUrl = false; - } + void _loadPaywallUrlFailure() { + _showMessagePaywallUrlNotAvailable(); } - void _showMessagePaywallUrlNotAvailable({BuildContext? context}) { - final overlayContext = context ?? currentOverlayContext; - AppLocalizations? appLocalizations; - if (context != null) { - appLocalizations = AppLocalizations.of(context); - } else if (currentContext != null) { - appLocalizations = AppLocalizations.of(currentContext!); - } - - if (overlayContext == null || appLocalizations == null) return; + void _showMessagePaywallUrlNotAvailable() { + if (currentOverlayContext == null || currentContext == null) return; + final appLocalizations = AppLocalizations.of(currentContext!); + appToast.showToastMessage( - overlayContext, + currentOverlayContext!, appLocalizations.paywallUrlNotAvailable, actionName: appLocalizations.retry, onActionClick: _handleRetryGetPaywallUrl, @@ -82,49 +60,54 @@ class PaywallController extends BaseController { ); } - void navigateToPaywall(BuildContext context) { - if (paywallUrlPattern == null) { - _showMessagePaywallUrlNotAvailable(context: context); - return; - } - final qualifiedPaywall = getPaywallUrl(paywallUrlPattern!); - AppUtils.launchLink(qualifiedPaywall); - } - - String getPaywallUrl(PaywallUrlPattern pattern) { - final defaultUrl = pattern.getQualifiedUrl( - ownerEmail: ownEmailAddress, - domainName: RouteUtils.getRootDomain(), - ); - + void navigateToPaywall() { try { final workplaceFqdn = twakeAppManager.oidcUserInfo?.workplaceFqdn?.trim(); if (workplaceFqdn == null || workplaceFqdn.isEmpty) { - return defaultUrl; + _navigateToPaywallUseEcoSystem(); + return; + } else { + _navigateToPaywallUseWorkplaceFqdn(workplaceFqdn); } - - final paywallUrl = WebLinkGenerator.safeGenerateWebLink( - workplaceFqdn: workplaceFqdn, - pathname: 'paywall', - ); - - // Fallback if generated URL is empty or invalid - return paywallUrl.isNotEmpty ? paywallUrl : defaultUrl; } catch (e) { - logError('$runtimeType::getPaywallUrl: Failed to generate paywall URL: $e'); - return defaultUrl; + logError('$runtimeType::navigateToPaywall: Failed to navigate to paywall $e'); + _navigateToPaywallUseEcoSystem(); } } + void _navigateToPaywallUseWorkplaceFqdn(String workplaceFqdn) { + final paywallUrl = WebLinkGenerator.safeGenerateWebLink( + workplaceFqdn: workplaceFqdn, + pathname: '/settings/premium', + ); + + if (paywallUrl.isNotEmpty) { + AppUtils.launchLink(paywallUrl); + } else { + _navigateToPaywallUseEcoSystem(); + } + } + + void _navigateToPaywallUseEcoSystem() { + _loadPaywallUrl(); + } + + void _redirectPaywallPage(PaywallUrlPattern urlPattern) { + final qualifiedPaywall = urlPattern.getQualifiedUrl( + ownerEmail: ownEmailAddress, + domainName: RouteUtils.getRootDomain(), + ); + AppUtils.launchLink(qualifiedPaywall); + } + void _handleRetryGetPaywallUrl() { - isRetryGetPaywallUrl = true; - loadPaywallUrl(); + _loadPaywallUrl(); } @override void handleSuccessViewState(Success success) { if (success is GetPaywallUrlSuccess) { - loadPaywallUrlSuccess(success.paywallUrlPattern); + _loadPaywallUrlSuccess(success.paywallUrlPattern); } else { super.handleSuccessViewState(success); } @@ -133,28 +116,9 @@ class PaywallController extends BaseController { @override void handleFailureViewState(Failure failure) { if (failure is GetPaywallUrlFailure) { - loadPaywallUrlFailure(); + _loadPaywallUrlFailure(); } else { super.handleFailureViewState(failure); } } - - @override - void handleErrorViewState(Object error, StackTrace stackTrace) { - super.handleErrorViewState(error, stackTrace); - isRetryGetPaywallUrl = false; - } - - @override - void handleUrgentExceptionOnWeb({Failure? failure, Exception? exception}) { - super.handleUrgentExceptionOnWeb(failure: failure, exception: exception); - isRetryGetPaywallUrl = false; - } - - @override - void onClose() { - paywallUrlPattern = null; - isRetryGetPaywallUrl = false; - super.onClose(); - } } diff --git a/lib/features/quotas/presentation/quotas_controller.dart b/lib/features/quotas/presentation/quotas_controller.dart index 1fe661144..3ed0bd660 100644 --- a/lib/features/quotas/presentation/quotas_controller.dart +++ b/lib/features/quotas/presentation/quotas_controller.dart @@ -2,7 +2,6 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; import 'package:core/utils/app_logger.dart'; import 'package:dartz/dartz.dart'; -import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart'; @@ -104,8 +103,8 @@ class QuotasController extends BaseController { mailboxDashBoardController.validateUserHasIsAlreadyHighestSubscription(); } - void handleManageMyStorage(BuildContext context) { - mailboxDashBoardController.paywallController?.navigateToPaywall(context); + void handleManageMyStorage() { + mailboxDashBoardController.paywallController?.navigateToPaywall(); } void closeBanner() { diff --git a/lib/features/quotas/presentation/widget/quotas_banner_widget.dart b/lib/features/quotas/presentation/widget/quotas_banner_widget.dart index cfc06ab36..a9a44c5de 100644 --- a/lib/features/quotas/presentation/widget/quotas_banner_widget.dart +++ b/lib/features/quotas/presentation/widget/quotas_banner_widget.dart @@ -80,8 +80,8 @@ class QuotasBannerWidget extends StatelessWidget { backgroundColor: QuotasBannerStyles.backgroundColor, textStyle: QuotasBannerStyles.manageStorageButtonTextStyle, padding: EdgeInsets.zero, - onTapActionCallback: () => - _quotasController.handleManageMyStorage(context), + onTapActionCallback: + _quotasController.handleManageMyStorage, ), ], ), diff --git a/lib/main/utils/app_utils.dart b/lib/main/utils/app_utils.dart index db55c69c1..2194a8eed 100644 --- a/lib/main/utils/app_utils.dart +++ b/lib/main/utils/app_utils.dart @@ -33,6 +33,7 @@ class AppUtils { } static void launchLink(String url, {bool isNewTab = true}) { + log('AppUtils::launchLink: url = $url'); if (PlatformInfo.isWeb && HtmlUtils.isSafariBelow17()) { html.window.open(url, isNewTab ? '_blank' : '_self'); } else {