TF-1317 Show push notification on background or terminated app
This commit is contained in:
@@ -15,10 +15,12 @@ class UpdateAuthenticationAccountInteractor {
|
||||
try{
|
||||
yield Right(UpdateAuthenticationAccountLoading());
|
||||
final currentAccount = await _accountRepository.getCurrentAccount();
|
||||
await _accountRepository.setCurrentAccount(currentAccount.fromAccountId(
|
||||
accountId: accountId,
|
||||
apiUrl: apiUrl
|
||||
));
|
||||
await _accountRepository.setCurrentAccount(
|
||||
currentAccount.fromAccountId(
|
||||
accountId: accountId,
|
||||
apiUrl: apiUrl
|
||||
)
|
||||
);
|
||||
yield Right(UpdateAuthenticationAccountSuccess());
|
||||
} catch(e) {
|
||||
yield Left(UpdateAuthenticationAccountFailure(e));
|
||||
|
||||
+57
-20
@@ -1,4 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
@@ -10,7 +11,6 @@ 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';
|
||||
import 'package:jmap_dart_client/jmap/core/capability/mail_capability.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
@@ -101,6 +101,7 @@ import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_utils.dart';
|
||||
import 'package:tmail_ui_user/main/routes/router_arguments.dart';
|
||||
import 'package:tmail_ui_user/main/utils/email_receive_manager.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
|
||||
|
||||
class MailboxDashBoardController extends ReloadableController {
|
||||
|
||||
@@ -387,16 +388,7 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
_notificationManager.activatedNotificationClickedOnTerminate = true;
|
||||
final notificationResponse = await _notificationManager.getCurrentNotificationResponse();
|
||||
log('MailboxDashBoardController::_handleClickLocalNotificationOnTerminated():payload: ${notificationResponse?.payload}');
|
||||
final emailIdFromPayload = notificationResponse?.payload;
|
||||
final currentAccountId = accountId.value;
|
||||
if (emailIdFromPayload?.isNotEmpty == true && currentAccountId != null) {
|
||||
_getPresentationEmailFromEmailIdAction(
|
||||
EmailId(Id(emailIdFromPayload!)),
|
||||
currentAccountId
|
||||
);
|
||||
} else {
|
||||
dispatchRoute(DashboardRoutes.thread);
|
||||
}
|
||||
_handleMessageFromNotification(notificationResponse?.payload, onForeground: false);
|
||||
}
|
||||
|
||||
void _getUserProfile() async {
|
||||
@@ -1428,21 +1420,62 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
void _handleClickLocalNotificationOnForeground(NotificationResponse? response) {
|
||||
_notificationManager.activatedNotificationClickedOnTerminate = true;
|
||||
log('MailboxDashBoardController::_handleClickLocalNotificationOnForeground():payload: ${response?.payload}');
|
||||
final emailIdFromPayload = response?.payload;
|
||||
final currentAccountId = accountId.value;
|
||||
if (emailIdFromPayload?.isNotEmpty == true && currentAccountId != null) {
|
||||
popAllRouteIfHave();
|
||||
dispatchRoute(DashboardRoutes.waiting);
|
||||
_handleMessageFromNotification(response?.payload);
|
||||
}
|
||||
|
||||
_getPresentationEmailFromEmailIdAction(
|
||||
EmailId(Id(emailIdFromPayload!)),
|
||||
currentAccountId
|
||||
);
|
||||
void _handleMessageFromNotification(String? payload, {bool onForeground = true}) {
|
||||
log('MailboxDashBoardController::_handleMessageFromNotification():payload: $payload');
|
||||
if (payload == null) {
|
||||
dispatchRoute(DashboardRoutes.thread);
|
||||
return;
|
||||
}
|
||||
|
||||
final payloadDecoded = jsonDecode(payload);
|
||||
if (payloadDecoded is Map<String, dynamic>) {
|
||||
final notificationPayload = NotificationPayload.fromJson(payloadDecoded);
|
||||
log('MailboxDashBoardController::_handleMessageFromNotification():notificationPayload: $notificationPayload');
|
||||
|
||||
if (notificationPayload.emailId != null) {
|
||||
_handleNotificationMessageFromEmailId(notificationPayload.emailId!, onForeground: onForeground);
|
||||
} else if (notificationPayload.newState != null) {
|
||||
_handleNotificationMessageFromNewState(notificationPayload.newState!, onForeground: onForeground);
|
||||
} else {
|
||||
dispatchRoute(DashboardRoutes.thread);
|
||||
}
|
||||
} else {
|
||||
dispatchRoute(DashboardRoutes.thread);
|
||||
}
|
||||
}
|
||||
|
||||
void _handleNotificationMessageFromNewState(jmap.State newState, {bool onForeground = true}) {
|
||||
if (onForeground) {
|
||||
_openInboxMailbox();
|
||||
}
|
||||
}
|
||||
|
||||
void _handleNotificationMessageFromEmailId(EmailId emailId, {bool onForeground = true}) {
|
||||
final currentAccountId = accountId.value;
|
||||
if (currentAccountId != null) {
|
||||
if (onForeground) {
|
||||
_showWaitingView();
|
||||
}
|
||||
_getPresentationEmailFromEmailIdAction(emailId, currentAccountId);
|
||||
} else {
|
||||
dispatchRoute(DashboardRoutes.thread);
|
||||
}
|
||||
}
|
||||
|
||||
void _showWaitingView() {
|
||||
popAllRouteIfHave();
|
||||
dispatchRoute( DashboardRoutes.waiting);
|
||||
}
|
||||
|
||||
void _openInboxMailbox() {
|
||||
popAllRouteIfHave();
|
||||
dispatchMailboxUIAction(SelectMailboxDefaultAction());
|
||||
dispatchRoute(DashboardRoutes.thread);
|
||||
}
|
||||
|
||||
void _getPresentationEmailFromEmailIdAction(EmailId emailId, AccountId accountId) {
|
||||
log('MailboxDashBoardController:_getPresentationEmailFromEmailIdAction:emailId: $emailId');
|
||||
consumeState(_getEmailByIdInteractor.execute(
|
||||
@@ -1482,6 +1515,10 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
}
|
||||
}
|
||||
|
||||
void updateEmailList(List<PresentationEmail> newEmailList) {
|
||||
emailsInCurrentMailbox.value = newEmailList;
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
_emailReceiveManager.closeEmailReceiveManagerStream();
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
@@ -6,6 +8,7 @@ import 'package:core/utils/build_utils.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
|
||||
import 'package:model/email/presentation_email.dart';
|
||||
import 'package:model/notification/notification_payload.dart';
|
||||
import 'package:tmail_ui_user/features/base/action/ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_stored_state_email_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_stored_email_state_interactor.dart';
|
||||
@@ -20,8 +23,11 @@ import 'package:tmail_ui_user/features/push_notification/domain/usecases/store_e
|
||||
import 'package:tmail_ui_user/features/push_notification/domain/usecases/store_email_state_to_refresh_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/presentation/action/fcm_action.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/presentation/listener/change_listener.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_manager.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/presentation/utils/fcm_utils.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
class EmailChangeListener extends ChangeListener {
|
||||
@@ -78,9 +84,23 @@ class EmailChangeListener extends ChangeListener {
|
||||
_newState = newState;
|
||||
_accountId = accountId;
|
||||
log('EmailChangeListener::_pushNotificationAction():newState: $newState');
|
||||
_getStoredEmailDeliveryState();
|
||||
|
||||
if (BuildUtils.isWeb) {
|
||||
_storeEmailDeliveryStateAction(_newState!);
|
||||
} else {
|
||||
if (Platform.isAndroid) {
|
||||
_getStoredEmailDeliveryState();
|
||||
} else if (Platform.isIOS) {
|
||||
_storeEmailDeliveryStateAction(_newState!);
|
||||
_showLocalNotificationForIOS(_newState!, _accountId!);
|
||||
} else {
|
||||
logError('EmailChangeListener::_pushNotificationAction(): NOT SUPPORTED PLATFORM');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _getStoredEmailDeliveryState() {
|
||||
if (_getStoredEmailDeliveryStateInteractor != null) {
|
||||
consumeState(_getStoredEmailDeliveryStateInteractor!.execute());
|
||||
@@ -112,13 +132,30 @@ class EmailChangeListener extends ChangeListener {
|
||||
}
|
||||
}
|
||||
|
||||
void _showLocalNotification(PresentationEmail presentationEmail, jmap.State newState) {
|
||||
void _showLocalNotification(PresentationEmail presentationEmail) {
|
||||
final notificationPayload = NotificationPayload(emailId: presentationEmail.id);
|
||||
log('EmailChangeListener::_showLocalNotification():notificationPayload: $notificationPayload');
|
||||
LocalNotificationManager.instance.showPushNotification(
|
||||
id: presentationEmail.id.id.value,
|
||||
title: presentationEmail.subject ?? '',
|
||||
message: presentationEmail.preview,
|
||||
emailAddress: presentationEmail.from?.first,
|
||||
payload: presentationEmail.id.id.value,
|
||||
payload: notificationPayload.encodeToString,
|
||||
);
|
||||
}
|
||||
|
||||
void _showLocalNotificationForIOS(jmap.State newState, AccountId accountId) {
|
||||
final notificationPayload = NotificationPayload(newState: newState);
|
||||
log('EmailChangeListener::_showLocalNotificationForIOS():notificationPayload: $notificationPayload');
|
||||
LocalNotificationManager.instance.showPushNotification(
|
||||
id: '${FcmUtils.instance.platformOS}-${accountId.id.value}',
|
||||
title: currentContext != null
|
||||
? AppLocalizations.of(currentContext!).appTitlePushNotification
|
||||
: LocalNotificationConfig.notificationTitle,
|
||||
message: currentContext != null
|
||||
? AppLocalizations.of(currentContext!).youHaveNewMessages
|
||||
: LocalNotificationConfig.notificationMessage,
|
||||
payload: notificationPayload.encodeToString,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -144,19 +181,21 @@ class EmailChangeListener extends ChangeListener {
|
||||
if (_newState != null) {
|
||||
_storeEmailDeliveryStateAction(_newState!);
|
||||
|
||||
if (!BuildUtils.isWeb) {
|
||||
for (var presentationEmail in success.emailList) {
|
||||
_showLocalNotification(presentationEmail, _newState!);
|
||||
}
|
||||
if (!BuildUtils.isWeb && Platform.isAndroid) {
|
||||
_handleLocalPushNotification(success.emailList);
|
||||
}
|
||||
}
|
||||
|
||||
if (!BuildUtils.isWeb) {
|
||||
LocalNotificationManager.instance.groupPushNotification();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _handleLocalPushNotification(List<PresentationEmail> emailList) {
|
||||
for (var presentationEmail in emailList) {
|
||||
_showLocalNotification(presentationEmail);
|
||||
}
|
||||
|
||||
LocalNotificationManager.instance.groupPushNotification();
|
||||
}
|
||||
|
||||
void _handleStoreEmailStateToRefreshAction(jmap.State newState) {
|
||||
log('EmailChangeListener::_handleStoreEmailStateToRefreshAction():newState: $newState');
|
||||
if (_storeEmailStateToRefreshInteractor != null) {
|
||||
|
||||
+3
@@ -7,6 +7,8 @@ class LocalNotificationConfig {
|
||||
static const _channelId = 'team_mail_notification_channel_id';
|
||||
static const _channelName = 'Team Mail notifications';
|
||||
static const _channelDescription = 'Team Mail notifications';
|
||||
static const notificationTitle = 'Team Mail';
|
||||
static const notificationMessage = 'You have new messages';
|
||||
|
||||
static const iosInitializationSettings = DarwinInitializationSettings();
|
||||
|
||||
@@ -53,6 +55,7 @@ class LocalNotificationConfig {
|
||||
presentSound: true,
|
||||
presentAlert: true,
|
||||
presentBadge: true,
|
||||
threadIdentifier: _channelId
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
+5
-1
@@ -8,6 +8,8 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:model/extensions/email_address_extension.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/presentation/notification/local_notification_config.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
class LocalNotificationManager {
|
||||
|
||||
@@ -159,7 +161,9 @@ class LocalNotificationManager {
|
||||
if (activeNotifications != null && activeNotifications.isNotEmpty) {
|
||||
final inboxStyleInformation = InboxStyleInformation(
|
||||
[''],
|
||||
summaryText: '${activeNotifications.length - 1} new emails'.addBlockTag('b'),
|
||||
summaryText: currentContext != null
|
||||
? AppLocalizations.of(currentContext!).totalNewMessagePushNotification(activeNotifications.length - 1).addBlockTag('b')
|
||||
: '${activeNotifications.length - 1} new emails'.addBlockTag('b'),
|
||||
htmlFormatSummaryText: true,
|
||||
);
|
||||
|
||||
|
||||
@@ -82,20 +82,20 @@ class FcmUtils {
|
||||
String get platformOS {
|
||||
var platformName = '';
|
||||
if (BuildUtils.isWeb) {
|
||||
platformName = "Web";
|
||||
platformName = 'Web';
|
||||
} else {
|
||||
if (Platform.isAndroid) {
|
||||
platformName = "Android";
|
||||
platformName = 'Android';
|
||||
} else if (Platform.isIOS) {
|
||||
platformName = "IOS";
|
||||
platformName = 'IOS';
|
||||
} else if (Platform.isFuchsia) {
|
||||
platformName = "Fuchsia";
|
||||
platformName = 'Fuchsia';
|
||||
} else if (Platform.isLinux) {
|
||||
platformName = "Linux";
|
||||
platformName = 'Linux';
|
||||
} else if (Platform.isMacOS) {
|
||||
platformName = "MacOS";
|
||||
platformName = 'MacOS';
|
||||
} else if (Platform.isWindows) {
|
||||
platformName = "Windows";
|
||||
platformName = 'Windows';
|
||||
}
|
||||
}
|
||||
log('FcmUtils::platformOS():$platformName');
|
||||
|
||||
@@ -117,8 +117,6 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
|
||||
SearchQuery? get searchQuery => searchController.searchEmailFilter.value.text;
|
||||
|
||||
RxList<PresentationEmail> get emailList => mailboxDashBoardController.emailsInCurrentMailbox;
|
||||
|
||||
ThreadController(
|
||||
this._getEmailsInMailboxInteractor,
|
||||
this._refreshChangesEmailsInMailboxInteractor,
|
||||
@@ -154,7 +152,7 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
newState.fold(
|
||||
(failure) {
|
||||
if (failure is SearchEmailFailure) {
|
||||
emailList.clear();
|
||||
mailboxDashBoardController.emailsInCurrentMailbox.clear();
|
||||
} else if (failure is SearchMoreEmailFailure || failure is LoadMoreEmailsFailure) {
|
||||
_isLoadingMore = false;
|
||||
} else if (failure is GetEmailByIdFailure) {
|
||||
@@ -356,7 +354,7 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
|
||||
void _resetToOriginalValue() {
|
||||
dispatchState(Right(LoadingState()));
|
||||
emailList.clear();
|
||||
mailboxDashBoardController.emailsInCurrentMailbox.clear();
|
||||
canLoadMore = true;
|
||||
_isLoadingMore = false;
|
||||
cancelSelectEmail();
|
||||
@@ -365,13 +363,13 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
void _getAllEmailSuccess(GetAllEmailSuccess success) {
|
||||
_currentEmailState = success.currentEmailState;
|
||||
log('ThreadController::_getAllEmailSuccess():_currentEmailState: $_currentEmailState');
|
||||
emailList.value = success.emailList.syncPresentationEmail(
|
||||
final newListEmail = success.emailList.syncPresentationEmail(
|
||||
mapMailboxById: mailboxDashBoardController.mapMailboxById,
|
||||
selectedMailbox: currentMailbox,
|
||||
searchQuery: searchController.searchQuery,
|
||||
isSearchEmailRunning: searchController.isSearchEmailRunning
|
||||
);
|
||||
|
||||
mailboxDashBoardController.updateEmailList(newListEmail);
|
||||
if (listEmailController.hasClients) {
|
||||
listEmailController.animateTo(0, duration: const Duration(milliseconds: 500), curve: Curves.fastOutSlowIn);
|
||||
}
|
||||
@@ -380,17 +378,18 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
void _refreshChangesAllEmailSuccess(RefreshChangesAllEmailSuccess success) {
|
||||
_currentEmailState = success.currentEmailState;
|
||||
|
||||
final emailsBeforeChanges = emailList;
|
||||
final emailsBeforeChanges = mailboxDashBoardController.emailsInCurrentMailbox;
|
||||
final emailsAfterChanges = success.emailList;
|
||||
final newListEmail = emailsAfterChanges.combine(emailsBeforeChanges);
|
||||
emailList.value = newListEmail.syncPresentationEmail(
|
||||
final emailListSynced = newListEmail.syncPresentationEmail(
|
||||
mapMailboxById: mailboxDashBoardController.mapMailboxById,
|
||||
selectedMailbox: currentMailbox,
|
||||
searchQuery: searchController.searchQuery,
|
||||
isSearchEmailRunning: searchController.isSearchEmailRunning
|
||||
);
|
||||
mailboxDashBoardController.updateEmailList(emailListSynced);
|
||||
|
||||
if (emailList.isEmpty) {
|
||||
if (mailboxDashBoardController.emailsInCurrentMailbox.isEmpty) {
|
||||
refreshAllEmail();
|
||||
}
|
||||
}
|
||||
@@ -410,29 +409,33 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
}
|
||||
|
||||
EmailFilterCondition _getFilterCondition({bool isLoadMore = false}) {
|
||||
final lastEmail = mailboxDashBoardController.emailsInCurrentMailbox.isNotEmpty
|
||||
? mailboxDashBoardController.emailsInCurrentMailbox.last
|
||||
: null;
|
||||
final mailboxIdSelected = mailboxDashBoardController.selectedMailbox.value?.id;
|
||||
switch(mailboxDashBoardController.filterMessageOption.value) {
|
||||
case FilterMessageOption.all:
|
||||
return EmailFilterCondition(
|
||||
inMailbox: mailboxDashBoardController.selectedMailbox.value?.id,
|
||||
before: isLoadMore ? emailList.last.receivedAt : null
|
||||
inMailbox: mailboxIdSelected,
|
||||
before: isLoadMore ? lastEmail?.receivedAt : null
|
||||
);
|
||||
case FilterMessageOption.unread:
|
||||
return EmailFilterCondition(
|
||||
inMailbox: mailboxDashBoardController.selectedMailbox.value?.id,
|
||||
notKeyword: KeyWordIdentifier.emailSeen.value,
|
||||
before: isLoadMore ? emailList.last.receivedAt : null
|
||||
inMailbox: mailboxIdSelected,
|
||||
notKeyword: KeyWordIdentifier.emailSeen.value,
|
||||
before: isLoadMore ? lastEmail?.receivedAt : null
|
||||
);
|
||||
case FilterMessageOption.attachments:
|
||||
return EmailFilterCondition(
|
||||
inMailbox: mailboxDashBoardController.selectedMailbox.value?.id,
|
||||
hasAttachment: true,
|
||||
before: isLoadMore ? emailList.last.receivedAt : null
|
||||
inMailbox: mailboxIdSelected,
|
||||
hasAttachment: true,
|
||||
before: isLoadMore ? lastEmail?.receivedAt : null
|
||||
);
|
||||
case FilterMessageOption.starred:
|
||||
return EmailFilterCondition(
|
||||
inMailbox: mailboxDashBoardController.selectedMailbox.value?.id,
|
||||
hasKeyword: KeyWordIdentifier.emailFlagged.value,
|
||||
before: isLoadMore ? emailList.last.receivedAt : null
|
||||
inMailbox: mailboxIdSelected,
|
||||
hasKeyword: KeyWordIdentifier.emailFlagged.value,
|
||||
before: isLoadMore ? lastEmail?.receivedAt : null
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -443,20 +446,26 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
cancelSelectEmail();
|
||||
|
||||
if (searchController.isSearchEmailRunning) {
|
||||
final limit = emailList.isNotEmpty ? UnsignedInt(emailList.length) : ThreadConstants.defaultLimit;
|
||||
searchController.searchEmailFilter.value = _searchEmailFilter.clearBeforeDate();
|
||||
_searchEmail(limit: limit);
|
||||
_searchEmail(limit: limitEmailFetched);
|
||||
} else {
|
||||
_getAllEmail();
|
||||
}
|
||||
}
|
||||
|
||||
UnsignedInt get limitEmailFetched {
|
||||
final emailsInCurrentMailbox = mailboxDashBoardController.emailsInCurrentMailbox;
|
||||
final limit = emailsInCurrentMailbox.isNotEmpty
|
||||
? UnsignedInt(emailsInCurrentMailbox.length)
|
||||
: ThreadConstants.defaultLimit;
|
||||
return limit;
|
||||
}
|
||||
|
||||
void _refreshEmailChanges({jmap.State? currentEmailState}) {
|
||||
log('ThreadController::_refreshEmailChanges(): currentEmailState: $currentEmailState');
|
||||
if (searchController.isSearchEmailRunning) {
|
||||
final limit = emailList.isNotEmpty ? UnsignedInt(emailList.length) : ThreadConstants.defaultLimit;
|
||||
searchController.searchEmailFilter.value = _searchEmailFilter.clearBeforeDate();
|
||||
_searchEmail(limit: limit);
|
||||
_searchEmail(limit: limitEmailFetched);
|
||||
} else {
|
||||
final newEmailState = currentEmailState ?? _currentEmailState;
|
||||
log('ThreadController::_refreshEmailChanges(): newEmailState: $newEmailState');
|
||||
@@ -487,7 +496,7 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
filterOption: mailboxDashBoardController.filterMessageOption.value,
|
||||
filter: _getFilterCondition(isLoadMore: true),
|
||||
properties: ThreadConstants.propertiesDefault,
|
||||
lastEmailId: emailList.last.id)
|
||||
lastEmailId: mailboxDashBoardController.emailsInCurrentMailbox.last.id)
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -497,7 +506,9 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
}
|
||||
|
||||
bool _notDuplicatedInCurrentList(PresentationEmail email) {
|
||||
return emailList.isEmpty || !emailList.map((element) => element.id).contains(email.id);
|
||||
final emailsInCurrentMailbox = mailboxDashBoardController.emailsInCurrentMailbox;
|
||||
return emailsInCurrentMailbox.isEmpty ||
|
||||
!emailsInCurrentMailbox.map((element) => element.id).contains(email.id);
|
||||
}
|
||||
|
||||
void _loadMoreEmailsSuccess(LoadMoreEmailsSuccess success) {
|
||||
@@ -513,7 +524,7 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
isSearchEmailRunning: searchController.isSearchEmailRunning
|
||||
);
|
||||
|
||||
emailList.addAll(appendableList);
|
||||
mailboxDashBoardController.emailsInCurrentMailbox.addAll(appendableList);
|
||||
} else {
|
||||
canLoadMore = false;
|
||||
}
|
||||
@@ -527,8 +538,11 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
}
|
||||
|
||||
Tuple2<StartRangeSelection,EndRangeSelection> _getSelectionEmailsRange(PresentationEmail presentationEmailSelected) {
|
||||
final emailSelectedIndex = emailList.indexWhere((e) => e.id == presentationEmailSelected.id);
|
||||
final latestEmailSelectedOrUnselectedIndex = emailList.indexWhere((e) => e.id == latestEmailSelectedOrUnselected.value?.id);
|
||||
final emailsInCurrentMailbox = mailboxDashBoardController.emailsInCurrentMailbox;
|
||||
final emailSelectedIndex = emailsInCurrentMailbox
|
||||
.indexWhere((e) => e.id == presentationEmailSelected.id);
|
||||
final latestEmailSelectedOrUnselectedIndex = emailsInCurrentMailbox
|
||||
.indexWhere((e) => e.id == latestEmailSelectedOrUnselected.value?.id);
|
||||
if (emailSelectedIndex > latestEmailSelectedOrUnselectedIndex) {
|
||||
return Tuple2(latestEmailSelectedOrUnselectedIndex, emailSelectedIndex);
|
||||
} else {
|
||||
@@ -537,16 +551,22 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
}
|
||||
|
||||
bool _checkAllowMakeRangeEmailsSelected(Tuple2<StartRangeSelection,EndRangeSelection> selectionEmailsRange) {
|
||||
final emailsInCurrentMailbox = mailboxDashBoardController.emailsInCurrentMailbox;
|
||||
return latestEmailSelectedOrUnselected.value?.selectMode == SelectMode.ACTIVE &&
|
||||
!emailList.sublist(selectionEmailsRange.value1, selectionEmailsRange.value2).every((e) => e.selectMode == SelectMode.ACTIVE) ||
|
||||
!emailsInCurrentMailbox.sublist(selectionEmailsRange.value1, selectionEmailsRange.value2).every((e) => e.selectMode == SelectMode.ACTIVE) ||
|
||||
latestEmailSelectedOrUnselected.value?.selectMode == SelectMode.INACTIVE &&
|
||||
emailList.sublist(selectionEmailsRange.value1, selectionEmailsRange.value2).every((e) => e.selectMode == SelectMode.INACTIVE);
|
||||
emailsInCurrentMailbox.sublist(selectionEmailsRange.value1, selectionEmailsRange.value2).every((e) => e.selectMode == SelectMode.INACTIVE);
|
||||
}
|
||||
|
||||
void _applySelectModeToRangeEmails(Tuple2<StartRangeSelection,EndRangeSelection> selectionEmailsRange, SelectMode selectMode) {
|
||||
emailList.value = emailList.asMap().map((index, email) {
|
||||
return MapEntry(index, index >= selectionEmailsRange.value1 && index <= selectionEmailsRange.value2 ? email.toSelectedEmail(selectMode: selectMode) : email);
|
||||
}).values.toList();
|
||||
final newEmailList = mailboxDashBoardController.emailsInCurrentMailbox
|
||||
.asMap()
|
||||
.map((index, email) {
|
||||
return MapEntry(index, index >= selectionEmailsRange.value1 && index <= selectionEmailsRange.value2 ? email.toSelectedEmail(selectMode: selectMode) : email);
|
||||
})
|
||||
.values
|
||||
.toList();
|
||||
mailboxDashBoardController.updateEmailList(newEmailList);
|
||||
}
|
||||
|
||||
void _rangeSelectionEmailsAction(PresentationEmail presentationEmailSelected) {
|
||||
@@ -560,14 +580,19 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
}
|
||||
|
||||
void selectEmail(BuildContext context, PresentationEmail presentationEmailSelected) {
|
||||
final emailsInCurrentMailbox = mailboxDashBoardController.emailsInCurrentMailbox;
|
||||
|
||||
if (_rangeSelectionMode && latestEmailSelectedOrUnselected.value != null && latestEmailSelectedOrUnselected.value?.id != presentationEmailSelected.id) {
|
||||
_rangeSelectionEmailsAction(presentationEmailSelected);
|
||||
} else {
|
||||
emailList.value = emailList
|
||||
final newEmailList = emailsInCurrentMailbox
|
||||
.map((email) => email.id == presentationEmailSelected.id ? email.toggleSelect() : email)
|
||||
.toList();
|
||||
mailboxDashBoardController.updateEmailList(newEmailList);
|
||||
}
|
||||
latestEmailSelectedOrUnselected.value = emailList.firstWhereOrNull((e) => e.id == presentationEmailSelected.id);
|
||||
|
||||
latestEmailSelectedOrUnselected.value = emailsInCurrentMailbox
|
||||
.firstWhereOrNull((e) => e.id == presentationEmailSelected.id);
|
||||
focusNodeKeyBoard.requestFocus();
|
||||
if (_isUnSelectedAll()) {
|
||||
mailboxDashBoardController.currentSelectMode.value = SelectMode.INACTIVE;
|
||||
@@ -585,19 +610,27 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
}
|
||||
|
||||
void setSelectAllEmailAction() {
|
||||
emailList.value = emailList.map((email) => email.toSelectedEmail(selectMode: SelectMode.ACTIVE)).toList();
|
||||
final newEmailList = mailboxDashBoardController.emailsInCurrentMailbox
|
||||
.map((email) => email.toSelectedEmail(selectMode: SelectMode.ACTIVE))
|
||||
.toList();
|
||||
mailboxDashBoardController.updateEmailList(newEmailList);
|
||||
mailboxDashBoardController.currentSelectMode.value = SelectMode.ACTIVE;
|
||||
mailboxDashBoardController.listEmailSelected.value = listEmailSelected;
|
||||
}
|
||||
|
||||
List<PresentationEmail> get listEmailSelected => emailList.listEmailSelected;
|
||||
List<PresentationEmail> get listEmailSelected =>
|
||||
mailboxDashBoardController.emailsInCurrentMailbox.listEmailSelected;
|
||||
|
||||
bool _isUnSelectedAll() {
|
||||
return emailList.every((email) => email.selectMode == SelectMode.INACTIVE);
|
||||
return mailboxDashBoardController.emailsInCurrentMailbox
|
||||
.every((email) => email.selectMode == SelectMode.INACTIVE);
|
||||
}
|
||||
|
||||
void cancelSelectEmail() {
|
||||
emailList.value = emailList.map((email) => email.toSelectedEmail(selectMode: SelectMode.INACTIVE)).toList();
|
||||
final newEmailList = mailboxDashBoardController.emailsInCurrentMailbox
|
||||
.map((email) => email.toSelectedEmail(selectMode: SelectMode.INACTIVE))
|
||||
.toList();
|
||||
mailboxDashBoardController.updateEmailList(newEmailList);
|
||||
mailboxDashBoardController.currentSelectMode.value = SelectMode.INACTIVE;
|
||||
mailboxDashBoardController.listEmailSelected.clear();
|
||||
}
|
||||
@@ -673,28 +706,30 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
.map((email) => email.toSearchPresentationEmail(mailboxDashBoardController.mapMailboxById))
|
||||
.toList();
|
||||
|
||||
final emailsSearchBeforeChanges = emailList;
|
||||
final emailsSearchBeforeChanges = mailboxDashBoardController.emailsInCurrentMailbox;
|
||||
final emailsSearchAfterChanges = resultEmailSearchList;
|
||||
final newListEmailSearch = emailsSearchAfterChanges.combine(emailsSearchBeforeChanges);
|
||||
emailList.value = newListEmailSearch.syncPresentationEmail(
|
||||
final newEmailListSynced = newListEmailSearch.syncPresentationEmail(
|
||||
mapMailboxById: mailboxDashBoardController.mapMailboxById,
|
||||
selectedMailbox: currentMailbox,
|
||||
searchQuery: searchController.searchQuery,
|
||||
isSearchEmailRunning: searchController.isSearchEmailRunning
|
||||
);
|
||||
mailboxDashBoardController.updateEmailList(newEmailListSynced);
|
||||
searchController.autoFocus.value = true;
|
||||
}
|
||||
|
||||
void searchMoreEmails() {
|
||||
if (canSearchMore && _accountId != null) {
|
||||
searchController.updateFilterEmail(before: emailList.last.receivedAt);
|
||||
final lastEmail = mailboxDashBoardController.emailsInCurrentMailbox.last;
|
||||
searchController.updateFilterEmail(before: lastEmail.receivedAt);
|
||||
consumeState(_searchMoreEmailInteractor.execute(
|
||||
_accountId!,
|
||||
limit: ThreadConstants.defaultLimit,
|
||||
sort: _sortOrder,
|
||||
filter: searchController.searchEmailFilter.value.mappingToEmailFilterCondition(),
|
||||
properties: ThreadConstants.propertiesDefault,
|
||||
lastEmailId: emailList.last.id
|
||||
lastEmailId: lastEmail.id
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -703,7 +738,7 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
if (success.emailList.isNotEmpty) {
|
||||
final resultEmailSearchList = success.emailList
|
||||
.map((email) => email.toSearchPresentationEmail(mailboxDashBoardController.mapMailboxById))
|
||||
.where((email) => !emailList.contains(email))
|
||||
.where((email) => !mailboxDashBoardController.emailsInCurrentMailbox.contains(email))
|
||||
.toList()
|
||||
.syncPresentationEmail(
|
||||
mapMailboxById: mailboxDashBoardController.mapMailboxById,
|
||||
@@ -711,7 +746,7 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
searchQuery: searchController.searchQuery,
|
||||
isSearchEmailRunning: searchController.isSearchEmailRunning
|
||||
);
|
||||
emailList.addAll(resultEmailSearchList);
|
||||
mailboxDashBoardController.emailsInCurrentMailbox.addAll(resultEmailSearchList);
|
||||
} else {
|
||||
canSearchMore = false;
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ class ThreadView extends GetWidget<ThreadController>
|
||||
return Obx(() {
|
||||
if ((!BuildUtils.isWeb || (BuildUtils.isWeb && controller.isSelectionEnabled()
|
||||
&& controller.isSearchActive() && !_responsiveUtils.isDesktop(context)))
|
||||
&& controller.emailList.listEmailSelected.isNotEmpty) {
|
||||
&& controller.mailboxDashBoardController.emailsInCurrentMailbox.listEmailSelected.isNotEmpty) {
|
||||
return Column(children: [
|
||||
const Divider(color: AppColor.lineItemListColor, height: 1, thickness: 0.2),
|
||||
Padding(
|
||||
@@ -131,7 +131,7 @@ class ThreadView extends GetWidget<ThreadController>
|
||||
context,
|
||||
_imagePaths,
|
||||
_responsiveUtils,
|
||||
controller.emailList.listEmailSelected,
|
||||
controller.mailboxDashBoardController.emailsInCurrentMailbox.listEmailSelected,
|
||||
controller.mailboxDashBoardController.selectedMailbox.value)
|
||||
..addOnPressEmailSelectionActionClick((actionType, selectionEmail) =>
|
||||
controller.pressEmailSelectionAction(context, actionType, selectionEmail)))
|
||||
@@ -147,7 +147,7 @@ class ThreadView extends GetWidget<ThreadController>
|
||||
return Obx(() {
|
||||
return AppBarThreadWidgetBuilder(
|
||||
controller.currentMailbox,
|
||||
controller.emailList.listEmailSelected,
|
||||
controller.mailboxDashBoardController.emailsInCurrentMailbox.listEmailSelected,
|
||||
controller.mailboxDashBoardController.currentSelectMode.value,
|
||||
controller.mailboxDashBoardController.filterMessageOption.value,
|
||||
onOpenMailboxMenuActionClick: controller.openMailboxLeftMenu,
|
||||
@@ -287,9 +287,10 @@ class ThreadView extends GetWidget<ThreadController>
|
||||
padding: EdgeInsets.zero,
|
||||
color: Colors.white,
|
||||
child: Obx(() {
|
||||
log('ThreadView::_buildListEmail():');
|
||||
return Visibility(
|
||||
visible: controller.openingEmail.isFalse,
|
||||
child: _buildResultListEmail(context, controller.emailList));
|
||||
child: _buildResultListEmail(context, controller.mailboxDashBoardController.emailsInCurrentMailbox));
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -439,7 +440,7 @@ class ThreadView extends GetWidget<ThreadController>
|
||||
|
||||
bool supportEmptyTrash(BuildContext context) {
|
||||
return controller.isMailboxTrash
|
||||
&& controller.emailList.isNotEmpty
|
||||
&& controller.mailboxDashBoardController.emailsInCurrentMailbox.isNotEmpty
|
||||
&& !controller.isSearchActive()
|
||||
&& !_responsiveUtils.isWebDesktop(context);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"@@last_modified": "2022-12-28T14:09:51.971658",
|
||||
"@@last_modified": "2023-01-09T16:48:24.908944",
|
||||
"initializing_data": "Initializing data...",
|
||||
"@initializing_data": {
|
||||
"type": "text",
|
||||
@@ -2551,5 +2551,27 @@
|
||||
"type": "text",
|
||||
"placeholders_order": [],
|
||||
"placeholders": {}
|
||||
},
|
||||
"youHaveNewMessages": "You have new messages",
|
||||
"@youHaveNewMessages": {
|
||||
"type": "text",
|
||||
"placeholders_order": [],
|
||||
"placeholders": {}
|
||||
},
|
||||
"appTitlePushNotification": "Team Mail",
|
||||
"@appTitlePushNotification": {
|
||||
"type": "text",
|
||||
"placeholders_order": [],
|
||||
"placeholders": {}
|
||||
},
|
||||
"totalNewMessagePushNotification": "{count} new emails",
|
||||
"@totalNewMessagePushNotification": {
|
||||
"type": "text",
|
||||
"placeholders_order": [
|
||||
"count"
|
||||
],
|
||||
"placeholders": {
|
||||
"count": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2620,4 +2620,24 @@ class AppLocalizations {
|
||||
name: 'regards',
|
||||
);
|
||||
}
|
||||
|
||||
String get youHaveNewMessages {
|
||||
return Intl.message(
|
||||
'You have new messages',
|
||||
name: 'youHaveNewMessages',
|
||||
);
|
||||
}
|
||||
|
||||
String get appTitlePushNotification {
|
||||
return Intl.message(
|
||||
'Team Mail',
|
||||
name: 'appTitlePushNotification');
|
||||
}
|
||||
|
||||
String totalNewMessagePushNotification(int count) {
|
||||
return Intl.message(
|
||||
'$count new emails',
|
||||
name: 'totalNewMessagePushNotification',
|
||||
args: [count]);
|
||||
}
|
||||
}
|
||||
@@ -74,4 +74,6 @@ export 'upload/file_info.dart';
|
||||
export 'upload/upload_response.dart';
|
||||
// User
|
||||
export 'user/user_profile.dart';
|
||||
export 'user/user_profile_response.dart';
|
||||
export 'user/user_profile_response.dart';
|
||||
// Notification
|
||||
export 'notification/notification_payload.dart';
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:jmap_dart_client/http/converter/email_id_nullable_converter.dart';
|
||||
import 'package:jmap_dart_client/http/converter/state_nullable_converter.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'notification_payload.g.dart';
|
||||
|
||||
@EmailIdNullableConverter()
|
||||
@StateNullableConverter()
|
||||
@JsonSerializable(explicitToJson: true, includeIfNull: false)
|
||||
class NotificationPayload with EquatableMixin {
|
||||
|
||||
final EmailId? emailId;
|
||||
final jmap.State? newState;
|
||||
|
||||
NotificationPayload({this.emailId, this.newState});
|
||||
|
||||
factory NotificationPayload.fromJson(Map<String, dynamic> json) => _$NotificationPayloadFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$NotificationPayloadToJson(this);
|
||||
|
||||
String get encodeToString => jsonEncode(toJson());
|
||||
|
||||
@override
|
||||
List<Object?> get props => [emailId, newState];
|
||||
}
|
||||
Reference in New Issue
Block a user