Skip to content

Commit

Permalink
TF-2928 Use default browser confirm dialog when token expired
Browse files Browse the repository at this point in the history
  • Loading branch information
dab246 authored and hoangdat committed Jul 17, 2024
1 parent 45e4cfa commit 30c1d80
Show file tree
Hide file tree
Showing 15 changed files with 192 additions and 141 deletions.
60 changes: 60 additions & 0 deletions core/lib/presentation/views/dialog/confirm_dialog_button.dart
Original file line number Diff line number Diff line change
@@ -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
)
),
),
),
);
}
}
88 changes: 31 additions & 57 deletions core/lib/presentation/views/dialog/confirmation_dialog_builder.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

import 'package:core/core.dart';
import 'package:core/presentation/views/dialog/confirm_dialog_button.dart';
import 'package:flutter/material.dart';

typedef OnConfirmButtonAction = void Function();
Expand Down Expand Up @@ -237,22 +238,26 @@ class ConfirmDialogBuilder {
if (_cancelText.isNotEmpty)
Padding(
padding: const EdgeInsetsDirectional.only(top: 8, start: 16, end: 16),
child: _buildButton(
name: _cancelText,
bgColor: _colorCancelButton,
radius: _radiusButton,
child: ConfirmDialogButton(
label: _cancelText,
backgroundColor: _colorCancelButton,
borderRadius: _radiusButton,
textStyle: _styleTextCancelButton,
action: _onCancelButtonAction),
padding: _paddingButton,
maxLines: titleActionButtonMaxLines,
onTapAction: _onCancelButtonAction),
),
if (_confirmText.isNotEmpty)
Padding(
padding: const EdgeInsetsDirectional.only(top: 8, start: 16, end: 16),
child: _buildButton(
name: _confirmText,
bgColor: _colorConfirmButton,
radius: _radiusButton,
child: ConfirmDialogButton(
label: _confirmText,
backgroundColor: _colorConfirmButton,
borderRadius: _radiusButton,
textStyle: _styleTextConfirmButton,
action: _onConfirmButtonAction),
padding: _paddingButton,
maxLines: titleActionButtonMaxLines,
onTapAction: _onConfirmButtonAction),
),
const SizedBox(height: 16),
]
Expand All @@ -262,59 +267,28 @@ class ConfirmDialogBuilder {
child: Row(
children: [
if (_cancelText.isNotEmpty)
Expanded(child: _buildButton(
name: _cancelText,
bgColor: _colorCancelButton,
radius: _radiusButton,
textStyle: _styleTextCancelButton,
action: _onCancelButtonAction)),
Expanded(child: ConfirmDialogButton(
label: _cancelText,
backgroundColor: _colorCancelButton,
borderRadius: _radiusButton,
textStyle: _styleTextCancelButton,
padding: _paddingButton,
maxLines: titleActionButtonMaxLines,
onTapAction: _onCancelButtonAction)),
if (_confirmText.isNotEmpty && _cancelText.isNotEmpty) const SizedBox(width: 8),
if (_confirmText.isNotEmpty)
Expanded(child: _buildButton(
name: _confirmText,
bgColor: _colorConfirmButton,
radius: _radiusButton,
textStyle: _styleTextConfirmButton,
action: _onConfirmButtonAction))
Expanded(child: ConfirmDialogButton(
label: _confirmText,
backgroundColor: _colorConfirmButton,
borderRadius: _radiusButton,
textStyle: _styleTextConfirmButton,
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
)),
),
);
}
}
56 changes: 35 additions & 21 deletions lib/features/base/base_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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: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/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/popup_context_menu_action_mixin.dart';
import 'package:tmail_ui_user/features/caching/caching_manager.dart';
Expand Down Expand Up @@ -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/utils/app_config.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';

abstract class BaseController extends GetxController
Expand All @@ -90,8 +90,8 @@ abstract class BaseController extends GetxController
GetStoredFirebaseRegistrationInteractor? _getStoredFirebaseRegistrationInteractor;
DestroyFirebaseRegistrationInteractor? _destroyFirebaseRegistrationInteractor;

