TF-3334 Use queue to handle multiple refresh changes mailbox from incoming websocket
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:core/presentation/extensions/either_view_state_extension.dart';
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
@@ -32,6 +33,8 @@ import 'package:tmail_ui_user/features/manage_account/domain/state/create_new_ru
|
||||
import 'package:tmail_ui_user/features/manage_account/domain/usecases/create_new_email_rule_filter_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/network_connection/presentation/network_connection_controller.dart'
|
||||
if (dart.library.html) 'package:tmail_ui_user/features/network_connection/presentation/web_network_connection_controller.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/presentation/websocket/web_socket_message.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/presentation/websocket/web_socket_queue_handler.dart';
|
||||
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rules_filter_creator_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/search/email/presentation/search_email_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
|
||||
@@ -90,12 +93,12 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
bool canLoadMore = false;
|
||||
bool canSearchMore = false;
|
||||
MailboxId? _currentMemoryMailboxId;
|
||||
jmap.State? _currentEmailState;
|
||||
final ScrollController listEmailController = ScrollController();
|
||||
final FocusNode focusNodeKeyBoard = FocusNode();
|
||||
final latestEmailSelectedOrUnselected = Rxn<PresentationEmail>();
|
||||
@visibleForTesting
|
||||
bool isListEmailScrollViewJumping = false;
|
||||
WebSocketQueueHandler? _webSocketQueueHandler;
|
||||
|
||||
StreamSubscription<html.Event>? _resizeBrowserStreamSubscription;
|
||||
|
||||
@@ -128,6 +131,7 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
if (PlatformInfo.isWeb) {
|
||||
_registerBrowserResizeListener();
|
||||
}
|
||||
_initWebSocketQueueHandler();
|
||||
super.onInit();
|
||||
}
|
||||
|
||||
@@ -140,7 +144,6 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
@override
|
||||
void onClose() {
|
||||
_currentMemoryMailboxId = null;
|
||||
_currentEmailState = null;
|
||||
listEmailController.dispose();
|
||||
focusNodeKeyBoard.dispose();
|
||||
if (PlatformInfo.isWeb) {
|
||||
@@ -154,8 +157,6 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
super.handleSuccessViewState(success);
|
||||
if (success is GetAllEmailSuccess) {
|
||||
_getAllEmailSuccess(success);
|
||||
} else if (success is RefreshChangesAllEmailSuccess) {
|
||||
_refreshChangesAllEmailSuccess(success);
|
||||
} else if (success is LoadMoreEmailsSuccess) {
|
||||
_loadMoreEmailsSuccess(success);
|
||||
} else if (success is SearchEmailSuccess) {
|
||||
@@ -231,6 +232,13 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
});
|
||||
}
|
||||
|
||||
void _initWebSocketQueueHandler() {
|
||||
_webSocketQueueHandler = WebSocketQueueHandler(
|
||||
processMessageCallback: _handleWebSocketMessage,
|
||||
onErrorCallback: onError,
|
||||
);
|
||||
}
|
||||
|
||||
void _resetLoadingMore() {
|
||||
if (loadingMoreStatus.value == LoadingMoreStatus.running) {
|
||||
loadingMoreStatus.value = LoadingMoreStatus.idle;
|
||||
@@ -383,8 +391,8 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
log('ThreadController::_getAllEmailSuccess: GetAllForMailboxId = ${success.currentMailboxId?.asString} | SELECTED_MAILBOX_ID = ${selectedMailboxId?.asString} | SELECTED_MAILBOX_NAME = ${selectedMailbox?.name?.name}');
|
||||
return;
|
||||
}
|
||||
_currentEmailState = success.currentEmailState;
|
||||
log('ThreadController::_getAllEmailSuccess():COUNT = ${success.emailList.length} | EMAIL_STATE = $_currentEmailState');
|
||||
mailboxDashBoardController.setCurrentEmailState(success.currentEmailState);
|
||||
log('ThreadController::_getAllEmailSuccess():COUNT = ${success.emailList.length} | EMAIL_STATE = ${mailboxDashBoardController.currentEmailState}');
|
||||
final newListEmail = success.emailList.syncPresentationEmail(
|
||||
mapMailboxById: mailboxDashBoardController.mapMailboxById,
|
||||
selectedMailbox: selectedMailbox,
|
||||
@@ -413,8 +421,7 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
log('ThreadController::_refreshChangesAllEmailSuccess: RefreshedMailboxId = ${success.currentMailboxId?.asString} | SELECTED_MAILBOX_ID = ${selectedMailboxId?.asString} | SELECTED_MAILBOX_NAME = ${selectedMailbox?.name?.name}');
|
||||
return;
|
||||
}
|
||||
|
||||
_currentEmailState = success.currentEmailState;
|
||||
mailboxDashBoardController.setCurrentEmailState(success.currentEmailState);
|
||||
log('ThreadController::_refreshChangesAllEmailSuccess: COUNT = ${success.emailList.length}');
|
||||
final emailsBeforeChanges = mailboxDashBoardController.emailsInCurrentMailbox;
|
||||
final emailsAfterChanges = success.emailList;
|
||||
@@ -515,31 +522,112 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
|
||||
void _refreshEmailChanges({jmap.State? newState}) {
|
||||
log('ThreadController::_refreshEmailChanges(): newState: $newState');
|
||||
if (searchController.isSearchEmailRunning) {
|
||||
_searchEmail(limit: limitEmailFetched, needRefreshSearchState: true);
|
||||
} else {
|
||||
if (_currentEmailState == null ||
|
||||
_currentEmailState == newState ||
|
||||
_session == null ||
|
||||
_accountId == null) {
|
||||
return;
|
||||
if (_accountId == null ||
|
||||
_session == null ||
|
||||
mailboxDashBoardController.currentEmailState == null ||
|
||||
newState == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
_webSocketQueueHandler?.enqueue(WebSocketMessage(newState: newState));
|
||||
}
|
||||
|
||||
Future<void> _handleWebSocketMessage(WebSocketMessage message) async {
|
||||
try {
|
||||
if (mailboxDashBoardController.currentEmailState == null ||
|
||||
mailboxDashBoardController.currentEmailState == message.newState) {
|
||||
log('ThreadController::_handleWebSocketMessage:Skipping redundant state: ${message.newState}');
|
||||
return Future.value();
|
||||
}
|
||||
consumeState(_refreshChangesEmailsInMailboxInteractor.execute(
|
||||
|
||||
if (searchController.isSearchEmailRunning) {
|
||||
await _refreshChangeSearchEmail();
|
||||
} else {
|
||||
await _refreshChangeListEmail();
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
logError('ThreadController::_handleWebSocketMessage:Error processing state: $e');
|
||||
onError(e, stackTrace);
|
||||
} finally {
|
||||
if (mailboxDashBoardController.currentEmailState != null) {
|
||||
_webSocketQueueHandler?.removeMessagesUpToCurrent(
|
||||
mailboxDashBoardController.currentEmailState!.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _refreshChangeSearchEmail() async {
|
||||
log('ThreadController::_refreshChangeSearchEmail:');
|
||||
if (limitEmailFetched.value > ThreadConstants.maximumEmailQueryLimit &&
|
||||
listEmailController.hasClients) {
|
||||
listEmailController.jumpTo(0);
|
||||
}
|
||||
canSearchMore = false;
|
||||
searchController.updateFilterEmail(
|
||||
positionOption: option(
|
||||
_searchEmailFilter.sortOrderType.isScrollByPosition(),
|
||||
0,
|
||||
),
|
||||
beforeOption: const None(),
|
||||
);
|
||||
searchController.activateSimpleSearch();
|
||||
|
||||
final searchViewState = await _searchEmailInteractor.execute(
|
||||
_session!,
|
||||
_accountId!,
|
||||
limit: limitEmailFetched,
|
||||
position: _searchEmailFilter.position,
|
||||
sort: _searchEmailFilter.sortOrderType.getSortOrder().toNullable(),
|
||||
filter: _searchEmailFilter.mappingToEmailFilterCondition(
|
||||
moreFilterCondition: _getFilterCondition(),
|
||||
),
|
||||
properties: EmailUtils.getPropertiesForEmailGetMethod(
|
||||
_session!,
|
||||
_accountId!,
|
||||
_currentEmailState!,
|
||||
sort: EmailSortOrderType.mostRecent.getSortOrder().toNullable(),
|
||||
propertiesCreated: EmailUtils.getPropertiesForEmailGetMethod(
|
||||
_session!,
|
||||
_accountId!,
|
||||
),
|
||||
propertiesUpdated: ThreadConstants.propertiesUpdatedDefault,
|
||||
emailFilter: EmailFilter(
|
||||
filter: _getFilterCondition(mailboxIdSelected: selectedMailboxId),
|
||||
filterOption: mailboxDashBoardController.filterMessageOption.value,
|
||||
mailboxId: selectedMailboxId,
|
||||
),
|
||||
));
|
||||
),
|
||||
needRefreshSearchState: true,
|
||||
).last;
|
||||
|
||||
final searchState = searchViewState
|
||||
.foldSuccessWithResult<SearchEmailSuccess>();
|
||||
|
||||
if (searchState is SearchEmailSuccess) {
|
||||
_searchEmailsSuccess(searchState);
|
||||
} else {
|
||||
mailboxDashBoardController.updateRefreshAllEmailState(
|
||||
Left(RefreshAllEmailFailure()));
|
||||
canSearchMore = false;
|
||||
mailboxDashBoardController.emailsInCurrentMailbox.clear();
|
||||
onDataFailureViewState(searchState);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _refreshChangeListEmail() async {
|
||||
log('ThreadController::_refreshChangeListEmail:');
|
||||
final refreshViewState = await _refreshChangesEmailsInMailboxInteractor.execute(
|
||||
_session!,
|
||||
_accountId!,
|
||||
mailboxDashBoardController.currentEmailState!,
|
||||
sort: EmailSortOrderType.mostRecent.getSortOrder().toNullable(),
|
||||
propertiesCreated: EmailUtils.getPropertiesForEmailGetMethod(
|
||||
_session!,
|
||||
_accountId!,
|
||||
),
|
||||
propertiesUpdated: ThreadConstants.propertiesUpdatedDefault,
|
||||
emailFilter: EmailFilter(
|
||||
filter: _getFilterCondition(mailboxIdSelected: selectedMailboxId),
|
||||
filterOption: mailboxDashBoardController.filterMessageOption.value,
|
||||
mailboxId: selectedMailboxId,
|
||||
),
|
||||
).last;
|
||||
|
||||
final refreshState = refreshViewState
|
||||
.foldSuccessWithResult<RefreshChangesAllEmailSuccess>();
|
||||
|
||||
if (refreshState is RefreshChangesAllEmailSuccess) {
|
||||
_refreshChangesAllEmailSuccess(refreshState);
|
||||
} else {
|
||||
onDataFailureViewState(refreshState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1168,12 +1256,10 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
}
|
||||
|
||||
void goToCreateEmailRuleView() async {
|
||||
final accountId = mailboxDashBoardController.accountId.value;
|
||||
final session = mailboxDashBoardController.sessionCurrent;
|
||||
if (accountId != null && session != null) {
|
||||
if (_accountId != null && _session != null) {
|
||||
final arguments = RulesFilterCreatorArguments(
|
||||
accountId,
|
||||
session,
|
||||
_accountId!,
|
||||
_session!,
|
||||
mailboxDestination: selectedMailbox
|
||||
);
|
||||
|
||||
@@ -1182,7 +1268,7 @@ class ThreadController extends BaseController with EmailActionController {
|
||||
: await push(AppRoutes.rulesFilterCreator, arguments: arguments);
|
||||
|
||||
if (newRuleFilterRequest is CreateNewEmailRuleFilterRequest) {
|
||||
_createNewRuleFilterAction(accountId, newRuleFilterRequest);
|
||||
_createNewRuleFilterAction(_accountId!, newRuleFilterRequest);
|
||||
}
|
||||
} else {
|
||||
logError('ThreadController::goToCreateEmailRuleView: Account or Session is NULL');
|
||||
|
||||
Reference in New Issue
Block a user