TF-1897 Implement resend sending email when failed

(cherry picked from commit f508b65688503e9ae8ece5a1924e84481b98a39e)
This commit is contained in:
dab246
2023-06-10 19:20:30 +07:00
committed by Dat Vu
parent b6528b5bf5
commit c5bd77f800
16 changed files with 338 additions and 129 deletions
@@ -21,7 +21,6 @@ class SendingEmailCacheManager {
SendingEmailHiveCache sendingEmailHiveCache SendingEmailHiveCache sendingEmailHiveCache
) async { ) async {
final keyCache = TupleKey(sendingEmailHiveCache.sendingId, accountId.asString, userName.value).encodeKey; final keyCache = TupleKey(sendingEmailHiveCache.sendingId, accountId.asString, userName.value).encodeKey;
log('SendingEmailCacheManager::storeSendingEmail():keyCache: $keyCache | sendingEmailHiveCache: $sendingEmailHiveCache');
await _hiveCacheClient.insertItem(keyCache, sendingEmailHiveCache); await _hiveCacheClient.insertItem(keyCache, sendingEmailHiveCache);
final newSendingEmailHiveCache = await _hiveCacheClient.getItem(keyCache); final newSendingEmailHiveCache = await _hiveCacheClient.getItem(keyCache);
if (newSendingEmailHiveCache != null) { if (newSendingEmailHiveCache != null) {
@@ -32,29 +31,15 @@ class SendingEmailCacheManager {
} }
} }
Future<List<SendingEmailHiveCache>> getAllSendingEmailsByTupleKey( Future<List<SendingEmailHiveCache>> getAllSendingEmailsByTupleKey(AccountId accountId, UserName userName) async {
AccountId accountId, final sendingEmailsCache = await _hiveCacheClient.getListByTupleKey(accountId.asString, userName.value);
UserName userName,
{bool needToReopen = false}
) async {
final sendingEmailsCache = await _hiveCacheClient.getListByTupleKey(
accountId.asString,
userName.value,
needToReopen: needToReopen);
log('SendingEmailCacheManager::getAllSendingEmailsByTupleKey():COUNT: ${sendingEmailsCache.length}');
sendingEmailsCache.sortByLatestTime(); sendingEmailsCache.sortByLatestTime();
return sendingEmailsCache; return sendingEmailsCache;
} }
Future<void> deleteSendingEmail( Future<void> deleteSendingEmail(AccountId accountId, UserName userName, String sendingId) async {
AccountId accountId,
UserName userName,
String sendingId,
{bool needToReopen = false}
) async {
final keyCache = TupleKey(sendingId, accountId.asString, userName.value).encodeKey; final keyCache = TupleKey(sendingId, accountId.asString, userName.value).encodeKey;
log('SendingEmailCacheManager::deleteSendingEmail():keyCache: $keyCache'); await _hiveCacheClient.deleteItem(keyCache);
await _hiveCacheClient.deleteItem(keyCache, needToReopen: needToReopen);
final storedSendingEmail = await _hiveCacheClient.getItem(keyCache); final storedSendingEmail = await _hiveCacheClient.getItem(keyCache);
if (storedSendingEmail != null) { if (storedSendingEmail != null) {
log('SendingEmailCacheManager::deleteSendingEmail():sendingId: ${storedSendingEmail.sendingId}'); log('SendingEmailCacheManager::deleteSendingEmail():sendingId: ${storedSendingEmail.sendingId}');
@@ -62,9 +47,8 @@ class SendingEmailCacheManager {
} }
} }
Future<List<SendingEmailHiveCache>> getAllSendingEmails({bool needToReopen = false}) async { Future<List<SendingEmailHiveCache>> getAllSendingEmails() async {
final sendingEmailsCache = await _hiveCacheClient.getAll(needToReopen: needToReopen); final sendingEmailsCache = await _hiveCacheClient.getAll();
log('SendingEmailCacheManager::getAllSendingEmails():COUNT: ${sendingEmailsCache.length}');
sendingEmailsCache.sortByLatestTime(); sendingEmailsCache.sortByLatestTime();
return sendingEmailsCache; return sendingEmailsCache;
} }
@@ -74,12 +58,10 @@ class SendingEmailCacheManager {
Future<SendingEmailHiveCache> updateSendingEmail( Future<SendingEmailHiveCache> updateSendingEmail(
AccountId accountId, AccountId accountId,
UserName userName, UserName userName,
SendingEmailHiveCache sendingEmailHiveCache, SendingEmailHiveCache sendingEmailHiveCache
{bool needToReopen = false}
) async { ) async {
final keyCache = TupleKey(sendingEmailHiveCache.sendingId, accountId.asString, userName.value).encodeKey; final keyCache = TupleKey(sendingEmailHiveCache.sendingId, accountId.asString, userName.value).encodeKey;
log('SendingEmailCacheManager::updateSendingEmail():keyCache: $keyCache | sendingEmailHiveCache: $sendingEmailHiveCache'); await _hiveCacheClient.updateItem(keyCache, sendingEmailHiveCache);
await _hiveCacheClient.updateItem(keyCache, sendingEmailHiveCache, needToReopen: needToReopen);
final newSendingEmailHiveCache = await _hiveCacheClient.getItem(keyCache); final newSendingEmailHiveCache = await _hiveCacheClient.getItem(keyCache);
if (newSendingEmailHiveCache != null) { if (newSendingEmailHiveCache != null) {
log('SendingEmailCacheManager::updateSendingEmail():sendingId: ${newSendingEmailHiveCache.sendingId} | sendingState: ${newSendingEmailHiveCache.sendingState}'); log('SendingEmailCacheManager::updateSendingEmail():sendingId: ${newSendingEmailHiveCache.sendingId} | sendingState: ${newSendingEmailHiveCache.sendingState}');
@@ -88,4 +70,31 @@ class SendingEmailCacheManager {
throw NotFoundSendingEmailHiveObject(); throw NotFoundSendingEmailHiveObject();
} }
} }
Future<List<SendingEmailHiveCache>> updateMultipleSendingEmail(
AccountId accountId,
UserName userName,
List<SendingEmailHiveCache> listSendingEmailHiveCache
) async {
final mapSendingEmailCache = {
for (var sendingEmailCache in listSendingEmailHiveCache)
TupleKey(sendingEmailCache.sendingId, accountId.asString, userName.value).encodeKey: sendingEmailCache
};
await _hiveCacheClient.updateMultipleItem(mapSendingEmailCache);
final newListSendingEmailCache = await _hiveCacheClient.getValuesByListKey(mapSendingEmailCache.keys.toList());
log('SendingEmailCacheManager::updateMultipleSendingEmail():newListSendingEmailCache: ${newListSendingEmailCache.map((sendingEmail) => '${sendingEmail.sendingId} | ${sendingEmail.sendingState}').toList()}');
return newListSendingEmailCache;
}
Future<void> deleteMultipleSendingEmail(AccountId accountId, UserName userName, List<String> sendingIds) async {
final listTupleKey = sendingIds.map((sendingId) => TupleKey(sendingId, accountId.asString, userName.value).encodeKey).toList();
await _hiveCacheClient.deleteMultipleItem(listTupleKey);
final newListSendingEmailCache = await _hiveCacheClient.getValuesByListKey(listTupleKey);
log('SendingEmailCacheManager::deleteMultipleSendingEmail():newListSendingEmailCache: ${newListSendingEmailCache.map((sendingEmail) => '${sendingEmail.sendingId} | ${sendingEmail.sendingState}').toList()}');
if (newListSendingEmailCache.isNotEmpty) {
throw ExistSendingEmailHiveObject();
}
}
Future<void> closeSendingEmailHiveCacheBox() => _hiveCacheClient.closeBox();
} }
@@ -23,6 +23,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_r
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart';
import 'package:tmail_ui_user/features/offline_mode/bindings/sending_email_interactor_bindings.dart'; import 'package:tmail_ui_user/features/offline_mode/bindings/sending_email_interactor_bindings.dart';
import 'package:tmail_ui_user/features/offline_mode/exceptions/workmanager_exception.dart'; import 'package:tmail_ui_user/features/offline_mode/exceptions/workmanager_exception.dart';
import 'package:tmail_ui_user/features/offline_mode/manager/sending_email_cache_manager.dart';
import 'package:tmail_ui_user/features/offline_mode/model/sending_state.dart'; import 'package:tmail_ui_user/features/offline_mode/model/sending_state.dart';
import 'package:tmail_ui_user/features/offline_mode/observer/work_observer.dart'; import 'package:tmail_ui_user/features/offline_mode/observer/work_observer.dart';
import 'package:tmail_ui_user/features/push_notification/presentation/notification/local_notification_config.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/notification/local_notification_config.dart';
@@ -53,6 +54,7 @@ class SendingEmailObserver extends WorkObserver {
DeleteSendingEmailInteractor? _deleteSendingEmailInteractor; DeleteSendingEmailInteractor? _deleteSendingEmailInteractor;
SendingQueueIsolateManager? _sendingQueueIsolateManager; SendingQueueIsolateManager? _sendingQueueIsolateManager;
UpdateSendingEmailInteractor? _updateSendingEmailInteractor; UpdateSendingEmailInteractor? _updateSendingEmailInteractor;
SendingEmailCacheManager? _sendingEmailCacheManager;
Completer<bool>? _completer; Completer<bool>? _completer;
@@ -64,7 +66,6 @@ class SendingEmailObserver extends WorkObserver {
@override @override
Future<void> observe(String taskId, Map<String, dynamic> inputData, Completer<bool> completer) async { Future<void> observe(String taskId, Map<String, dynamic> inputData, Completer<bool> completer) async {
log('SendingEmailObserver::observe():taskId: $taskId | inputData: $inputData');
_completer = completer; _completer = completer;
_sendingEmail = SendingEmail.fromJson(inputData); _sendingEmail = SendingEmail.fromJson(inputData);
log('SendingEmailObserver::observe():_sendingEmail: $_sendingEmail'); log('SendingEmailObserver::observe():_sendingEmail: $_sendingEmail');
@@ -85,14 +86,20 @@ class SendingEmailObserver extends WorkObserver {
SendEmailInteractorBindings().dependencies(); SendEmailInteractorBindings().dependencies();
}); });
return await _getInteractorBindings(); await _getInteractorBindings();
await _sendingEmailCacheManager?.closeSendingEmailHiveCacheBox();
return Future.value();
} }
@override @override
void handleFailureViewState(Failure failure) { void handleFailureViewState(Failure failure) {
log('SendingEmailObserver::_handleFailureViewState(): $failure'); log('SendingEmailObserver::_handleFailureViewState(): $failure');
if (failure is SendEmailFailure || failure is DeleteSendingEmailFailure) { if (failure is SendEmailFailure) {
_updateStoredSendingEmail(SendingState.error); _handleSendEmailFailure(failure);
} else if (failure is DeleteSendingEmailFailure) {
_handleDeleteSendingEmailFailure(failure);
} else if (failure is GetAuthenticatedAccountFailure || } else if (failure is GetAuthenticatedAccountFailure ||
failure is NoAuthenticatedAccountFailure || failure is NoAuthenticatedAccountFailure ||
failure is GetSessionFailure || failure is GetSessionFailure ||
@@ -115,7 +122,7 @@ class SendingEmailObserver extends WorkObserver {
} else if (success is SendEmailSuccess) { } else if (success is SendEmailSuccess) {
_handleSendEmailSuccess(success); _handleSendEmailSuccess(success);
} else if (success is DeleteSendingEmailSuccess) { } else if (success is DeleteSendingEmailSuccess) {
_handleDeleteSendingEmailSuccess(); _handleDeleteSendingEmailSuccess(success);
} else if (success is UpdateSendingEmailSuccess) { } else if (success is UpdateSendingEmailSuccess) {
_handleUpdateStoredSendingEmailSuccess(success); _handleUpdateStoredSendingEmailSuccess(success);
} }
@@ -137,6 +144,7 @@ class SendingEmailObserver extends WorkObserver {
_deleteSendingEmailInteractor = getBinding<DeleteSendingEmailInteractor>(); _deleteSendingEmailInteractor = getBinding<DeleteSendingEmailInteractor>();
_sendingQueueIsolateManager = getBinding<SendingQueueIsolateManager>(); _sendingQueueIsolateManager = getBinding<SendingQueueIsolateManager>();
_updateSendingEmailInteractor = getBinding<UpdateSendingEmailInteractor>(); _updateSendingEmailInteractor = getBinding<UpdateSendingEmailInteractor>();
_sendingEmailCacheManager = getBinding<SendingEmailCacheManager>();
} catch (e) { } catch (e) {
logError('SendingEmailObserver::_getInteractorBindings(): ${e.toString()}'); logError('SendingEmailObserver::_getInteractorBindings(): ${e.toString()}');
_handleTaskFailureInWorkManager(); _handleTaskFailureInWorkManager();
@@ -153,19 +161,11 @@ class SendingEmailObserver extends WorkObserver {
} }
void _getAuthenticatedAccount() { void _getAuthenticatedAccount() {
if (_getAuthenticatedAccountInteractor != null) { consumeState(_getAuthenticatedAccountInteractor!.execute());
consumeState(_getAuthenticatedAccountInteractor!.execute());
} else {
_handleTaskFailureInWorkManager();
}
} }
void _getSessionAction() { void _getSessionAction() {
if (_getSessionInteractor != null) { consumeState(_getSessionInteractor!.execute());
consumeState(_getSessionInteractor!.execute());
} else {
_handleTaskFailureInWorkManager();
}
} }
void _handleGetSessionSuccess(GetSessionSuccess success) async { void _handleGetSessionSuccess(GetSessionSuccess success) async {
@@ -174,13 +174,7 @@ class SendingEmailObserver extends WorkObserver {
final apiUrl = success.session.getQualifiedApiUrl(baseUrl: _dynamicUrlInterceptors?.jmapUrl); final apiUrl = success.session.getQualifiedApiUrl(baseUrl: _dynamicUrlInterceptors?.jmapUrl);
if (apiUrl.isNotEmpty) { if (apiUrl.isNotEmpty) {
_dynamicUrlInterceptors?.changeBaseUrl(apiUrl); _dynamicUrlInterceptors?.changeBaseUrl(apiUrl);
_sendEmailAction();
_updateStoredSendingEmail(SendingState.running);
await Future.delayed(
const Duration(milliseconds: 2000),
_sendEmailAction
);
} else { } else {
_handleTaskFailureInWorkManager(); _handleTaskFailureInWorkManager();
} }
@@ -197,26 +191,32 @@ class SendingEmailObserver extends WorkObserver {
} }
void _sendEmailAction() { void _sendEmailAction() {
if (_sendEmailInteractor != null && _isDataParameterNotNull) { consumeState(
final mailboxRequest = _sendingEmail!.mailboxNameRequest != null && _sendingEmail!.creationIdRequest != null _sendEmailInteractor!.execute(
? CreateNewMailboxRequest(_sendingEmail!.creationIdRequest!, _sendingEmail!.mailboxNameRequest!)
: null;
consumeState(_sendEmailInteractor!.execute(
_currentSession!, _currentSession!,
_currentAccountId!, _currentAccountId!,
_sendingEmail!.toEmailRequest(), _sendingEmail!.toEmailRequest(),
mailboxRequest: mailboxRequest mailboxRequest: _getMailboxRequest()
)); )
);
}
CreateNewMailboxRequest? _getMailboxRequest() {
if (_sendingEmail!.mailboxNameRequest != null &&
_sendingEmail!.creationIdRequest != null) {
return CreateNewMailboxRequest(
_sendingEmail!.creationIdRequest!,
_sendingEmail!.mailboxNameRequest!);
} else { } else {
_updateStoredSendingEmail(SendingState.error); return null;
} }
} }
void _handleGetAccountByOidcSuccess(GetStoredTokenOidcSuccess storedTokenOidcSuccess) { void _handleGetAccountByOidcSuccess(GetStoredTokenOidcSuccess storedTokenOidcSuccess) {
_dynamicUrlInterceptors?.setJmapUrl(storedTokenOidcSuccess.baseUrl.toString()); _dynamicUrlInterceptors?.setJmapUrl(storedTokenOidcSuccess.baseUrl.toString());
_authorizationInterceptors?.setTokenAndAuthorityOidc( _authorizationInterceptors?.setTokenAndAuthorityOidc(
newToken: storedTokenOidcSuccess.tokenOidc.toToken(), newToken: storedTokenOidcSuccess.tokenOidc.toToken(),
newConfig: storedTokenOidcSuccess.oidcConfiguration newConfig: storedTokenOidcSuccess.oidcConfiguration
); );
_dynamicUrlInterceptors?.changeBaseUrl(storedTokenOidcSuccess.baseUrl.toString()); _dynamicUrlInterceptors?.changeBaseUrl(storedTokenOidcSuccess.baseUrl.toString());
_getSessionAction(); _getSessionAction();
@@ -224,28 +224,31 @@ class SendingEmailObserver extends WorkObserver {
void _handleSendEmailSuccess(SendEmailSuccess success) { void _handleSendEmailSuccess(SendEmailSuccess success) {
_showLocalNotification(); _showLocalNotification();
_deleteSendingEmailAction(); _updateStoredSendingEmail(SendingState.success);
}
void _handleSendEmailFailure(SendEmailFailure failure) {
_updateStoredSendingEmail(SendingState.error);
} }
void _deleteSendingEmailAction() { void _deleteSendingEmailAction() {
log('SendingEmailObserver::_deleteSendingEmailAction():'); consumeState(
if (_deleteSendingEmailInteractor != null && _isDataParameterNotNull) { _deleteSendingEmailInteractor!.execute(
consumeState(_deleteSendingEmailInteractor!.execute(
_currentAccountId!, _currentAccountId!,
_currentSession!.username, _currentSession!.username,
_sendingEmail!.sendingId, _sendingEmail!.sendingId
needToReopen: true )
)); );
} else {
log('SendingEmailObserver::_deleteSendingEmailAction(): NOT CALLED');
_updateStoredSendingEmail(SendingState.error);
}
} }
void _handleDeleteSendingEmailSuccess() { void _handleDeleteSendingEmailSuccess(DeleteSendingEmailSuccess success) {
_handleTaskSuccessInWorkManager(); _handleTaskSuccessInWorkManager();
} }
void _handleDeleteSendingEmailFailure(DeleteSendingEmailFailure failure) {
_handleTaskFailureInWorkManager();
}
void _showLocalNotification() { void _showLocalNotification() {
LocalNotificationManager.instance.showPushNotification( LocalNotificationManager.instance.showPushNotification(
id: _sendingEmail?.sendingId ?? '', id: _sendingEmail?.sendingId ?? '',
@@ -255,26 +258,26 @@ class SendingEmailObserver extends WorkObserver {
); );
} }
bool get _isDataParameterNotNull => _currentSession != null && _currentAccountId != null && _sendingEmail != null;
void _updateStoredSendingEmail(SendingState newState) { void _updateStoredSendingEmail(SendingState newState) {
log('SendingEmailObserver::_updateStoredSendingEmail():newState: $newState'); log('SendingEmailObserver::_updateStoredSendingEmail():newState: $newState');
if (_updateSendingEmailInteractor != null && _isDataParameterNotNull) { consumeState(
consumeState(_updateSendingEmailInteractor!.execute( _updateSendingEmailInteractor!.execute(
_currentAccountId!, _currentAccountId!,
_currentSession!.username, _currentSession!.username,
_sendingEmail!.updatingSendingState(newState), _sendingEmail!.updatingSendingState(newState)
needToReopen: true )
)); );
} else {
_handleTaskFailureInWorkManager();
}
} }
void _handleUpdateStoredSendingEmailSuccess(UpdateSendingEmailSuccess success) { void _handleUpdateStoredSendingEmailSuccess(UpdateSendingEmailSuccess success) {
_updatingSendingStateToMainUI( log('SendingEmailObserver::_handleUpdateStoredSendingEmailSuccess(): $success');
sendingState: success.newSendingEmail.sendingState, if (success.newSendingEmail.isSuccess) {
sendingId: success.newSendingEmail.sendingId); _deleteSendingEmailAction();
} else {
_updatingSendingStateToMainUI(
sendingState: success.newSendingEmail.sendingState,
sendingId: success.newSendingEmail.sendingId);
}
} }
void _handleTaskFailureInWorkManager() async { void _handleTaskFailureInWorkManager() async {
@@ -0,0 +1,9 @@
import 'package:tmail_ui_user/features/offline_mode/model/sending_email_hive_cache.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/extensions/sending_email_extension.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
extension ListSendingEmailExtension on List<SendingEmail> {
List<SendingEmailHiveCache> toHiveCache() => map((sendingEmail) => sendingEmail.toHiveCache()).toList();
List<String> get sendingIds => map((sendingEmail) => sendingEmail.sendingId).toSet().toList();
}
@@ -101,6 +101,10 @@ class SendingEmail with EquatableMixin {
bool get isWaiting => sendingState == SendingState.waiting; bool get isWaiting => sendingState == SendingState.waiting;
bool get isError => sendingState == SendingState.error;
bool get isSuccess => sendingState == SendingState.success;
@override @override
List<Object?> get props => [ List<Object?> get props => [
sendingId, sendingId,
@@ -0,0 +1,40 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
class UpdateMultipleSendingEmailLoading extends UIState {}
class UpdateMultipleSendingEmailAllSuccess extends UIState {
final List<SendingEmail> newSendingEmails;
UpdateMultipleSendingEmailAllSuccess(this.newSendingEmails);
@override
List<Object?> get props => [newSendingEmails];
}
class UpdateMultipleSendingEmailHasSomeSuccess extends UIState {
final List<SendingEmail> newSendingEmails;
UpdateMultipleSendingEmailHasSomeSuccess(this.newSendingEmails);
@override
List<Object?> get props => [newSendingEmails];
}
class UpdateMultipleSendingEmailAllFailure extends FeatureFailure {
UpdateMultipleSendingEmailAllFailure(dynamic exception) : super(exception: exception);
@override
List<Object?> get props => [exception];
}
class UpdateMultipleSendingEmailFailure extends FeatureFailure {
UpdateMultipleSendingEmailFailure(dynamic exception) : super(exception: exception);
@override
List<Object?> get props => [exception];
}
@@ -0,0 +1,38 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:tmail_ui_user/features/sending_queue/data/exceptions/sending_queue_exceptions.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/repository/sending_queue_repository.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/state/update_multiple_sending_email_state.dart';
class UpdateMultipleSendingEmailInteractor {
final SendingQueueRepository _sendingQueueRepository;
UpdateMultipleSendingEmailInteractor(this._sendingQueueRepository);
Stream<Either<Failure, Success>> execute(
AccountId accountId,
UserName userName,
List<SendingEmail> newSendingEmails
) async* {
try {
yield Right<Failure, Success>(UpdateMultipleSendingEmailLoading());
final storedSendingEmails = await _sendingQueueRepository.updateMultipleSendingEmail(
accountId,
userName,
newSendingEmails);
if (storedSendingEmails.length == newSendingEmails.length) {
yield Right<Failure, Success>(UpdateMultipleSendingEmailAllSuccess(storedSendingEmails));
} else if (storedSendingEmails.isEmpty) {
yield Left<Failure, Success>(UpdateMultipleSendingEmailAllFailure(NotFoundSendingEmailHiveObject()));
} else {
yield Right<Failure, Success>(UpdateMultipleSendingEmailHasSomeSuccess(storedSendingEmails));
}
} catch (e) {
yield Left<Failure, Success>(UpdateMultipleSendingEmailFailure(e));
}
}
}
@@ -15,12 +15,11 @@ class UpdateSendingEmailInteractor {
Stream<Either<Failure, Success>> execute( Stream<Either<Failure, Success>> execute(
AccountId accountId, AccountId accountId,
UserName userName, UserName userName,
SendingEmail newSendingEmail, SendingEmail newSendingEmail
{bool needToReopen = false}
) async* { ) async* {
try { try {
yield Right<Failure, Success>(UpdateSendingEmailLoading()); yield Right<Failure, Success>(UpdateSendingEmailLoading());
final storedSendingEmail = await _sendingQueueRepository.updateSendingEmail(accountId, userName, newSendingEmail, needToReopen: needToReopen); final storedSendingEmail = await _sendingQueueRepository.updateSendingEmail(accountId, userName, newSendingEmail);
yield Right<Failure, Success>(UpdateSendingEmailSuccess(storedSendingEmail)); yield Right<Failure, Success>(UpdateSendingEmailSuccess(storedSendingEmail));
} catch (e) { } catch (e) {
yield Left<Failure, Success>(UpdateSendingEmailFailure(e)); yield Left<Failure, Success>(UpdateSendingEmailFailure(e));
@@ -1,6 +1,7 @@
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/delete_multiple_sending_email_interactor.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/usecases/delete_multiple_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/update_multiple_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/update_sending_email_interactor.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/usecases/update_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/presentation/sending_queue_controller.dart'; import 'package:tmail_ui_user/features/sending_queue/presentation/sending_queue_controller.dart';
@@ -15,6 +16,7 @@ class SendingQueueBindings extends Bindings {
Get.put(SendingQueueController( Get.put(SendingQueueController(
Get.find<DeleteMultipleSendingEmailInteractor>(), Get.find<DeleteMultipleSendingEmailInteractor>(),
Get.find<UpdateSendingEmailInteractor>(), Get.find<UpdateSendingEmailInteractor>(),
Get.find<UpdateMultipleSendingEmailInteractor>(),
)); ));
} }
} }
@@ -7,7 +7,6 @@ import 'package:tmail_ui_user/features/sending_queue/data/repository/sending_que
import 'package:tmail_ui_user/features/sending_queue/domain/repository/sending_queue_repository.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/repository/sending_queue_repository.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/delete_multiple_sending_email_interactor.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/usecases/delete_multiple_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/delete_sending_email_interactor.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/usecases/delete_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/delete_single_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/get_all_sending_email_interactor.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/usecases/get_all_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/offline_mode/manager/detailed_email_cache_manager.dart'; import 'package:tmail_ui_user/features/offline_mode/manager/detailed_email_cache_manager.dart';
import 'package:tmail_ui_user/features/offline_mode/manager/detailed_email_cache_worker_queue.dart'; import 'package:tmail_ui_user/features/offline_mode/manager/detailed_email_cache_worker_queue.dart';
@@ -15,6 +14,7 @@ import 'package:tmail_ui_user/features/offline_mode/manager/opened_email_cache_m
import 'package:tmail_ui_user/features/offline_mode/manager/opened_email_cache_worker_queue.dart'; import 'package:tmail_ui_user/features/offline_mode/manager/opened_email_cache_worker_queue.dart';
import 'package:tmail_ui_user/features/offline_mode/manager/sending_email_cache_manager.dart'; import 'package:tmail_ui_user/features/offline_mode/manager/sending_email_cache_manager.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/store_sending_email_interactor.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/usecases/store_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/update_multiple_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/update_sending_email_interactor.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/usecases/update_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/thread/data/local/email_cache_manager.dart'; import 'package:tmail_ui_user/features/thread/data/local/email_cache_manager.dart';
import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart'; import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart';
@@ -41,10 +41,10 @@ class SendingQueueInteractorBindings extends InteractorsBindings {
void bindingsInteractor() { void bindingsInteractor() {
Get.lazyPut(() => StoreSendingEmailInteractor(Get.find<SendingQueueRepository>())); Get.lazyPut(() => StoreSendingEmailInteractor(Get.find<SendingQueueRepository>()));
Get.lazyPut(() => GetAllSendingEmailInteractor(Get.find<SendingQueueRepository>())); Get.lazyPut(() => GetAllSendingEmailInteractor(Get.find<SendingQueueRepository>()));
Get.lazyPut(() => DeleteSingleSendingEmailInteractor(Get.find<SendingQueueRepository>())); Get.lazyPut(() => DeleteMultipleSendingEmailInteractor(Get.find<SendingQueueRepository>()));
Get.lazyPut(() => DeleteMultipleSendingEmailInteractor(Get.find<DeleteSingleSendingEmailInteractor>()));
Get.lazyPut(() => DeleteSendingEmailInteractor(Get.find<SendingQueueRepository>())); Get.lazyPut(() => DeleteSendingEmailInteractor(Get.find<SendingQueueRepository>()));
Get.lazyPut(() => UpdateSendingEmailInteractor(Get.find<SendingQueueRepository>())); Get.lazyPut(() => UpdateSendingEmailInteractor(Get.find<SendingQueueRepository>()));
Get.lazyPut(() => UpdateMultipleSendingEmailInteractor(Get.find<SendingQueueRepository>()));
} }
@override @override
@@ -1,4 +1,5 @@
import 'package:tmail_ui_user/features/offline_mode/model/sending_state.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/extensions/sending_email_extension.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/extensions/sending_email_extension.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
@@ -16,4 +17,8 @@ extension ListSendingEmailExtension on List<SendingEmail> {
bool isAllUnSelected() => every((sendingEmail) => !sendingEmail.isSelected); bool isAllUnSelected() => every((sendingEmail) => !sendingEmail.isSelected);
List<SendingEmail> listSelected() => where((sendingEmail) => sendingEmail.isSelected).toList(); List<SendingEmail> listSelected() => where((sendingEmail) => sendingEmail.isSelected).toList();
bool isAllSendingStateError() => every((sendingEmail) => sendingEmail.isError);
List<SendingEmail> toSendingStateWaiting() => map((sendingEmail) => sendingEmail.updatingSendingState(SendingState.waiting)).toList();
} }
@@ -7,6 +7,7 @@ import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
enum SendingEmailActionType { enum SendingEmailActionType {
create, create,
edit, edit,
resend,
delete; delete;
String getButtonTitle(BuildContext context) { String getButtonTitle(BuildContext context) {
@@ -17,6 +18,8 @@ enum SendingEmailActionType {
return AppLocalizations.of(context).edit; return AppLocalizations.of(context).edit;
case SendingEmailActionType.create: case SendingEmailActionType.create:
return ''; return '';
case SendingEmailActionType.resend:
return AppLocalizations.of(context).resend;
} }
} }
@@ -28,6 +31,8 @@ enum SendingEmailActionType {
return 'button_edit_sending_email'; return 'button_edit_sending_email';
case SendingEmailActionType.create: case SendingEmailActionType.create:
return ''; return '';
case SendingEmailActionType.resend:
return 'button_resend_sending_email';
} }
} }
@@ -36,6 +41,7 @@ enum SendingEmailActionType {
case SendingEmailActionType.delete: case SendingEmailActionType.delete:
return AppColor.colorDeletePermanentlyButton.withOpacity(buttonState.opacity); return AppColor.colorDeletePermanentlyButton.withOpacity(buttonState.opacity);
case SendingEmailActionType.edit: case SendingEmailActionType.edit:
case SendingEmailActionType.resend:
return AppColor.primaryColor.withOpacity(buttonState.opacity); return AppColor.primaryColor.withOpacity(buttonState.opacity);
case SendingEmailActionType.create: case SendingEmailActionType.create:
return Colors.transparent.withOpacity(buttonState.opacity); return Colors.transparent.withOpacity(buttonState.opacity);
@@ -47,6 +53,7 @@ enum SendingEmailActionType {
case SendingEmailActionType.delete: case SendingEmailActionType.delete:
return AppColor.colorDeletePermanentlyButton.withOpacity(buttonState.opacity); return AppColor.colorDeletePermanentlyButton.withOpacity(buttonState.opacity);
case SendingEmailActionType.edit: case SendingEmailActionType.edit:
case SendingEmailActionType.resend:
return AppColor.primaryColor.withOpacity(buttonState.opacity); return AppColor.primaryColor.withOpacity(buttonState.opacity);
case SendingEmailActionType.create: case SendingEmailActionType.create:
return Colors.transparent.withOpacity(buttonState.opacity); return Colors.transparent.withOpacity(buttonState.opacity);
@@ -1,8 +1,8 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/utils/app_logger.dart'; import 'package:core/utils/app_logger.dart';
import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart'; import 'package:core/presentation/state/success.dart';
import 'package:core/presentation/utils/app_toast.dart'; import 'package:core/presentation/utils/app_toast.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -17,9 +17,14 @@ import 'package:tmail_ui_user/features/caching/utils/cache_utils.dart';
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
import 'package:tmail_ui_user/features/network_status_handle/presentation/network_connnection_controller.dart'; import 'package:tmail_ui_user/features/network_status_handle/presentation/network_connnection_controller.dart';
import 'package:tmail_ui_user/features/offline_mode/manager/sending_email_cache_manager.dart';
import 'package:tmail_ui_user/features/offline_mode/model/sending_state.dart'; import 'package:tmail_ui_user/features/offline_mode/model/sending_state.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/extensions/list_sending_email_extension.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/extensions/sending_email_extension.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/state/update_multiple_sending_email_state.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/state/update_sending_email_state.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/state/update_sending_email_state.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/update_multiple_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/update_sending_email_interactor.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/usecases/update_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/presentation/utils/sending_queue_isolate_manager.dart'; import 'package:tmail_ui_user/features/sending_queue/presentation/utils/sending_queue_isolate_manager.dart';
import 'package:tmail_ui_user/features/offline_mode/controller/work_scheduler_controller.dart'; import 'package:tmail_ui_user/features/offline_mode/controller/work_scheduler_controller.dart';
@@ -34,10 +39,12 @@ class SendingQueueController extends BaseController with MessageDialogActionMixi
final DeleteMultipleSendingEmailInteractor _deleteMultipleSendingEmailInteractor; final DeleteMultipleSendingEmailInteractor _deleteMultipleSendingEmailInteractor;
final UpdateSendingEmailInteractor _updateSendingEmailInteractor; final UpdateSendingEmailInteractor _updateSendingEmailInteractor;
final UpdateMultipleSendingEmailInteractor _updateMultipleSendingEmailInteractor;
final dashboardController = getBinding<MailboxDashBoardController>(); final dashboardController = getBinding<MailboxDashBoardController>();
final _networkConnectionController = getBinding<NetworkConnectionController>(); final _networkConnectionController = getBinding<NetworkConnectionController>();
final _sendingQueueIsolateManager = getBinding<SendingQueueIsolateManager>(); final _sendingQueueIsolateManager = getBinding<SendingQueueIsolateManager>();
final _sendingEmailCacheManager = getBinding<SendingEmailCacheManager>();
final _imagePaths = getBinding<ImagePaths>(); final _imagePaths = getBinding<ImagePaths>();
final _appToast = getBinding<AppToast>(); final _appToast = getBinding<AppToast>();
@@ -48,6 +55,7 @@ class SendingQueueController extends BaseController with MessageDialogActionMixi
SendingQueueController( SendingQueueController(
this._deleteMultipleSendingEmailInteractor, this._deleteMultipleSendingEmailInteractor,
this._updateSendingEmailInteractor, this._updateSendingEmailInteractor,
this._updateMultipleSendingEmailInteractor,
); );
@override @override
@@ -61,7 +69,7 @@ class SendingQueueController extends BaseController with MessageDialogActionMixi
); );
} }
void _handleSendingQueueEvent(Object? event) { void _handleSendingQueueEvent(Object? event) async {
log('SendingQueueController::_handleSendingQueueEvent():event: $event'); log('SendingQueueController::_handleSendingQueueEvent():event: $event');
try { try {
if (event is String) { if (event is String) {
@@ -69,16 +77,20 @@ class SendingQueueController extends BaseController with MessageDialogActionMixi
final sendingId = tupleKey.parts[0]; final sendingId = tupleKey.parts[0];
final sendingState = SendingState.values.firstWhereOrNull((state) => state.name == tupleKey.parts[1]); final sendingState = SendingState.values.firstWhereOrNull((state) => state.name == tupleKey.parts[1]);
log('SendingQueueController::_handleSendingQueueEvent():sendingId: $sendingId | sendingState: $sendingState'); log('SendingQueueController::_handleSendingQueueEvent():sendingId: $sendingId | sendingState: $sendingState');
if (sendingState != null) { if (sendingState != null) {
await _sendingEmailCacheManager?.closeSendingEmailHiveCacheBox();
switch(sendingState) { switch(sendingState) {
case SendingState.waiting: case SendingState.waiting:
_handleSendingStateRunningEvent(sendingId); _updatingSendingStateToRunningAction(sendingId);
break; break;
case SendingState.running: case SendingState.running:
case SendingState.success: case SendingState.success:
refreshSendingQueue();
break;
case SendingState.error: case SendingState.error:
refreshSendingQueue(needToReopen: true); await WorkSchedulerController().cancelByUniqueId(sendingId);
_updatingSendingStateToErrorAction(sendingId);
break; break;
} }
} }
@@ -88,11 +100,21 @@ class SendingQueueController extends BaseController with MessageDialogActionMixi
} }
} }
void _handleSendingStateRunningEvent(String sendingId) { void _updatingSendingStateToRunningAction(String sendingId) {
log('SendingQueueController::_handleSendingStateRunningEvent():sendingId: $sendingId'); log('SendingQueueController::_updatingSendingStateToRunningAction():sendingId: $sendingId');
final matchedSendingEmail = dashboardController!.listSendingEmails.firstWhereOrNull((sendingEmail) => sendingEmail.sendingId == sendingId); final matchedSendingEmail = dashboardController!.listSendingEmails.firstWhereOrNull((sendingEmail) => sendingEmail.sendingId == sendingId);
if (matchedSendingEmail != null) { if (matchedSendingEmail != null) {
_updateSendingEmailAction(matchedSendingEmail); final newSendingEmail = matchedSendingEmail.updatingSendingState(SendingState.running);
_updateSendingEmailAction(newSendingEmail);
}
}
void _updatingSendingStateToErrorAction(String sendingId) {
log('SendingQueueController::_updatingSendingStateToErrorAction():sendingId: $sendingId');
final matchedSendingEmail = dashboardController!.listSendingEmails.firstWhereOrNull((sendingEmail) => sendingEmail.sendingId == sendingId);
if (matchedSendingEmail != null) {
final newSendingEmail = matchedSendingEmail.updatingSendingState(SendingState.error);
_updateSendingEmailAction(newSendingEmail);
} }
} }
@@ -118,8 +140,8 @@ class SendingQueueController extends BaseController with MessageDialogActionMixi
bool get isConnectedNetwork => _networkConnectionController?.isNetworkConnectionAvailable() == true; bool get isConnectedNetwork => _networkConnectionController?.isNetworkConnectionAvailable() == true;
void refreshSendingQueue({bool needToReopen = false}) { void refreshSendingQueue() {
dashboardController!.getAllSendingEmails(needToReopen: needToReopen); dashboardController!.getAllSendingEmails();
} }
void openMailboxMenu() { void openMailboxMenu() {
@@ -148,6 +170,9 @@ class SendingQueueController extends BaseController with MessageDialogActionMixi
break; break;
case SendingEmailActionType.create: case SendingEmailActionType.create:
break; break;
case SendingEmailActionType.resend:
_resendSendingEmailAction(listSendingEmails);
break;
} }
} }
@@ -185,32 +210,31 @@ class SendingQueueController extends BaseController with MessageDialogActionMixi
} }
void _handleDeleteSendingEmail(List<SendingEmail> listSendingEmails) async { void _handleDeleteSendingEmail(List<SendingEmail> listSendingEmails) async {
disableSelectionMode();
final accountId = dashboardController!.accountId.value; final accountId = dashboardController!.accountId.value;
final session = dashboardController!.sessionCurrent; final session = dashboardController!.sessionCurrent;
if (accountId != null && session != null) { if (accountId != null && session != null) {
final sendingIds = listSendingEmails.map((sendingEmail) => sendingEmail.sendingId).toSet().toList(); consumeState(
_deleteMultipleSendingEmailInteractor.execute(
await Future.wait( accountId,
sendingIds.map((sendingId) => WorkSchedulerController().cancelByUniqueId(sendingId)), session.username,
eagerError: true listSendingEmails.sendingIds
)
); );
consumeState(_deleteMultipleSendingEmailInteractor.execute(accountId, session.username, sendingIds));
} }
} }
void _handleDeleteSendingEmailSuccess() { void _handleDeleteSendingEmailSuccess(DeleteMultipleSendingEmailSuccess success) async {
if (currentContext != null && currentOverlayContext != null) { await Future.wait(success.sendingIds.map(WorkSchedulerController().cancelByUniqueId));
selectionState.value = SelectMode.INACTIVE;
if (currentContext != null && currentOverlayContext != null) {
_appToast!.showToastSuccessMessage( _appToast!.showToastSuccessMessage(
currentOverlayContext!, currentOverlayContext!,
AppLocalizations.of(currentContext!).messageHaveBeenDeletedSuccessfully AppLocalizations.of(currentContext!).messageHaveBeenDeletedSuccessfully);
);
refreshSendingQueue();
} }
refreshSendingQueue();
} }
void _editSendingEmailAction(SendingEmail sendingEmail) { void _editSendingEmailAction(SendingEmail sendingEmail) {
@@ -227,10 +251,6 @@ class SendingQueueController extends BaseController with MessageDialogActionMixi
dashboardController?.goToComposer(arguments); dashboardController?.goToComposer(arguments);
} }
void _handleDeleteSendingEmailFailure() {
selectionState.value = SelectMode.INACTIVE;
}
void _updateSendingEmailAction(SendingEmail newSendingEmail) { void _updateSendingEmailAction(SendingEmail newSendingEmail) {
final accountId = dashboardController!.accountId.value; final accountId = dashboardController!.accountId.value;
final session = dashboardController!.sessionCurrent; final session = dashboardController!.sessionCurrent;
@@ -238,29 +258,62 @@ class SendingQueueController extends BaseController with MessageDialogActionMixi
consumeState(_updateSendingEmailInteractor.execute( consumeState(_updateSendingEmailInteractor.execute(
accountId, accountId,
session.username, session.username,
newSendingEmail, newSendingEmail
needToReopen: true
)); ));
} }
} }
void _resendSendingEmailAction(List<SendingEmail> listSendingEmails) async {
disableSelectionMode();
final accountId = dashboardController!.accountId.value;
final session = dashboardController!.sessionCurrent;
if (accountId != null && session != null) {
consumeState(
_updateMultipleSendingEmailInteractor.execute(
accountId,
session.username,
listSendingEmails.toSendingStateWaiting()
)
);
}
}
void _handleResendSendingEmailSuccess(List<SendingEmail> newListSendingEmails) async {
await Future.forEach<SendingEmail>(newListSendingEmails, (sendingEmail) async {
await WorkSchedulerController().cancelByUniqueId(sendingEmail.sendingId);
dashboardController!.addSendingEmailToSendingQueue(sendingEmail);
});
if (currentContext != null && currentOverlayContext != null) {
_appToast!.showToastSuccessMessage(
currentOverlayContext!,
AppLocalizations.of(currentContext!).messagesHaveBeenResent);
}
refreshSendingQueue();
}
@override @override
void handleSuccessViewState(Success success) { void handleSuccessViewState(Success success) {
super.handleSuccessViewState(success); super.handleSuccessViewState(success);
if (success is DeleteMultipleSendingEmailAllSuccess || if (success is DeleteMultipleSendingEmailSuccess) {
success is DeleteMultipleSendingEmailHasSomeSuccess) { _handleDeleteSendingEmailSuccess(success);
_handleDeleteSendingEmailSuccess();
} else if (success is UpdateSendingEmailSuccess) { } else if (success is UpdateSendingEmailSuccess) {
refreshSendingQueue(needToReopen: true); refreshSendingQueue();
} else if (success is UpdateMultipleSendingEmailAllSuccess) {
_handleResendSendingEmailSuccess(success.newSendingEmails);
} else if (success is UpdateMultipleSendingEmailHasSomeSuccess) {
_handleResendSendingEmailSuccess(success.newSendingEmails);
} }
} }
@override @override
void handleFailureViewState(Failure failure) { void handleFailureViewState(Failure failure) {
super.handleFailureViewState(failure); super.handleFailureViewState(failure);
if (failure is DeleteMultipleSendingEmailAllFailure || if (failure is UpdateSendingEmailFailure) {
failure is DeleteMultipleSendingEmailFailure) { refreshSendingQueue();
_handleDeleteSendingEmailFailure();
} }
} }
@@ -64,7 +64,7 @@ class SendingQueueView extends GetWidget<SendingQueueController> with AppLoaderM
if (controller.selectionState.value == SelectMode.INACTIVE) { if (controller.selectionState.value == SelectMode.INACTIVE) {
return RefreshIndicator( return RefreshIndicator(
color: AppColor.primaryColor, color: AppColor.primaryColor,
onRefresh: () async => controller.refreshSendingQueue(needToReopen: true), onRefresh: () async => controller.refreshSendingQueue(),
child: _buildListViewItemSendingEmails()); child: _buildListViewItemSendingEmails());
} else { } else {
return _buildListViewItemSendingEmails(); return _buildListViewItemSendingEmails();
@@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/state/button_state.dart'; import 'package:tmail_ui_user/features/base/state/button_state.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
import 'package:tmail_ui_user/features/sending_queue/presentation/extensions/list_sending_email_extension.dart';
import 'package:tmail_ui_user/features/sending_queue/presentation/model/sending_email_action_type.dart'; import 'package:tmail_ui_user/features/sending_queue/presentation/model/sending_email_action_type.dart';
typedef OnHandleSendingEmailActionType = void Function(SendingEmailActionType, List<SendingEmail>); typedef OnHandleSendingEmailActionType = void Function(SendingEmailActionType, List<SendingEmail>);
@@ -53,6 +54,19 @@ class BottomBarSendingQueueWidget extends StatelessWidget {
}) })
..text(SendingEmailActionType.edit.getButtonTitle(context), isVertical: responsiveUtils.isPortraitMobile(context)) ..text(SendingEmailActionType.edit.getButtonTitle(context), isVertical: responsiveUtils.isPortraitMobile(context))
).build()), ).build()),
Expanded(child: (ButtonBuilder(imagePaths.icRefresh)
..key(Key(SendingEmailActionType.resend.getButtonKey()))
..iconColor(SendingEmailActionType.resend.getButtonIconColor(_isCanResend ? ButtonState.enabled : ButtonState.disabled))
..padding(const EdgeInsets.all(8))
..radiusSplash(8)
..textStyle(TextStyle(fontSize: 12, color: SendingEmailActionType.resend.getButtonTitleColor(_isCanResend ? ButtonState.enabled : ButtonState.disabled)))
..onPressActionClick(() {
if (_isCanResend) {
onHandleSendingEmailActionType?.call(SendingEmailActionType.resend, listSendingEmailSelected);
}
})
..text(SendingEmailActionType.resend.getButtonTitle(context), isVertical: responsiveUtils.isPortraitMobile(context))
).build()),
Expanded(child: (ButtonBuilder(imagePaths.icDeleteComposer) Expanded(child: (ButtonBuilder(imagePaths.icDeleteComposer)
..key(Key(SendingEmailActionType.delete.getButtonKey())) ..key(Key(SendingEmailActionType.delete.getButtonKey()))
..iconColor(SendingEmailActionType.delete.getButtonIconColor(ButtonState.enabled)) ..iconColor(SendingEmailActionType.delete.getButtonIconColor(ButtonState.enabled))
@@ -70,4 +84,6 @@ class BottomBarSendingQueueWidget extends StatelessWidget {
bool get _isEditable => !isConnectedNetwork && bool get _isEditable => !isConnectedNetwork &&
listSendingEmailSelected.length == 1 && listSendingEmailSelected.length == 1 &&
listSendingEmailSelected.first.isWaiting; listSendingEmailSelected.first.isWaiting;
bool get _isCanResend => listSendingEmailSelected.isAllSendingStateError();
} }
+13 -1
View File
@@ -1,5 +1,5 @@
{ {
"@@last_modified": "2023-06-09T10:30:29.843203", "@@last_modified": "2023-06-09T22:51:52.101985",
"initializing_data": "Initializing data...", "initializing_data": "Initializing data...",
"@initializing_data": { "@initializing_data": {
"type": "text", "type": "text",
@@ -2905,5 +2905,17 @@
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
},
"resend": "Resend",
"@resend": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"messagesHaveBeenResent": "Messages have been resent",
"@messagesHaveBeenResent": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
} }
} }
@@ -2995,4 +2995,16 @@ class AppLocalizations {
name: 'connectedToTheInternet' name: 'connectedToTheInternet'
); );
} }
String get resend {
return Intl.message(
'Resend',
name: 'resend');
}
String get messagesHaveBeenResent {
return Intl.message(
'Messages have been resent',
name: 'messagesHaveBeenResent');
}
} }