diff --git a/lib/features/base/base_controller.dart b/lib/features/base/base_controller.dart index 006ba94f8..faa4dc8d6 100644 --- a/lib/features/base/base_controller.dart +++ b/lib/features/base/base_controller.dart @@ -48,6 +48,7 @@ import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_sto import 'package:tmail_ui_user/features/push_notification/presentation/bindings/fcm_interactor_bindings.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/bindings/web_socket_interactor_bindings.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/config/fcm_configuration.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/cache/linagora_ecosystem_cache.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/controller/fcm_message_controller.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/controller/fcm_token_controller.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/controller/web_socket_controller.dart'; @@ -596,6 +597,7 @@ abstract class BaseController extends GetxController authorizationInterceptors.clear(); authorizationIsolateInterceptors.clear(); await cachingManager.closeHive(); + LinagoraEcosystemCache().clearCache(); } catch (e) { logWarning('BaseController::clearAllData: Cannot clear all data: $e'); } diff --git a/lib/features/mailbox_dashboard/data/cache/linagora_ecosystem_cache.dart b/lib/features/mailbox_dashboard/data/cache/linagora_ecosystem_cache.dart new file mode 100644 index 000000000..3b0a3927b --- /dev/null +++ b/lib/features/mailbox_dashboard/data/cache/linagora_ecosystem_cache.dart @@ -0,0 +1,27 @@ +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/linagora_ecosystem/linagora_ecosystem.dart'; + +class LinagoraEcosystemCache { + static final LinagoraEcosystemCache _instance = LinagoraEcosystemCache._internal(); + + factory LinagoraEcosystemCache() => _instance; + + LinagoraEcosystemCache._internal(); + + final Map _cache = {}; + + void cacheEcosystem(LinagoraEcosystem ecosystem, String baseUrl) { + _cache[baseUrl] = ecosystem; + } + + LinagoraEcosystem? getCachedEcosystem(String baseUrl) { + return _cache[baseUrl]; + } + + void clearCache() { + _cache.clear(); + } + + bool hasCachedEcosystem(String baseUrl) { + return _cache.containsKey(baseUrl); + } +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/data/network/linagora_ecosystem_api.dart b/lib/features/mailbox_dashboard/data/network/linagora_ecosystem_api.dart index 9b661008f..1686283ec 100644 --- a/lib/features/mailbox_dashboard/data/network/linagora_ecosystem_api.dart +++ b/lib/features/mailbox_dashboard/data/network/linagora_ecosystem_api.dart @@ -5,6 +5,7 @@ import 'package:core/data/network/dio_client.dart'; import 'package:core/utils/app_logger.dart'; import 'package:tmail_ui_user/features/login/data/extensions/service_path_extension.dart'; import 'package:tmail_ui_user/features/login/data/network/endpoint.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/cache/linagora_ecosystem_cache.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/exceptions/linagora_ecosystem_exceptions.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/linagora_ecosystem/api_url_linagora_ecosystem.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/linagora_ecosystem/linagora_ecosystem.dart'; @@ -17,45 +18,51 @@ class LinagoraEcosystemApi { LinagoraEcosystemApi(this._dioClient); Future getLinagoraEcosystem(String baseUrl) async { + final cachedEcosystem = LinagoraEcosystemCache().getCachedEcosystem(baseUrl); + if (cachedEcosystem != null) { + log('LinagoraEcosystemApi::getLinagoraEcosystem: Using cached data'); + return cachedEcosystem; + } + final result = await _dioClient.get( Endpoint.linagoraEcosystem.usingBaseUrl(baseUrl).generateEndpointPath(), ); log('LinagoraEcosystemApi::getLinagoraEcosystem: $result'); + + LinagoraEcosystem ecosystem; if (result is Map) { - return LinagoraEcosystem.deserialize(result); + ecosystem = LinagoraEcosystem.deserialize(result); } else if (result is String) { - return LinagoraEcosystem.deserialize(jsonDecode(result)); + ecosystem = LinagoraEcosystem.deserialize(jsonDecode(result)); } else { throw NotFoundLinagoraEcosystem(); } + + LinagoraEcosystemCache().cacheEcosystem(ecosystem, baseUrl); + + return ecosystem; } Future getPaywallUrl(String baseUrl) async { - final result = await _dioClient.get( - Endpoint.linagoraEcosystem.usingBaseUrl(baseUrl).generateEndpointPath(), - ); - log('LinagoraEcosystemApi::getPaywallUrl: $result'); - LinagoraEcosystem? linagoraEcosystem; - if (result is Map) { - linagoraEcosystem = LinagoraEcosystem.deserialize(result); - } else if (result is String) { - linagoraEcosystem = LinagoraEcosystem.deserialize(jsonDecode(result)); + try { + linagoraEcosystem = await getLinagoraEcosystem(baseUrl); + } catch (exception) { + if (exception is NotFoundLinagoraEcosystem) { + throw NotFoundPaywallUrl(); + } + rethrow; } - if (linagoraEcosystem == null) { - throw NotFoundLinagoraEcosystem(); - } else { - final paywallProperty = - linagoraEcosystem.properties?[LinagoraEcosystemIdentifier.paywallURL] as ApiUrlLinagoraEcosystem?; - log('LinagoraEcosystemApi::getPaywallUrl: paywallProperty = $paywallProperty'); + final paywallProperty = + linagoraEcosystem.properties?[LinagoraEcosystemIdentifier.paywallURL] as ApiUrlLinagoraEcosystem?; + log('LinagoraEcosystemApi::getPaywallUrl: paywallProperty = $paywallProperty'); - if (paywallProperty == null) { - throw NotFoundPaywallUrl(); - } else { - return PaywallUrlPattern(paywallProperty.value); - } + if (paywallProperty == null) { + throw NotFoundPaywallUrl(); + } else { + return PaywallUrlPattern(paywallProperty.value); } } diff --git a/test/features/mailbox_dashboard/linagora_ecosystem_cache_test.dart b/test/features/mailbox_dashboard/linagora_ecosystem_cache_test.dart new file mode 100644 index 000000000..c5c1c4522 --- /dev/null +++ b/test/features/mailbox_dashboard/linagora_ecosystem_cache_test.dart @@ -0,0 +1,106 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/data/cache/linagora_ecosystem_cache.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/linagora_ecosystem/linagora_ecosystem.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/linagora_ecosystem/linagora_ecosystem_identifier.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/linagora_ecosystem/linagora_ecosystem_properties.dart'; + +void main() { + group('LinagoraEcosystemCache Test', () { + const testBaseUrl = 'https://example.com'; + const differentBaseUrl = 'https://different.com'; + + final testEcosystem = LinagoraEcosystem({ + LinagoraEcosystemIdentifier.linShareApiUrl: ApiUrlLinagoraEcosystem('https://linshare.com/api'), + }); + + final differentEcosystem = LinagoraEcosystem({ + LinagoraEcosystemIdentifier.twakeApiUrl: ApiUrlLinagoraEcosystem('https://twake.com/api'), + }); + + tearDown(() { + // Clear cache after each test + LinagoraEcosystemCache().clearCache(); + }); + + test('should cache and retrieve ecosystem correctly', () { + // Cache the ecosystem + LinagoraEcosystemCache().cacheEcosystem(testEcosystem, testBaseUrl); + + // Retrieve from cache + final cachedEcosystem = LinagoraEcosystemCache().getCachedEcosystem(testBaseUrl); + + expect(cachedEcosystem, isNotNull); + expect(cachedEcosystem, equals(testEcosystem)); + }); + + test('should return null for different base URL', () { + // Cache the ecosystem for one base URL + LinagoraEcosystemCache().cacheEcosystem(testEcosystem, testBaseUrl); + + // Try to retrieve for different base URL + final cachedEcosystem = LinagoraEcosystemCache().getCachedEcosystem(differentBaseUrl); + + expect(cachedEcosystem, isNull); + }); + + test('should return null when cache is empty', () { + final cachedEcosystem = LinagoraEcosystemCache().getCachedEcosystem(testBaseUrl); + + expect(cachedEcosystem, isNull); + }); + + test('should clear cache correctly', () { + // Cache the ecosystem + LinagoraEcosystemCache().cacheEcosystem(testEcosystem, testBaseUrl); + + // Verify it's cached + var cachedEcosystem = LinagoraEcosystemCache().getCachedEcosystem(testBaseUrl); + expect(cachedEcosystem, isNotNull); + + // Clear cache + LinagoraEcosystemCache().clearCache(); + + // Verify it's cleared + cachedEcosystem = LinagoraEcosystemCache().getCachedEcosystem(testBaseUrl); + expect(cachedEcosystem, isNull); + }); + + test('should handle multiple base URLs correctly', () { + // Cache ecosystems for different base URLs + LinagoraEcosystemCache().cacheEcosystem(testEcosystem, testBaseUrl); + LinagoraEcosystemCache().cacheEcosystem(differentEcosystem, differentBaseUrl); + + // Verify each base URL gets its own ecosystem + final cachedTestEcosystem = LinagoraEcosystemCache().getCachedEcosystem(testBaseUrl); + final cachedDifferentEcosystem = LinagoraEcosystemCache().getCachedEcosystem(differentBaseUrl); + + expect(cachedTestEcosystem, equals(testEcosystem)); + expect(cachedDifferentEcosystem, equals(differentEcosystem)); + }); + + test('hasCachedEcosystem should return correct boolean', () { + // Initially should be false + expect(LinagoraEcosystemCache().hasCachedEcosystem(testBaseUrl), isFalse); + + // After caching should be true + LinagoraEcosystemCache().cacheEcosystem(testEcosystem, testBaseUrl); + expect(LinagoraEcosystemCache().hasCachedEcosystem(testBaseUrl), isTrue); + + // After clearing should be false again + LinagoraEcosystemCache().clearCache(); + expect(LinagoraEcosystemCache().hasCachedEcosystem(testBaseUrl), isFalse); + }); + }); +} + +class ApiUrlLinagoraEcosystem extends LinagoraEcosystemProperties { + final String value; + + ApiUrlLinagoraEcosystem(this.value); + + @override + List get props => [value]; + + @override + bool? get stringify => true; +} \ No newline at end of file