TF-2901 Create before unload manager to handle before log out callbacks
This commit is contained in:
@@ -23,6 +23,7 @@ import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:model/account/authentication_type.dart';
|
||||
import 'package:rule_filter/rule_filter/capability_rule_filter.dart';
|
||||
import 'package:tmail_ui_user/features/base/before_unload_manager.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/message_dialog_action_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/popup_context_menu_action_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/caching/caching_manager.dart';
|
||||
@@ -169,7 +170,14 @@ abstract class BaseController extends GetxController
|
||||
if (!authorizationInterceptors.isAppRunning) {
|
||||
return;
|
||||
}
|
||||
_executeBeforeUnloadAndLogOut(exception);
|
||||
}
|
||||
|
||||
Future<void> _executeBeforeUnloadAndLogOut(Exception? exception) async {
|
||||
if (exception is BadCredentialsException || exception is ConnectionError) {
|
||||
if (PlatformInfo.isWeb) {
|
||||
await executeBeforeUnload();
|
||||
}
|
||||
clearDataAndGoToLoginPage();
|
||||
}
|
||||
}
|
||||
@@ -334,6 +342,11 @@ abstract class BaseController extends GetxController
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> executeBeforeUnload() async {
|
||||
final beforeUnloadManager = getBinding<BeforeUnloadManager>();
|
||||
await beforeUnloadManager?.executeBeforeUnloadListeners();
|
||||
}
|
||||
|
||||
Future<void> clearDataAndGoToLoginPage() async {
|
||||
log('BaseController::clearDataAndGoToLoginPage:');
|
||||
await clearAllData();
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
abstract class BeforeUnloadHandler {
|
||||
Future<void> onBeforeUnload();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
|
||||
typedef BeforeUnloadListener = Future<void> Function();
|
||||
|
||||
class BeforeUnloadManager {
|
||||
static final BeforeUnloadManager _instance = BeforeUnloadManager._();
|
||||
factory BeforeUnloadManager() => _instance;
|
||||
BeforeUnloadManager._();
|
||||
|
||||
final _listeners = <BeforeUnloadListener>[];
|
||||
|
||||
void addListener(BeforeUnloadListener listener) {
|
||||
_listeners.add(listener);
|
||||
}
|
||||
|
||||
void removeListener(BeforeUnloadListener listener) {
|
||||
_listeners.remove(listener);
|
||||
}
|
||||
|
||||
Future<void> executeBeforeUnloadListeners() async {
|
||||
await Future.wait(_listeners.map((listener) => listener.call()))
|
||||
.onError((error, stackTrace) => [logError(error.toString())]);
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tmail_ui_user/features/base/before_unload_manager.dart';
|
||||
import 'package:tmail_ui_user/features/sending_queue/presentation/utils/sending_queue_isolate_manager.dart';
|
||||
import 'package:tmail_ui_user/main/utils/app_config.dart';
|
||||
import 'package:tmail_ui_user/main/utils/email_receive_manager.dart';
|
||||
@@ -64,6 +65,7 @@ class CoreBindings extends Bindings {
|
||||
Get.put(FileUtils());
|
||||
Get.put(PrintUtils());
|
||||
Get.put(ApplicationManager(Get.find<DeviceInfoPlugin>()));
|
||||
Get.put(BeforeUnloadManager());
|
||||
}
|
||||
|
||||
void _bindingIsolate() {
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:tmail_ui_user/features/base/before_unload_manager.dart';
|
||||
|
||||
void main() {
|
||||
|
||||
group('before unload manager test:', () {
|
||||
test(
|
||||
'should finish all futures '
|
||||
'when no future fails',
|
||||
() async {
|
||||
// arrange
|
||||
List<int> result = [];
|
||||
future1Second() => Future<void>.delayed(const Duration(seconds: 1), () => result.add(1));
|
||||
future2Second() => Future<void>.delayed(const Duration(seconds: 2), () => result.add(2));
|
||||
future3Second() => Future<void>.delayed(const Duration(seconds: 3), () => result.add(3));
|
||||
final beforeUnloadManager = BeforeUnloadManager();
|
||||
beforeUnloadManager.addListener(future1Second);
|
||||
beforeUnloadManager.addListener(future2Second);
|
||||
beforeUnloadManager.addListener(future3Second);
|
||||
|
||||
// act
|
||||
await beforeUnloadManager.executeBeforeUnloadListeners();
|
||||
|
||||
// assert
|
||||
expect(result.length, 3);
|
||||
});
|
||||
|
||||
test(
|
||||
'should finish all possible futures '
|
||||
'when one future fail',
|
||||
() async {
|
||||
// arrange
|
||||
List<int> result = [];
|
||||
final exception = Exception('error');
|
||||
future1Second() => Future<void>.delayed(const Duration(seconds: 1), () => result.add(1));
|
||||
future2Second() => Future<void>.delayed(const Duration(seconds: 2), () => throw exception);
|
||||
future3Second() => Future<void>.delayed(const Duration(seconds: 3), () => result.add(3));
|
||||
final beforeUnloadManager = BeforeUnloadManager();
|
||||
beforeUnloadManager.addListener(future1Second);
|
||||
beforeUnloadManager.addListener(future2Second);
|
||||
beforeUnloadManager.addListener(future3Second);
|
||||
|
||||
// act
|
||||
await beforeUnloadManager.executeBeforeUnloadListeners();
|
||||
|
||||
// assert
|
||||
expect(result.length, 2);
|
||||
});
|
||||
|
||||
test(
|
||||
'should finish all possible futures '
|
||||
'when more than one future fail',
|
||||
() async {
|
||||
// arrange
|
||||
List<int> result = [];
|
||||
final exception1 = Exception('error 1');
|
||||
final exception2 = Exception('error 2');
|
||||
future1Second() => Future<void>.delayed(const Duration(seconds: 1), () => throw exception1);
|
||||
future2Second() => Future<void>.delayed(const Duration(seconds: 2), () => throw exception2);
|
||||
future3Second() => Future<void>.delayed(const Duration(seconds: 3), () => result.add(3));
|
||||
final beforeUnloadManager = BeforeUnloadManager();
|
||||
beforeUnloadManager.addListener(future1Second);
|
||||
beforeUnloadManager.addListener(future2Second);
|
||||
beforeUnloadManager.addListener(future3Second);
|
||||
|
||||
// act
|
||||
await beforeUnloadManager.executeBeforeUnloadListeners();
|
||||
|
||||
// assert
|
||||
expect(result.length, 1);
|
||||
});
|
||||
|
||||
test(
|
||||
'should finish all possible futures '
|
||||
'when more than one future fail',
|
||||
() async {
|
||||
// arrange
|
||||
List<int> result = [];
|
||||
final exception3 = Exception('error 3');
|
||||
final exception2 = Exception('error 2');
|
||||
future1Second() => Future<void>.delayed(const Duration(seconds: 1), () => result.add(1));
|
||||
future2Second() => Future<void>.delayed(const Duration(seconds: 2), () => throw exception2);
|
||||
future3Second() => Future<void>.delayed(const Duration(seconds: 3), () => throw exception3);
|
||||
final beforeUnloadManager = BeforeUnloadManager();
|
||||
beforeUnloadManager.addListener(future1Second);
|
||||
beforeUnloadManager.addListener(future2Second);
|
||||
beforeUnloadManager.addListener(future3Second);
|
||||
|
||||
// act
|
||||
await beforeUnloadManager.executeBeforeUnloadListeners();
|
||||
|
||||
// assert
|
||||
expect(result.length, 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user