TF-2928 Use default browser confirm dialog when token expired
This commit is contained in:
@@ -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
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
) {
|
) {
|
||||||
|
|||||||
+2
-2
@@ -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,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",
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export 'package:universal_html/src/html.dart';
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export 'html_io.dart' if (dart.library.html) 'html_web.dart';
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export 'package:universal_html/html.dart';
|
||||||
+22
-22
@@ -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);
|
||||||
Reference in New Issue
Block a user