diff --git a/assets/images/ic_subaddressing_allow.svg b/assets/images/ic_subaddressing_allow.svg
new file mode 100644
index 000000000..b9162f3b1
--- /dev/null
+++ b/assets/images/ic_subaddressing_allow.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/ic_subaddressing_disallow.svg b/assets/images/ic_subaddressing_disallow.svg
new file mode 100644
index 000000000..f3d19f3d3
--- /dev/null
+++ b/assets/images/ic_subaddressing_disallow.svg
@@ -0,0 +1,8 @@
+
diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart
index 4bf5cc9ac..a7c312c35 100644
--- a/core/lib/presentation/resources/image_paths.dart
+++ b/core/lib/presentation/resources/image_paths.dart
@@ -223,6 +223,8 @@ class ImagePaths {
String get icLogoTwakeWelcome => _getImagePath('ic_logo_twake_welcome.svg');
String get icHelp => _getImagePath('ic_help.svg');
String get icDownloadAll => _getImagePath('ic_download_all.svg');
+ String get icSubaddressingAllow => _getImagePath('ic_subaddressing_allow.svg');
+ String get icSubaddressingDisallow => _getImagePath('ic_subaddressing_disallow.svg');
String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
diff --git a/lib/features/base/upgradeable/upgrade_hive_database_steps_v13.dart b/lib/features/base/upgradeable/upgrade_hive_database_steps_v13.dart
new file mode 100644
index 000000000..481b8ef40
--- /dev/null
+++ b/lib/features/base/upgradeable/upgrade_hive_database_steps_v13.dart
@@ -0,0 +1,17 @@
+
+import 'package:tmail_ui_user/features/base/upgradeable/upgrade_database_steps.dart';
+import 'package:tmail_ui_user/features/caching/caching_manager.dart';
+
+class UpgradeHiveDatabaseStepsV13 extends UpgradeDatabaseSteps {
+
+ final CachingManager _cachingManager;
+
+ UpgradeHiveDatabaseStepsV13(this._cachingManager);
+
+ @override
+ Future onUpgrade(int oldVersion, int newVersion) async {
+ if (oldVersion > 0 && oldVersion < newVersion && newVersion == 13) {
+ await _cachingManager.clearMailboxCache();
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/features/caching/caching_manager.dart b/lib/features/caching/caching_manager.dart
index 613751f07..fb22bc36c 100644
--- a/lib/features/caching/caching_manager.dart
+++ b/lib/features/caching/caching_manager.dart
@@ -118,6 +118,12 @@ class CachingManager {
], eagerError: true);
}
+ Future clearMailboxCache() {
+ return Future.wait([
+ _mailboxCacheClient.clearAllData(),
+ ], eagerError: true);
+ }
+
Future storeCacheVersion(int newVersion) async {
log('CachingManager::storeCacheVersion():newVersion = $newVersion');
return _hiveCacheVersionClient.storeVersion(newVersion);
diff --git a/lib/features/caching/config/hive_cache_config.dart b/lib/features/caching/config/hive_cache_config.dart
index 0a8b61c47..ea8df229a 100644
--- a/lib/features/caching/config/hive_cache_config.dart
+++ b/lib/features/caching/config/hive_cache_config.dart
@@ -9,6 +9,7 @@ import 'package:path_provider/path_provider.dart' as path_provider;
import 'package:tmail_ui_user/features/base/upgradeable/upgrade_hive_database_steps_v10.dart';
import 'package:tmail_ui_user/features/base/upgradeable/upgrade_hive_database_steps_v11.dart';
import 'package:tmail_ui_user/features/base/upgradeable/upgrade_hive_database_steps_v12.dart';
+import 'package:tmail_ui_user/features/base/upgradeable/upgrade_hive_database_steps_v13.dart';
import 'package:tmail_ui_user/features/base/upgradeable/upgrade_hive_database_steps_v7.dart';
import 'package:tmail_ui_user/features/caching/caching_manager.dart';
import 'package:tmail_ui_user/features/caching/config/cache_version.dart';
@@ -70,6 +71,7 @@ class HiveCacheConfig {
await UpgradeHiveDatabaseStepsV10(cachingManager).onUpgrade(oldVersion, newVersion);
await UpgradeHiveDatabaseStepsV11(cachingManager).onUpgrade(oldVersion, newVersion);
await UpgradeHiveDatabaseStepsV12(cachingManager).onUpgrade(oldVersion, newVersion);
+ await UpgradeHiveDatabaseStepsV13(cachingManager).onUpgrade(oldVersion, newVersion);
if (oldVersion != newVersion) {
await cachingManager.storeCacheVersion(newVersion);
diff --git a/lib/features/mailbox/data/datasource/mailbox_datasource.dart b/lib/features/mailbox/data/datasource/mailbox_datasource.dart
index dc5238178..5a70c5b6e 100644
--- a/lib/features/mailbox/data/datasource/mailbox_datasource.dart
+++ b/lib/features/mailbox/data/datasource/mailbox_datasource.dart
@@ -18,6 +18,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/model/get_mailbox_by_role_
import 'package:tmail_ui_user/features/mailbox/domain/model/jmap_mailbox_response.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/move_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart';
+import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_right_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_multiple_mailbox_request.dart';
@@ -49,6 +50,8 @@ abstract class MailboxDataSource {
Future> subscribeMultipleMailbox(Session session, AccountId accountId, SubscribeMultipleMailboxRequest subscribeRequest);
+ Future handleMailboxRightRequest(Session session, AccountId accountId, MailboxRightRequest request);
+
Future> createDefaultMailbox(Session session, AccountId accountId, List listRole);
Future setRoleDefaultMailbox(Session session, AccountId accountId, List listMailbox);
diff --git a/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart b/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart
index 3c5496f13..29d609211 100644
--- a/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart
+++ b/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart
@@ -23,6 +23,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/model/get_mailbox_by_role_
import 'package:tmail_ui_user/features/mailbox/domain/model/jmap_mailbox_response.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/move_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart';
+import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_right_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_multiple_mailbox_request.dart';
import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
@@ -134,6 +135,11 @@ class MailboxCacheDataSourceImpl extends MailboxDataSource {
throw UnimplementedError();
}
+ @override
+ Future handleMailboxRightRequest(Session session, AccountId accountId, MailboxRightRequest request) {
+ throw UnimplementedError();
+ }
+
@override
Future> createDefaultMailbox(Session session, AccountId accountId, List listRole) {
throw UnimplementedError();
diff --git a/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart b/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart
index fdcd4e7f5..2464f76bd 100644
--- a/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart
+++ b/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart
@@ -22,6 +22,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/model/get_mailbox_by_role_
import 'package:tmail_ui_user/features/mailbox/domain/model/jmap_mailbox_response.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/move_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart';
+import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_right_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_multiple_mailbox_request.dart';
import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
@@ -121,6 +122,13 @@ class MailboxDataSourceImpl extends MailboxDataSource {
}).catchError(_exceptionThrower.throwException);
}
+ @override
+ Future handleMailboxRightRequest(Session session, AccountId accountId, MailboxRightRequest request) {
+ return Future.sync(() async {
+ return await mailboxAPI.handleMailboxRightRequest(session, accountId, request);
+ }).catchError(_exceptionThrower.throwException);
+ }
+
@override
Future> createDefaultMailbox(Session session, AccountId accountId, List listRole) {
return Future.sync(() async {
diff --git a/lib/features/mailbox/data/extensions/mailbox_cache_extension.dart b/lib/features/mailbox/data/extensions/mailbox_cache_extension.dart
index 84652e112..594eb3e3b 100644
--- a/lib/features/mailbox/data/extensions/mailbox_cache_extension.dart
+++ b/lib/features/mailbox/data/extensions/mailbox_cache_extension.dart
@@ -20,7 +20,8 @@ extension MailboxCacheExtension on MailboxCache {
unreadThreads: unreadThreads != null ? UnreadThreads(UnsignedInt(unreadThreads!)) : null,
myRights: myRights?.toMailboxRights(),
isSubscribed: isSubscribed != null ? IsSubscribed(isSubscribed!) : null,
- namespace: namespace != null ? Namespace(namespace!) : null
+ namespace: namespace != null ? Namespace(namespace!) : null,
+ rights: rights != null ? Map?>.from(rights!) : null,
);
}
}
\ No newline at end of file
diff --git a/lib/features/mailbox/data/extensions/mailbox_extension.dart b/lib/features/mailbox/data/extensions/mailbox_extension.dart
index 6735803fe..965d606a7 100644
--- a/lib/features/mailbox/data/extensions/mailbox_extension.dart
+++ b/lib/features/mailbox/data/extensions/mailbox_extension.dart
@@ -17,7 +17,8 @@ extension MailboxExtension on Mailbox {
unreadThreads: unreadThreads?.value.value.round(),
myRights: myRights?.toMailboxRightsCache(),
isSubscribed: isSubscribed?.value,
- namespace: namespace?.value
+ namespace: namespace?.value,
+ rights: rights?.map((key, value) => MapEntry(key, value)),
);
}
}
\ No newline at end of file
diff --git a/lib/features/mailbox/data/model/mailbox_cache.dart b/lib/features/mailbox/data/model/mailbox_cache.dart
index 05fe3e005..4463e7e45 100644
--- a/lib/features/mailbox/data/model/mailbox_cache.dart
+++ b/lib/features/mailbox/data/model/mailbox_cache.dart
@@ -48,6 +48,9 @@ class MailboxCache extends HiveObject with EquatableMixin {
@HiveField(12)
final String? namespace;
+ @HiveField(13)
+ final Map?>? rights;
+
MailboxCache(
this.id,
{
@@ -63,6 +66,7 @@ class MailboxCache extends HiveObject with EquatableMixin {
this.isSubscribed,
this.lastOpened,
this.namespace,
+ this.rights
}
);
@@ -80,5 +84,6 @@ class MailboxCache extends HiveObject with EquatableMixin {
myRights,
isSubscribed,
namespace,
+ rights
];
}
\ No newline at end of file
diff --git a/lib/features/mailbox/data/network/mailbox_api.dart b/lib/features/mailbox/data/network/mailbox_api.dart
index 462b72ebc..5d5332120 100644
--- a/lib/features/mailbox/data/network/mailbox_api.dart
+++ b/lib/features/mailbox/data/network/mailbox_api.dart
@@ -2,6 +2,8 @@ import 'dart:async';
import 'package:collection/collection.dart';
import 'package:core/utils/app_logger.dart';
+import 'package:flutter/material.dart' hide State;
+import 'package:get/get.dart';
import 'package:jmap_dart_client/http/http_client.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
@@ -26,20 +28,24 @@ import 'package:jmap_dart_client/jmap/mail/mailbox/query/query_mailbox_method.da
import 'package:jmap_dart_client/jmap/mail/mailbox/set/set_mailbox_method.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/set/set_mailbox_response.dart';
import 'package:model/error_type_handler/set_method_error_handler_mixin.dart';
+import 'package:model/mailbox/mailbox_constants.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/base/mixin/handle_error_mixin.dart';
import 'package:tmail_ui_user/features/composer/domain/exceptions/set_method_exception.dart';
import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart';
import 'package:tmail_ui_user/features/mailbox/domain/exceptions/mailbox_exception.dart';
import 'package:tmail_ui_user/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart';
+import 'package:tmail_ui_user/features/mailbox/domain/exceptions/set_mailbox_rights_exception.dart';
import 'package:tmail_ui_user/features/mailbox/domain/extensions/list_mailbox_id_extension.dart';
import 'package:tmail_ui_user/features/mailbox/domain/extensions/role_extension.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/get_mailbox_by_role_response.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/jmap_mailbox_response.dart';
+import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_subaddressing_action.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_subscribe_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/move_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart';
+import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_right_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_multiple_mailbox_request.dart';
import 'package:tmail_ui_user/main/error/capability_validator.dart';
@@ -401,6 +407,53 @@ class MailboxAPI with HandleSetErrorMixin {
return listMailboxIdSubscribe ?? [];
}
+ List _updateRightsForSubaddressing(MailboxSubaddressingAction action, List? currentRights) {
+ final updatedRights = List.from(currentRights ?? []);
+
+ if (action == MailboxSubaddressingAction.allow) {
+ updatedRights.addIf(!updatedRights.contains(postingRight), postingRight);
+ } else {
+ updatedRights.remove(postingRight);
+ }
+
+ return updatedRights;
+ }
+
+ @visibleForTesting
+ List updateRightsForSubaddressing(MailboxSubaddressingAction action, List? currentRights)
+ => _updateRightsForSubaddressing(action, currentRights);
+
+ Future handleMailboxRightRequest(Session session, AccountId accountId, MailboxRightRequest request) async {
+ final setMailboxMethod = SetMailboxMethod(accountId)
+ ..addUpdates({
+ request.mailboxId.id : PatchObject({
+ 'sharedWith/$anyoneIdentifier': _updateRightsForSubaddressing(request.subaddressingAction, request.currentRights?[anyoneIdentifier])
+ })
+ });
+
+ final requestBuilder = JmapRequestBuilder(httpClient, ProcessingInvocation());
+
+ final setMailboxInvocation = requestBuilder.invocation(setMailboxMethod);
+
+ final capabilities = setMailboxMethod.requiredCapabilities
+ .toCapabilitiesSupportTeamMailboxes(session, accountId);
+
+ final response = await (requestBuilder
+ ..usings(capabilities))
+ .build()
+ .execute();
+
+ final setMailboxResponse = response.parse(
+ setMailboxInvocation.methodCallId,
+ SetMailboxResponse.deserialize);
+
+ if (setMailboxResponse?.updated?.containsKey(request.mailboxId.id) ?? false) {
+ return true;
+ } else {
+ throw SetMailboxRightsException();
+ }
+ }
+
Future> createDefaultMailbox(
Session session,
AccountId accountId,
diff --git a/lib/features/mailbox/data/repository/mailbox_repository_impl.dart b/lib/features/mailbox/data/repository/mailbox_repository_impl.dart
index 0aa44a660..0ab32b1de 100644
--- a/lib/features/mailbox/data/repository/mailbox_repository_impl.dart
+++ b/lib/features/mailbox/data/repository/mailbox_repository_impl.dart
@@ -30,6 +30,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/model/jmap_mailbox_respons
import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_response.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/move_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart';
+import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_right_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_multiple_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart';
@@ -285,6 +286,11 @@ class MailboxRepositoryImpl extends MailboxRepository {
return mapDataSource[DataSourceType.network]!.subscribeMultipleMailbox(session, accountId, subscribeRequest);
}
+ @override
+ Future handleMailboxRightRequest(Session session, AccountId accountId, MailboxRightRequest request) {
+ return mapDataSource[DataSourceType.network]!.handleMailboxRightRequest(session, accountId, request);
+ }
+
@override
Future> createDefaultMailbox(Session session, AccountId accountId, List listRole) {
return mapDataSource[DataSourceType.network]!.createDefaultMailbox(session, accountId, listRole);
diff --git a/lib/features/mailbox/domain/constants/mailbox_constants.dart b/lib/features/mailbox/domain/constants/mailbox_constants.dart
index 36f7d97bf..36b221ba8 100644
--- a/lib/features/mailbox/domain/constants/mailbox_constants.dart
+++ b/lib/features/mailbox/domain/constants/mailbox_constants.dart
@@ -16,7 +16,8 @@ class MailboxConstants {
MailboxProperty.unreadEmails,
MailboxProperty.unreadThreads,
MailboxProperty.myRights,
- MailboxProperty.namespace
+ MailboxProperty.namespace,
+ MailboxProperty.rights
});
static final List defaultMailboxRoles = [
diff --git a/lib/features/mailbox/domain/exceptions/null_session_or_accountid_exception.dart b/lib/features/mailbox/domain/exceptions/null_session_or_accountid_exception.dart
new file mode 100644
index 000000000..2e9bc3e7b
--- /dev/null
+++ b/lib/features/mailbox/domain/exceptions/null_session_or_accountid_exception.dart
@@ -0,0 +1,8 @@
+
+class NullSessionOrAccountIdException implements Exception {
+
+ NullSessionOrAccountIdException();
+
+ @override
+ String toString() => 'NullSessionOrAccountIdException: session and accountId should not be null';
+}
diff --git a/lib/features/mailbox/domain/exceptions/set_mailbox_rights_exception.dart b/lib/features/mailbox/domain/exceptions/set_mailbox_rights_exception.dart
new file mode 100644
index 000000000..211c4b3ce
--- /dev/null
+++ b/lib/features/mailbox/domain/exceptions/set_mailbox_rights_exception.dart
@@ -0,0 +1,8 @@
+
+class SetMailboxRightsException implements Exception {
+
+ SetMailboxRightsException();
+
+ @override
+ String toString() => 'Failed to update mailbox rights.';
+}
\ No newline at end of file
diff --git a/lib/features/mailbox/domain/model/mailbox_right_request.dart b/lib/features/mailbox/domain/model/mailbox_right_request.dart
new file mode 100644
index 000000000..cf09072c2
--- /dev/null
+++ b/lib/features/mailbox/domain/model/mailbox_right_request.dart
@@ -0,0 +1,23 @@
+import 'package:equatable/equatable.dart';
+import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
+import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_subaddressing_action.dart';
+
+class MailboxRightRequest with EquatableMixin {
+
+ final MailboxSubaddressingAction subaddressingAction;
+ final MailboxId mailboxId;
+ final Map?>? currentRights;
+
+ MailboxRightRequest(
+ this.mailboxId,
+ this.currentRights,
+ this.subaddressingAction
+ );
+
+ @override
+ List