TF-2928 Use default browser confirm dialog when token expired

This commit is contained in:
dab246
2024-07-16 16:16:16 +07:00
committed by Dat H. Pham
parent 103dc9c5e3
commit 1fc3b76f94
15 changed files with 192 additions and 141 deletions
@@ -0,0 +1,60 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:flutter/material.dart';
class ConfirmDialogButton extends StatelessWidget {
final String label;
final double? borderRadius;
final Color? backgroundColor;
final EdgeInsetsGeometry? padding;
final int? maxLines;
final TextStyle? textStyle;
final VoidCallback? onTapAction;
const ConfirmDialogButton({
super.key,
required this.label,
this.borderRadius,
this.backgroundColor,
this.padding,
this.maxLines,
this.textStyle,
this.onTapAction
});
@override
Widget build(BuildContext context) {
return Material(
type: MaterialType.transparency,
child: InkWell(
onTap: onTapAction,
borderRadius: BorderRadius.all(Radius.circular(borderRadius ?? 10)),
child: Container(
width: double.infinity,
height: maxLines == 1 ? 44 : null,
decoration: BoxDecoration(
color: backgroundColor ?? AppColor.primaryColor,
borderRadius: BorderRadius.all(Radius.circular(borderRadius ?? 10)),
),
alignment: Alignment.center,
padding: maxLines == 1
? null
: padding ?? const EdgeInsets.symmetric(horizontal: 8, vertical: 12),
child: Text(
label,
textAlign: TextAlign.center,
maxLines: maxLines,
overflow: TextOverflow.ellipsis,
style: textStyle ?? Theme.of(context).textTheme.bodyMedium?.copyWith(
fontSize: 16,
height: 20 / 16,
fontWeight: FontWeight.w500,
color: Colors.white
)
),
),
),
);
}
}
@@ -1,5 +1,6 @@
import 'package:core/core.dart'; import 'package:core/core.dart';
import 'package:core/presentation/views/dialog/confirm_dialog_button.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
typedef OnConfirmButtonAction = void Function(); typedef OnConfirmButtonAction = void Function();
@@ -237,22 +238,26 @@ class ConfirmDialogBuilder {
if (_cancelText.isNotEmpty) if (_cancelText.isNotEmpty)
Padding( Padding(
padding: const EdgeInsetsDirectional.only(top: 8, start: 16, end: 16), padding: const EdgeInsetsDirectional.only(top: 8, start: 16, end: 16),
child: _buildButton( child: ConfirmDialogButton(
name: _cancelText, label: _cancelText,
bgColor: _colorCancelButton, backgroundColor: _colorCancelButton,
radius: _radiusButton, borderRadius: _radiusButton,
textStyle: _styleTextCancelButton, textStyle: _styleTextCancelButton,
action: _onCancelButtonAction), padding: _paddingButton,
maxLines: titleActionButtonMaxLines,
onTapAction: _onCancelButtonAction),
), ),
if (_confirmText.isNotEmpty) if (_confirmText.isNotEmpty)
Padding( Padding(
padding: const EdgeInsetsDirectional.only(top: 8, start: 16, end: 16), padding: const EdgeInsetsDirectional.only(top: 8, start: 16, end: 16),
child: _buildButton( child: ConfirmDialogButton(
name: _confirmText, label: _confirmText,
bgColor: _colorConfirmButton, backgroundColor: _colorConfirmButton,
radius: _radiusButton, borderRadius: _radiusButton,
textStyle: _styleTextConfirmButton, textStyle: _styleTextConfirmButton,
action: _onConfirmButtonAction), padding: _paddingButton,
maxLines: titleActionButtonMaxLines,
onTapAction: _onConfirmButtonAction),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
] ]
@@ -262,59 +267,28 @@ class ConfirmDialogBuilder {
child: Row( child: Row(
children: [ children: [
if (_cancelText.isNotEmpty) if (_cancelText.isNotEmpty)
Expanded(child: _buildButton( Expanded(child: ConfirmDialogButton(
name: _cancelText, label: _cancelText,
bgColor: _colorCancelButton, backgroundColor: _colorCancelButton,
radius: _radiusButton, borderRadius: _radiusButton,
textStyle: _styleTextCancelButton, textStyle: _styleTextCancelButton,
action: _onCancelButtonAction)), padding: _paddingButton,
maxLines: titleActionButtonMaxLines,
onTapAction: _onCancelButtonAction)),
if (_confirmText.isNotEmpty && _cancelText.isNotEmpty) const SizedBox(width: 8), if (_confirmText.isNotEmpty && _cancelText.isNotEmpty) const SizedBox(width: 8),
if (_confirmText.isNotEmpty) if (_confirmText.isNotEmpty)
Expanded(child: _buildButton( Expanded(child: ConfirmDialogButton(
name: _confirmText, label: _confirmText,
bgColor: _colorConfirmButton, backgroundColor: _colorConfirmButton,
radius: _radiusButton, borderRadius: _radiusButton,
textStyle: _styleTextConfirmButton, textStyle: _styleTextConfirmButton,
action: _onConfirmButtonAction)) padding: _paddingButton,
maxLines: titleActionButtonMaxLines,
onTapAction: _onConfirmButtonAction,))
] ]
)) ))
] ]
) )
); );
} }
Widget _buildButton({
String? name,
TextStyle? textStyle,
Color? bgColor,
double? radius,
Function()? action
}) {
return SizedBox(
width: double.infinity,
height: titleActionButtonMaxLines == 1 ? 45 : null,
child: ElevatedButton(
onPressed: action,
style: ElevatedButton.styleFrom(
foregroundColor: bgColor ?? AppColor.colorTextButton,
backgroundColor: bgColor ?? AppColor.colorTextButton,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(radius ?? 8),
side: BorderSide(width: 0, color: bgColor ?? AppColor.colorTextButton),
),
padding: _paddingButton ?? const EdgeInsets.all(8),
elevation: 0
),
child: Text(
name ?? '',
textAlign: TextAlign.center,
maxLines: titleActionButtonMaxLines,
style: textStyle ?? const TextStyle(
fontSize: 17,
fontWeight: FontWeight.w500,
color: Colors.white
)),
),
);
}
} }
+35 -21
View File
@@ -27,7 +27,7 @@ import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart
import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:model/account/authentication_type.dart'; import 'package:model/account/authentication_type.dart';
import 'package:rule_filter/rule_filter/capability_rule_filter.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/before_reconnect_manager.dart';
import 'package:tmail_ui_user/features/base/mixin/message_dialog_action_mixin.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/base/mixin/popup_context_menu_action_mixin.dart';
import 'package:tmail_ui_user/features/caching/caching_manager.dart'; import 'package:tmail_ui_user/features/caching/caching_manager.dart';
@@ -64,7 +64,7 @@ import 'package:tmail_ui_user/main/routes/app_routes.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart';
import 'package:tmail_ui_user/main/utils/app_config.dart'; import 'package:tmail_ui_user/main/utils/app_config.dart';
import 'package:tmail_ui_user/main/utils/app_utils.dart'; import 'package:tmail_ui_user/main/utils/app_utils.dart';
import 'package:universal_html/html.dart' as html; import 'package:tmail_ui_user/main/universal_import/html_stub.dart' as html;
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
abstract class BaseController extends GetxController abstract class BaseController extends GetxController
@@ -90,8 +90,8 @@ abstract class BaseController extends GetxController
GetStoredFirebaseRegistrationInteractor? _getStoredFirebaseRegistrationInteractor; GetStoredFirebaseRegistrationInteractor? _getStoredFirebaseRegistrationInteractor;
DestroyFirebaseRegistrationInteractor? _destroyFirebaseRegistrationInteractor; DestroyFirebaseRegistrationInteractor? _destroyFirebaseRegistrationInteractor;
StreamSubscription<html.Event>? _subscriptionBrowserOnBeforeUnload; StreamSubscription<html.Event>? _onBeforeUnloadBrowserSubscription;
StreamSubscription<html.Event>? _subscriptionBrowserOnUnload; StreamSubscription<html.Event>? _onUnloadBrowserSubscription;
final viewState = Rx<Either<Failure, Success>>(Right(UIState.idle)); final viewState = Rx<Either<Failure, Success>>(Right(UIState.idle));
FpsCallback? fpsCallback; FpsCallback? fpsCallback;
@@ -105,21 +105,21 @@ abstract class BaseController extends GetxController
} }
void _triggerBrowserReloadListener() { void _triggerBrowserReloadListener() {
_subscriptionBrowserOnBeforeUnload = _onBeforeUnloadBrowserSubscription =
html.window.onBeforeUnload.listen(handleBrowserBeforeReloadAction); html.window.onBeforeUnload.listen(onBeforeUnloadBrowserListener);
_subscriptionBrowserOnUnload = _onUnloadBrowserSubscription =
html.window.onUnload.listen(handleBrowserReloadAction); html.window.onUnload.listen(onUnloadBrowserListener);
} }
Future<void> handleBrowserBeforeReloadAction(html.Event event) async {} Future<void> onBeforeUnloadBrowserListener(html.Event event) async {}
Future<void> handleBrowserReloadAction(html.Event event) async {} Future<void> onUnloadBrowserListener(html.Event event) async {}
@override @override
void onClose() { void onClose() {
if (PlatformInfo.isWeb) { if (PlatformInfo.isWeb) {
_subscriptionBrowserOnBeforeUnload?.cancel(); _onBeforeUnloadBrowserSubscription?.cancel();
_subscriptionBrowserOnUnload?.cancel(); _onUnloadBrowserSubscription?.cancel();
} }
super.onClose(); super.onClose();
} }
@@ -204,8 +204,8 @@ abstract class BaseController extends GetxController
} }
} }
Future<void> _executeBeforeUnloadAndLogOut() async { Future<void> _executeBeforeReconnectAndLogOut() async {
await executeBeforeUnload(); await executeBeforeReconnect();
clearDataAndGoToLoginPage(); clearDataAndGoToLoginPage();
} }
@@ -234,7 +234,7 @@ abstract class BaseController extends GetxController
void _handleBadCredentialsException() { void _handleBadCredentialsException() {
if (PlatformInfo.isWeb) { if (PlatformInfo.isWeb) {
if (currentContext == null) { if (currentContext == null) {
_executeBeforeUnloadAndLogOut(); _executeBeforeReconnectAndLogOut();
return; return;
} }
@@ -245,11 +245,25 @@ abstract class BaseController extends GetxController
title: AppLocalizations.of(currentContext!).sessionExpired, title: AppLocalizations.of(currentContext!).sessionExpired,
alignCenter: true, alignCenter: true,
outsideDismissible: false, outsideDismissible: false,
titleActionButtonMaxLines: 1,
icon: SvgPicture.asset(imagePaths.icTMailLogo, width: 64, height: 64), icon: SvgPicture.asset(imagePaths.icTMailLogo, width: 64, height: 64),
paddingButton: const EdgeInsets.symmetric(horizontal: 8, vertical: 16), onConfirmAction: _executeBeforeReconnectAndLogOut);
onConfirmAction: _executeBeforeUnloadAndLogOut);
} else if (PlatformInfo.isMobile) { } else if (PlatformInfo.isMobile) {
clearDataAndGoToLoginPage(); if (currentContext == null) {
clearDataAndGoToLoginPage();
return;
}
showConfirmDialogAction(
currentContext!,
AppLocalizations.of(currentContext!).dialogMessageSessionHasExpired,
AppLocalizations.of(currentContext!).reconnect,
title: AppLocalizations.of(currentContext!).sessionExpired,
alignCenter: true,
outsideDismissible: false,
titleActionButtonMaxLines: 1,
icon: SvgPicture.asset(imagePaths.icTMailLogo, width: 64, height: 64),
onConfirmAction: clearDataAndGoToLoginPage);
} }
} }
@@ -413,9 +427,9 @@ abstract class BaseController extends GetxController
} }
} }
Future<void> executeBeforeUnload() async { Future<void> executeBeforeReconnect() async {
final beforeUnloadManager = getBinding<BeforeUnloadManager>(); final beforeReconnectManager = getBinding<BeforeReconnectManager>();
await beforeUnloadManager?.executeBeforeUnloadListeners(); await beforeReconnectManager?.executeBeforeReconnectListeners();
} }
Future<void> clearDataAndGoToLoginPage() async { Future<void> clearDataAndGoToLoginPage() async {
@@ -0,0 +1,3 @@
abstract class BeforeReconnectHandler {
Future<void> onBeforeReconnect();
}
@@ -0,0 +1,24 @@
import 'package:core/utils/app_logger.dart';
typedef BeforeReconnectListener = Future<void> Function();
class BeforeReconnectManager {
static final BeforeReconnectManager _instance = BeforeReconnectManager._();
factory BeforeReconnectManager() => _instance;
BeforeReconnectManager._();
final _listeners = <BeforeReconnectListener>[];
void addListener(BeforeReconnectListener listener) {
_listeners.add(listener);
}
void removeListener(BeforeReconnectListener listener) {
_listeners.remove(listener);
}
Future<void> executeBeforeReconnectListeners() async {
await Future.wait(_listeners.map((listener) => listener.call()))
.onError((error, stackTrace) => [logError(error.toString())]);
}
}
@@ -1,3 +0,0 @@
abstract class BeforeUnloadHandler {
Future<void> onBeforeUnload();
}
@@ -1,24 +0,0 @@
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())]);
}
}
@@ -27,8 +27,8 @@ import 'package:receive_sharing_intent/receive_sharing_intent.dart';
import 'package:rich_text_composer/rich_text_composer.dart'; import 'package:rich_text_composer/rich_text_composer.dart';
import 'package:super_tag_editor/tag_editor.dart'; import 'package:super_tag_editor/tag_editor.dart';
import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/base/before_unload_handler.dart'; import 'package:tmail_ui_user/features/base/before_reconnect_handler.dart';
import 'package:tmail_ui_user/features/base/before_unload_manager.dart'; import 'package:tmail_ui_user/features/base/before_reconnect_manager.dart';
import 'package:tmail_ui_user/features/base/state/base_ui_state.dart'; import 'package:tmail_ui_user/features/base/state/base_ui_state.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/composer/domain/exceptions/compose_email_exception.dart'; import 'package:tmail_ui_user/features/composer/domain/exceptions/compose_email_exception.dart';
@@ -95,14 +95,14 @@ import 'package:tmail_ui_user/features/upload/presentation/controller/upload_con
import 'package:tmail_ui_user/main/exceptions/remote_exception.dart'; import 'package:tmail_ui_user/main/exceptions/remote_exception.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart';
import 'package:universal_html/html.dart' as html; import 'package:tmail_ui_user/main/universal_import/html_stub.dart' as html;
class ComposerController extends BaseController with DragDropFileMixin implements BeforeUnloadHandler { class ComposerController extends BaseController with DragDropFileMixin implements BeforeReconnectHandler {
final mailboxDashBoardController = Get.find<MailboxDashBoardController>(); final mailboxDashBoardController = Get.find<MailboxDashBoardController>();
final networkConnectionController = Get.find<NetworkConnectionController>(); final networkConnectionController = Get.find<NetworkConnectionController>();
final _dynamicUrlInterceptors = Get.find<DynamicUrlInterceptors>(); final _dynamicUrlInterceptors = Get.find<DynamicUrlInterceptors>();
final _beforeUnloadManager = Get.find<BeforeUnloadManager>(); final _beforeReconnectManager = Get.find<BeforeReconnectManager>();
final composerArguments = Rxn<ComposerArguments>(); final composerArguments = Rxn<ComposerArguments>();
final isEnableEmailSendButton = false.obs; final isEnableEmailSendButton = false.obs;
@@ -220,7 +220,7 @@ class ComposerController extends BaseController with DragDropFileMixin implement
scrollControllerEmailAddress.addListener(_scrollControllerEmailAddressListener); scrollControllerEmailAddress.addListener(_scrollControllerEmailAddressListener);
_listenStreamEvent(); _listenStreamEvent();
_getAlwaysReadReceiptSetting(); _getAlwaysReadReceiptSetting();
_beforeUnloadManager.addListener(onBeforeUnload); _beforeReconnectManager.addListener(onBeforeReconnect);
} }
@override @override
@@ -250,7 +250,7 @@ class ComposerController extends BaseController with DragDropFileMixin implement
_subscriptionOnDrop?.cancel(); _subscriptionOnDrop?.cancel();
subjectEmailInputFocusNode?.removeListener(_subjectEmailInputFocusListener); subjectEmailInputFocusNode?.removeListener(_subjectEmailInputFocusListener);
_composerCacheListener?.cancel(); _composerCacheListener?.cancel();
_beforeUnloadManager.removeListener(onBeforeUnload); _beforeReconnectManager.removeListener(onBeforeReconnect);
if (PlatformInfo.isWeb) { if (PlatformInfo.isWeb) {
richTextWebController = null; richTextWebController = null;
} else { } else {
@@ -360,7 +360,7 @@ class ComposerController extends BaseController with DragDropFileMixin implement
} }
@override @override
Future<void> handleBrowserReloadAction(html.Event event) async { Future<void> onUnloadBrowserListener(html.Event event) async {
await _removeComposerCacheOnWebInteractor.execute(); await _removeComposerCacheOnWebInteractor.execute();
await _saveComposerCacheOnWebAction(); await _saveComposerCacheOnWebAction();
} }
@@ -2302,7 +2302,7 @@ class ComposerController extends BaseController with DragDropFileMixin implement
} }
@override @override
Future<void> onBeforeUnload() async { Future<void> onBeforeReconnect() async {
if (mailboxDashBoardController.accountId.value != null && if (mailboxDashBoardController.accountId.value != null &&
mailboxDashBoardController.sessionCurrent?.username != null mailboxDashBoardController.sessionCurrent?.username != null
) { ) {
@@ -151,9 +151,9 @@ import 'package:tmail_ui_user/main/routes/dialog_router.dart';
import 'package:tmail_ui_user/main/routes/navigation_router.dart'; import 'package:tmail_ui_user/main/routes/navigation_router.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart'; 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/route_utils.dart';
import 'package:tmail_ui_user/main/universal_import/html_stub.dart' as html;
import 'package:tmail_ui_user/main/utils/email_receive_manager.dart'; import 'package:tmail_ui_user/main/utils/email_receive_manager.dart';
import 'package:tmail_ui_user/main/utils/ios_notification_manager.dart'; import 'package:tmail_ui_user/main/utils/ios_notification_manager.dart';
import 'package:universal_html/html.dart' as html;
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
class MailboxDashBoardController extends ReloadableController { class MailboxDashBoardController extends ReloadableController {
@@ -417,7 +417,7 @@ class MailboxDashBoardController extends ReloadableController {
} }
@override @override
Future<void> handleBrowserBeforeReloadAction(html.Event event) async { Future<void> onBeforeUnloadBrowserListener(html.Event event) async {
if (event is html.BeforeUnloadEvent if (event is html.BeforeUnloadEvent
&& composerOverlayState.value == ComposerOverlayState.active) { && composerOverlayState.value == ComposerOverlayState.active) {
event.preventDefault(); event.preventDefault();
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"@@last_modified": "2024-07-12T12:54:25.065342", "@@last_modified": "2024-07-17T01:36:03.095458",
"initializing_data": "Initializing data...", "initializing_data": "Initializing data...",
"@initializing_data": { "@initializing_data": {
"type": "text", "type": "text",
+2 -2
View File
@@ -12,7 +12,7 @@ import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.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/base/before_reconnect_manager.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/main/utils/app_config.dart'; import 'package:tmail_ui_user/main/utils/app_config.dart';
import 'package:tmail_ui_user/main/utils/email_receive_manager.dart'; import 'package:tmail_ui_user/main/utils/email_receive_manager.dart';
@@ -66,7 +66,7 @@ class CoreBindings extends Bindings {
Get.put(FileUtils()); Get.put(FileUtils());
Get.put(PrintUtils()); Get.put(PrintUtils());
Get.put(ApplicationManager(Get.find<DeviceInfoPlugin>())); Get.put(ApplicationManager(Get.find<DeviceInfoPlugin>()));
Get.put(BeforeUnloadManager()); Get.put(BeforeReconnectManager());
if (PlatformInfo.isIOS) { if (PlatformInfo.isIOS) {
Get.put(IOSNotificationManager()); Get.put(IOSNotificationManager());
} }
+1
View File
@@ -0,0 +1 @@
export 'package:universal_html/src/html.dart';
+1
View File
@@ -0,0 +1 @@
export 'html_io.dart' if (dart.library.html) 'html_web.dart';
+1
View File
@@ -0,0 +1 @@
export 'package:universal_html/html.dart';
@@ -1,9 +1,9 @@
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:tmail_ui_user/features/base/before_unload_manager.dart'; import 'package:tmail_ui_user/features/base/before_reconnect_manager.dart';
void main() { void main() {
group('before unload manager test:', () { group('before reconnect manager test:', () {
test( test(
'should finish all futures ' 'should finish all futures '
'when no future fails', 'when no future fails',
@@ -13,13 +13,13 @@ void main() {
future1Second() => Future<void>.delayed(const Duration(seconds: 1), () => result.add(1)); future1Second() => Future<void>.delayed(const Duration(seconds: 1), () => result.add(1));
future2Second() => Future<void>.delayed(const Duration(seconds: 2), () => result.add(2)); future2Second() => Future<void>.delayed(const Duration(seconds: 2), () => result.add(2));
future3Second() => Future<void>.delayed(const Duration(seconds: 3), () => result.add(3)); future3Second() => Future<void>.delayed(const Duration(seconds: 3), () => result.add(3));
final beforeUnloadManager = BeforeUnloadManager(); final beforeReconnectManager = BeforeReconnectManager();
beforeUnloadManager.addListener(future1Second); beforeReconnectManager.addListener(future1Second);
beforeUnloadManager.addListener(future2Second); beforeReconnectManager.addListener(future2Second);
beforeUnloadManager.addListener(future3Second); beforeReconnectManager.addListener(future3Second);
// act // act
await beforeUnloadManager.executeBeforeUnloadListeners(); await beforeReconnectManager.executeBeforeReconnectListeners();
// assert // assert
expect(result.length, 3); expect(result.length, 3);
@@ -35,13 +35,13 @@ void main() {
future1Second() => Future<void>.delayed(const Duration(seconds: 1), () => result.add(1)); future1Second() => Future<void>.delayed(const Duration(seconds: 1), () => result.add(1));
future2Second() => Future<void>.delayed(const Duration(seconds: 2), () => throw exception); future2Second() => Future<void>.delayed(const Duration(seconds: 2), () => throw exception);
future3Second() => Future<void>.delayed(const Duration(seconds: 3), () => result.add(3)); future3Second() => Future<void>.delayed(const Duration(seconds: 3), () => result.add(3));
final beforeUnloadManager = BeforeUnloadManager(); final beforeReconnectManager = BeforeReconnectManager();
beforeUnloadManager.addListener(future1Second); beforeReconnectManager.addListener(future1Second);
beforeUnloadManager.addListener(future2Second); beforeReconnectManager.addListener(future2Second);
beforeUnloadManager.addListener(future3Second); beforeReconnectManager.addListener(future3Second);
// act // act
await beforeUnloadManager.executeBeforeUnloadListeners(); await beforeReconnectManager.executeBeforeReconnectListeners();
// assert // assert
expect(result.length, 2); expect(result.length, 2);
@@ -58,13 +58,13 @@ void main() {
future1Second() => Future<void>.delayed(const Duration(seconds: 1), () => throw exception1); future1Second() => Future<void>.delayed(const Duration(seconds: 1), () => throw exception1);
future2Second() => Future<void>.delayed(const Duration(seconds: 2), () => throw exception2); future2Second() => Future<void>.delayed(const Duration(seconds: 2), () => throw exception2);
future3Second() => Future<void>.delayed(const Duration(seconds: 3), () => result.add(3)); future3Second() => Future<void>.delayed(const Duration(seconds: 3), () => result.add(3));
final beforeUnloadManager = BeforeUnloadManager(); final beforeReconnectManager = BeforeReconnectManager();
beforeUnloadManager.addListener(future1Second); beforeReconnectManager.addListener(future1Second);
beforeUnloadManager.addListener(future2Second); beforeReconnectManager.addListener(future2Second);
beforeUnloadManager.addListener(future3Second); beforeReconnectManager.addListener(future3Second);
// act // act
await beforeUnloadManager.executeBeforeUnloadListeners(); await beforeReconnectManager.executeBeforeReconnectListeners();
// assert // assert
expect(result.length, 1); expect(result.length, 1);
@@ -81,13 +81,13 @@ void main() {
future1Second() => Future<void>.delayed(const Duration(seconds: 1), () => result.add(1)); future1Second() => Future<void>.delayed(const Duration(seconds: 1), () => result.add(1));
future2Second() => Future<void>.delayed(const Duration(seconds: 2), () => throw exception2); future2Second() => Future<void>.delayed(const Duration(seconds: 2), () => throw exception2);
future3Second() => Future<void>.delayed(const Duration(seconds: 3), () => throw exception3); future3Second() => Future<void>.delayed(const Duration(seconds: 3), () => throw exception3);
final beforeUnloadManager = BeforeUnloadManager(); final beforeReconnectManager = BeforeReconnectManager();
beforeUnloadManager.addListener(future1Second); beforeReconnectManager.addListener(future1Second);
beforeUnloadManager.addListener(future2Second); beforeReconnectManager.addListener(future2Second);
beforeUnloadManager.addListener(future3Second); beforeReconnectManager.addListener(future3Second);
// act // act
await beforeUnloadManager.executeBeforeUnloadListeners(); await beforeReconnectManager.executeBeforeReconnectListeners();
// assert // assert
expect(result.length, 1); expect(result.length, 1);