diff --git a/assets/images/ic_page_not_found.svg b/assets/images/ic_page_not_found.svg new file mode 100644 index 000000000..ed8dffea3 --- /dev/null +++ b/assets/images/ic_page_not_found.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart index d6e315a2c..38864a6df 100644 --- a/core/lib/presentation/resources/image_paths.dart +++ b/core/lib/presentation/resources/image_paths.dart @@ -176,6 +176,7 @@ class ImagePaths { String get icQuotasWarning => _getImagePath('ic_quotas_warning.svg'); String get icQuotasOutOfStorage => _getImagePath('ic_quotas_out_of_storage.svg'); String get icQuickCreatingRule => _getImagePath('ic_quick_creating_rule.svg'); + String get icPageNotFound => _getImagePath('ic_page_not_found.svg'); String _getImagePath(String imageName) { return AssetsPaths.images + imageName; diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart index 80f2a9552..9ec590f7a 100644 --- a/lib/features/mailbox/presentation/mailbox_controller.dart +++ b/lib/features/mailbox/presentation/mailbox_controller.dart @@ -439,6 +439,7 @@ class MailboxController extends BaseMailboxController { _clearNavigationRouter(); } else { _clearNavigationRouter(); + pushAndPop(AppRoutes.unknownRoutePage); } } diff --git a/lib/features/thread/presentation/thread_controller.dart b/lib/features/thread/presentation/thread_controller.dart index 7457fd7fb..a632bb79a 100644 --- a/lib/features/thread/presentation/thread_controller.dart +++ b/lib/features/thread/presentation/thread_controller.dart @@ -160,6 +160,7 @@ class ThreadController extends BaseController with EmailActionController { } else if (failure is GetEmailByIdFailure) { openingEmail.value = false; _navigationRouter = null; + pushAndPop(AppRoutes.unknownRoutePage); } }, (success) { diff --git a/lib/features/thread/presentation/widgets/email_tile_web_builder.dart b/lib/features/thread/presentation/widgets/email_tile_web_builder.dart index 635927ed8..0ae23b2d3 100644 --- a/lib/features/thread/presentation/widgets/email_tile_web_builder.dart +++ b/lib/features/thread/presentation/widgets/email_tile_web_builder.dart @@ -11,7 +11,6 @@ import 'package:model/mailbox/select_mode.dart'; import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart'; import 'package:tmail_ui_user/features/thread/presentation/mixin/base_email_item_tile.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; -import 'package:url_launcher/link.dart'; class EmailTileBuilder with BaseEmailItemTile { @@ -82,10 +81,7 @@ class EmailTileBuilder with BaseEmailItemTile { padding: _getPaddingItem(), decoration: _getDecorationItem(), alignment: Alignment.center, - child: Link( - uri: _presentationEmail.routeWeb, - builder: (_, __) => tile - ) + child: tile ); } diff --git a/lib/features/unknown_route_page/unknown_route_page_view.dart b/lib/features/unknown_route_page/unknown_route_page_view.dart new file mode 100644 index 000000000..24930ea4f --- /dev/null +++ b/lib/features/unknown_route_page/unknown_route_page_view.dart @@ -0,0 +1,88 @@ +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:core/presentation/utils/responsive_utils.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +class UnknownRoutePageView extends StatelessWidget { + + static const double maxWidthTextDefault = 440.0; + + final _imagePath = Get.find(); + final _responsiveUtils = Get.find(); + + UnknownRoutePageView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + + return Scaffold( + backgroundColor: Colors.white, + body: Center( + child: SingleChildScrollView( + child: Column(mainAxisSize: MainAxisSize.min, children: [ + SvgPicture.asset(_imagePath.icPageNotFound), + const SizedBox(height: 48), + Container( + color: Colors.white, + padding: _getPaddingTitle(context), + constraints: BoxConstraints(maxWidth: _getMaxWidthTitle(context)), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + AppLocalizations.of(context).titlePageNotFound, + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.w500, + color: Colors.black, + fontSize: _getFontSizeTitle(context) + ), + ), + const SizedBox(height: 12), + Text( + AppLocalizations.of(context).subTitlePageNotFound, + textAlign: TextAlign.center, + style: const TextStyle( + fontWeight: FontWeight.w500, + color: AppColor.colorSettingExplanation, + fontSize: 16 + ), + ) + ] + ), + ), + const SizedBox(height: 48) + ]), + ), + ), + ); + } + + double _getMaxWidthTitle(BuildContext context) { + final widthScreen = _responsiveUtils.getSizeScreenWidth(context); + if (widthScreen > maxWidthTextDefault) { + return maxWidthTextDefault; + } else { + return widthScreen; + } + } + + EdgeInsets _getPaddingTitle(BuildContext context) { + if (_responsiveUtils.isPortraitMobile(context)) { + return const EdgeInsets.symmetric(horizontal: 30); + } else { + return EdgeInsets.zero; + } + } + + double _getFontSizeTitle(BuildContext context) { + if (_responsiveUtils.isPortraitMobile(context)) { + return 20.0; + } else { + return 24.0; + } + } +} \ No newline at end of file diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index c7e0e0cfc..ec1f66177 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2022-11-11T04:08:42.994169", + "@@last_modified": "2022-11-11T02:15:40.658946", "initializing_data": "Initializing data...", "@initializing_data": { "type": "text", @@ -2503,5 +2503,23 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "titlePageNotFound": "Oops, we can’t find that page", + "@titlePageNotFound": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, + "subTitlePageNotFound": "It is possible that your destination page has disappeared or belongs to another account.", + "@subTitlePageNotFound": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, + "page404": "Page 404", + "@page404": { + "type": "text", + "placeholders_order": [], + "placeholders": {} } } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index d9e101a42..6eeb9b775 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -57,7 +57,14 @@ class TMailApp extends StatelessWidget { locale: LocalizationService.locale, fallbackLocale: LocalizationService.fallbackLocale, translations: LocalizationService(), - onGenerateTitle: (context) => AppLocalizations.of(context).page_name, + onGenerateTitle: (context) { + if (Get.currentRoute == AppRoutes.unknownRoutePage) { + return AppLocalizations.of(context).page404; + } else { + return AppLocalizations.of(context).page_name; + } + }, + unknownRoute: AppPages.unknownRoutePage, defaultTransition: Transition.fade, initialRoute: AppRoutes.home, getPages: AppPages.pages); diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index bd0a60262..53f464af9 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -2569,4 +2569,22 @@ class AppLocalizations { 'Create a rule with this email', name: 'quickCreatingRule'); } + + String get titlePageNotFound { + return Intl.message( + 'Oops, we can’t find that page', + name: 'titlePageNotFound'); + } + + String get subTitlePageNotFound { + return Intl.message( + 'It is possible that your destination page has disappeared or belongs to another account.', + name: 'subTitlePageNotFound'); + } + + String get page404 { + return Intl.message( + 'Page 404', + name: 'page404'); + } } \ No newline at end of file diff --git a/lib/main/pages/app_pages.dart b/lib/main/pages/app_pages.dart index 6d80e9540..833e2657e 100644 --- a/lib/main/pages/app_pages.dart +++ b/lib/main/pages/app_pages.dart @@ -25,6 +25,7 @@ import 'package:tmail_ui_user/features/manage_account/presentation/manage_accoun import 'package:tmail_ui_user/features/manage_account/presentation/manage_account_dashboard_view.dart' deferred as manage_account_dashboard; import 'package:tmail_ui_user/features/session/presentation/session_page_bindings.dart'; import 'package:tmail_ui_user/features/session/presentation/session_view.dart' deferred as session; +import 'package:tmail_ui_user/features/unknown_route_page/unknown_route_page_view.dart'; import 'package:tmail_ui_user/main/pages/deferred_widget.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart'; @@ -60,6 +61,7 @@ class AppPages { manage_account_dashboard.loadLibrary, () => manage_account_dashboard.ManageAccountDashBoardView()), binding: ManageAccountDashBoardBindings()), + unknownRoutePage, if (!BuildUtils.isWeb) ...[ GetPage( @@ -106,4 +108,9 @@ class AppPages { binding: RulesFilterCreatorBindings()) ] ]; + + static final unknownRoutePage = GetPage( + name: AppRoutes.unknownRoutePage, + page: () => UnknownRoutePageView(), + ); } diff --git a/lib/main/routes/app_routes.dart b/lib/main/routes/app_routes.dart index f43846a5d..9c6bebc39 100644 --- a/lib/main/routes/app_routes.dart +++ b/lib/main/routes/app_routes.dart @@ -12,4 +12,5 @@ abstract class AppRoutes { static const identityCreator = '/identity_creator'; static const rulesFilterCreator = '/rules_filter_creator'; static const emailsForwardCreator = '/emails_forward_creator'; + static const unknownRoutePage = '/notfound'; } \ No newline at end of file