StreamSubscription<html.Event>? _subscriptionBrowserOnBeforeUnload;
StreamSubscription<html.Event>? _subscriptionBrowserOnUnload;
StreamSubscription<html.Event>? _onBeforeUnloadBrowserSubscription;
StreamSubscription<html.Event>? _onUnloadBrowserSubscription;

final viewState = Rx<Either<Failure, Success>>(Right(UIState.idle));
FpsCallback? fpsCallback;
Expand All @@ -105,21 +105,21 @@ abstract class BaseController extends GetxController
}

void _triggerBrowserReloadListener() {
_subscriptionBrowserOnBeforeUnload =
html.window.onBeforeUnload.listen(handleBrowserBeforeReloadAction);
_subscriptionBrowserOnUnload =
html.window.onUnload.listen(handleBrowserReloadAction);
_onBeforeUnloadBrowserSubscription =
html.window.onBeforeUnload.listen(onBeforeUnloadBrowserListener);
_onUnloadBrowserSubscription =
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
void onClose() {
if (PlatformInfo.isWeb) {
_subscriptionBrowserOnBeforeUnload?.cancel();
_subscriptionBrowserOnUnload?.cancel();
_onBeforeUnloadBrowserSubscription?.cancel();
_onUnloadBrowserSubscription?.cancel();
}
super.onClose();
}
Expand Down Expand Up @@ -204,8 +204,8 @@ abstract class BaseController extends GetxController
}
}

Future<void> _executeBeforeUnloadAndLogOut() async {
await executeBeforeUnload();
Future<void> _executeBeforeReconnectAndLogOut() async {
await executeBeforeReconnect();
clearDataAndGoToLoginPage();
}

Expand Down Expand Up @@ -234,7 +234,7 @@ abstract class BaseController extends GetxController
void _handleBadCredentialsException() {
if (PlatformInfo.isWeb) {
if (currentContext == null) {
_executeBeforeUnloadAndLogOut();
_executeBeforeReconnectAndLogOut();
return;
}

Expand All @@ -245,11 +245,25 @@ abstract class BaseController extends GetxController
title: AppLocalizations.of(currentContext!).sessionExpired,
alignCenter: true,
outsideDismissible: false,
titleActionButtonMaxLines: 1,
icon: SvgPicture.asset(imagePaths.icTMailLogo, width: 64, height: 64),
paddingButton: const EdgeInsets.symmetric(horizontal: 8, vertical: 16),
onConfirmAction: _executeBeforeUnloadAndLogOut);
onConfirmAction: _executeBeforeReconnectAndLogOut);
} 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);
}
}

Expand Down Expand Up @@ -413,9 +427,9 @@ abstract class BaseController extends GetxController
}
}

Future<void> executeBeforeUnload() async {
final beforeUnloadManager = getBinding<BeforeUnloadManager>();
await beforeUnloadManager?.executeBeforeUnloadListeners();
Future<void> executeBeforeReconnect() async {
final beforeReconnectManager = getBinding<BeforeReconnectManager>();
await beforeReconnectManager?.executeBeforeReconnectListeners();
}

Future<void> clearDataAndGoToLoginPage() async {
Expand Down
3 changes: 3 additions & 0 deletions lib/features/base/before_reconnect_handler.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
abstract class BeforeReconnectHandler {
Future<void> onBeforeReconnect();
}
24 changes: 24 additions & 0 deletions lib/features/base/before_reconnect_manager.dart
Original file line number Diff line number Diff line change
@@ -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())]);
}
}
3 changes: 0 additions & 3 deletions lib/features/base/before_unload_handler.dart

This file was deleted.

24 changes: 0 additions & 24 deletions lib/features/base/before_unload_manager.dart

This file was deleted.

Loading

0 comments on commit 30c1d80

Please sign in to comment.