From d4eccbfe7393a049a66d59d1e32cd8ed3bc5ac91 Mon Sep 17 00:00:00 2001 From: Arif Ayduran Date: Wed, 29 Jan 2025 14:59:29 +0100 Subject: [PATCH] notfound --- .../deploy_firebase_and_github_on_push.yml | 2 +- devtools_options.yaml | 3 + lib/l10n/app_ar.arb | 5 +- lib/l10n/app_de.arb | 5 +- lib/l10n/app_en.arb | 21 +- lib/l10n/app_tr.arb | 8 +- .../core/application/responsive_update.dart | 18 +- lib/src/core/my_app.dart | 127 +++++----- lib/src/core/my_toolbar.dart | 10 +- .../home/presentation/home_screen.dart | 11 +- .../home/presentation/page_not_found.dart | 225 ++++++++++++++++++ .../presentation/projects_screen.dart | 51 +++- .../application/services/route_observer.dart | 16 ++ .../settings/data/session_settings.dart | 3 +- lib/src/presentation/svg/hover_logo.dart | 18 +- 15 files changed, 420 insertions(+), 103 deletions(-) create mode 100644 devtools_options.yaml create mode 100644 lib/src/features/home/presentation/page_not_found.dart diff --git a/.github/workflows/deploy_firebase_and_github_on_push.yml b/.github/workflows/deploy_firebase_and_github_on_push.yml index d582beb..a1e065b 100644 --- a/.github/workflows/deploy_firebase_and_github_on_push.yml +++ b/.github/workflows/deploy_firebase_and_github_on_push.yml @@ -17,7 +17,7 @@ jobs: - name: Set up Flutter uses: subosito/flutter-action@v2 with: - flutter-version: '3.27.2' # Optionally specify the version you need + flutter-version: '3.27.3' # Optionally specify the version you need # Step 3: Install Firebase CLI globally - name: Install Firebase CLI diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..fa0b357 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index 690a2e7..fbb425d 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -22,5 +22,8 @@ "onHoverSystemLang": "تُستخدم لغة النظام لمعالجة البيانات وتنسيقات العملات والإعدادات المحلية الأخرى.", "lastRouteMessage": "تمت استعادة جلسة الطريق الأخيرة بنجاح.", "drawerOnHover": "الوصول إلى قائمة الإعدادات.", - "logoOnHover": "شعار بخط اليد مصمم ذاتيًا" + "logoOnHover": "شعار بخط اليد مصمم ذاتيًا", + "goToHome": "اذهب إلى الصفحة الرئيسية", + "back": "رجوع", + "pageNotFound": "الصفحة '{path}' غير موجودة." } \ No newline at end of file diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 64acb7c..50f6145 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -22,5 +22,8 @@ "onHoverSystemLang": "Die Systemsprache wird verwendet, um Daten-, Währungsformate und andere lokale Einstellungen zu verwalten.", "lastRouteMessage":"Die letzte Routensitzung wurde erfolgreich wiederhergestellt.", "drawerOnHover": "Zugriff auf das Einstellungen-Menü.", - "logoOnHover": "Kalligraphisches, selbst gestaltetes Logo" + "logoOnHover": "Kalligraphisches, selbst gestaltetes Logo", + "goToHome": "Zur Startseite gehen", + "back": "Zurück", + "pageNotFound": "Die Seite '{path}' wurde nicht gefunden." } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index f6095d6..8090f5b 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -82,10 +82,25 @@ }, "drawerOnHover": "Access the settings menu.", "@drawerOnHover": { - "description": "Manage basic settings and adjustments." + "description": "Manage basic settings and adjustments." }, "logoOnHover": "Calligraphic self-designed logo", "@logoOnHover": { - "description": "Message shown on hover on logo" - } + "description": "Message shown on hover on logo" + }, + "goToHome": "Go to home", + "@goToHome": { + "description": "Navigation to home button text" + }, + "back": "Back", + "@back": { + "description": "Navigation back button text" + }, + "pageNotFound": "The page '{path}' was not found.", + "@pageNotFound": { + "description": "Page not found message to show", + "placeholders": { + "path": {} + } + } } \ No newline at end of file diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index e9eff15..9d36302 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -22,6 +22,8 @@ "onHoverSystemLang": "Sistem dili, veri, para birimi formatı ve diğer yerel ayarları işlemek için kullanılır.", "lastRouteMessage": "Son rota oturumu başarıyla geri yüklendi.", "drawerOnHover": "Ayarlar menüsüne erişim.", - "logoOnHover": "Kaligrafik, kendi tasarımımız olan logo" -} - \ No newline at end of file + "logoOnHover": "Kaligrafik, kendi tasarımımız olan logo", + "goToHome": "Ana sayfaya git", + "back": "Geri dön", + "pageNotFound": "'{path}' sayfası bulunamadı." +} \ No newline at end of file diff --git a/lib/src/core/application/responsive_update.dart b/lib/src/core/application/responsive_update.dart index c4ddbcc..96c0e8a 100644 --- a/lib/src/core/application/responsive_update.dart +++ b/lib/src/core/application/responsive_update.dart @@ -1,8 +1,7 @@ - -import 'package:arifayduran_dev/src/core/my_toolbar.dart'; +// import 'package:arifayduran_dev/src/core/my_toolbar.dart'; import 'package:arifayduran_dev/src/features/settings/data/session_settings.dart'; import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; +// import 'package:provider/provider.dart'; import 'package:responsive_framework/responsive_framework.dart'; // void initializeToolbarHeight(BuildContext context) { @@ -19,15 +18,18 @@ import 'package:responsive_framework/responsive_framework.dart'; void responsiveUpdate(BuildContext context) { // final double height = MediaQuery.of(context).size.height; - final toolbarProvider = Provider.of(context, listen: false); + + // final toolbarProvider = Provider.of(context, listen: false); // didtn used for now + // final bottombarProvider = // Provider.of(context, listen: false); if (ResponsiveBreakpoints.of(context).smallerThan("Big")) { - toolbarProvider.providersmaxBarsHeight = 60; - toolbarProvider.providersminBarsHeight = 40; - // bottombarProvider.providersMaxBottombarHeight = 60; - // bottombarProvider.providersMinBottombarHeight = 40; + // toolbarProvider.providersmaxBarsHeight = 60; + // toolbarProvider.providersminBarsHeight = 40; + + // bottombarProvider.providersMaxBottombarHeight = 60; // didtn used for now + // bottombarProvider.providersMinBottombarHeight = 40; // didtn used for now maxBarsHeight = 60; minBarsHeight = 40; } else { diff --git a/lib/src/core/my_app.dart b/lib/src/core/my_app.dart index 4a956ee..90b6933 100644 --- a/lib/src/core/my_app.dart +++ b/lib/src/core/my_app.dart @@ -1,5 +1,8 @@ +import 'dart:ui_web'; + import 'package:arifayduran_dev/src/core/application/scaffold_messenger_key.dart'; import 'package:arifayduran_dev/src/core/my_toolbar.dart'; +import 'package:arifayduran_dev/src/features/home/presentation/page_not_found.dart'; import 'package:arifayduran_dev/src/features/projects/presentation/projects_screen.dart'; import 'package:arifayduran_dev/src/features/settings/application/controllers/language_provider.dart'; // import 'package:arifayduran_dev/src/features/settings/application/services/deactivated/routes_service.dart'; // not using since observer @@ -28,7 +31,6 @@ class MyApp extends StatelessWidget { builder: (BuildContext context, Widget? child) { return MaterialApp( builder: (context, child) => ResponsiveBreakpoints.builder( - child: child!, breakpoints: [ const Breakpoint(start: 0, end: 300, name: "Small"), const Breakpoint(start: 301, end: 600, name: MOBILE), @@ -38,6 +40,7 @@ class MyApp extends StatelessWidget { // const Breakpoint(start: 801, end: 1920, name: DESKTOP), // const Breakpoint(start: 1921, end: double.infinity, name: '4K'), ], + child: child!, ), scrollBehavior: MyCustomScrollBehavior(), scaffoldMessengerKey: scaffoldMessengerKey, @@ -53,6 +56,7 @@ class MyApp extends StatelessWidget { themeMode: uiModeController.themeMode, initialRoute: initialRoute, // "/", navigatorObservers: [routeObserver], + onGenerateInitialRoutes: (initialRoute) { final Uri uri = Uri.parse(initialRoute); return [ @@ -89,10 +93,11 @@ class MyApp extends StatelessWidget { Route buildPage( {required String path, Map queryParams = const {}}) { return PageRouteBuilder( + // opaque: false, settings: RouteSettings( name: (path.startsWith('/') == false) ? '/$path' : path), - transitionDuration: const Duration(milliseconds: 500), - reverseTransitionDuration: const Duration(milliseconds: 500), + transitionDuration: Duration(milliseconds: routeDurationMs), + reverseTransitionDuration: Duration(milliseconds: routeDurationMs), pageBuilder: (context, animation, secondaryAnimation) { final toolbarProvider = Provider.of(context); // listen: false @@ -110,65 +115,67 @@ class MyApp extends StatelessWidget { // path != '/' && path.startsWith('/') ? path.substring(1) : path; return Scaffold( - backgroundColor: toolbarProvider.scrolledPlaceColor, - appBar: PreferredSize( - preferredSize: Size.fromHeight( - Provider.of(context).toolbarHeight), - child: Stack( - clipBehavior: Clip.none, - children: [ - myToolbar, - Positioned( - top: 0, - left: Directionality.of(context) == TextDirection.ltr - ? 0 - : null, - right: Directionality.of(context) == TextDirection.rtl - ? 0 - : null, - child: HoverLogo(isDark: uiModeController.darkModeSet), - ), - ], + backgroundColor: toolbarProvider.scrolledPlaceColor, + appBar: PreferredSize( + preferredSize: Size.fromHeight( + Provider.of(context).toolbarHeight), + child: Stack( + clipBehavior: Clip.none, + children: [ + myToolbar, + Positioned( + top: 0, + left: Directionality.of(context) == TextDirection.ltr + ? 0 + : null, + right: Directionality.of(context) == TextDirection.rtl + ? 0 + : null, + child: HoverLogo(isDark: uiModeController.darkModeSet), + ), + ], + ), ), - ), - // extendBody: true, - // bottomNavigationBar: - // MyBottombar(uiModeController: uiModeController), - body: - - // Stack( - // clipBehavior: Clip.none, - // children: [ - FadeTransition( - opacity: animation, - child: switch (pathName) { - '/' || - HomeScreen.routeName => - HomeScreen(uiModeController: uiModeController), - ProjectsScreen.routeName => - ProjectsScreen(uiModeController: uiModeController), - "/placeholder" => - - // const ResponsiveBreakpoints(breakpoints: [ - // Breakpoint(start: 0, end: 480, name: MOBILE), - // Breakpoint(start: 481, end: 1200, name: TABLET), - // Breakpoint(start: 1201, end: double.infinity, name: DESKTOP), - // ], child: - const Placeholder(), - // ), + // extendBody: true, + // bottomNavigationBar: + // MyBottombar(uiModeController: uiModeController), + body: - String() => - HomeScreen(uiModeController: uiModeController), - }), - // Positioned.fill( - // left: -634, - // child: CustomPaint( - // painter: VerticalLinePainter(), - // ), - // ), - // ], - // ), - ); + // Stack( + // clipBehavior: Clip.none, + // children: [ + FadeTransition( + opacity: animation, + child: switch (pathName) { + // '/' || + HomeScreen.routeName => + HomeScreen(uiModeController: uiModeController), + ProjectsScreen.routeName => + ProjectsScreen(uiModeController: uiModeController), + "/placeholder" => + + // const ResponsiveBreakpoints(breakpoints: [ + // Breakpoint(start: 0, end: 480, name: MOBILE), + // Breakpoint(start: 481, end: 1200, name: TABLET), + // Breakpoint(start: 1201, end: double.infinity, name: DESKTOP), + // ], child: + const Placeholder(), + // ), + + String() => PageNotFoundScreen( + uiModeController: uiModeController, + pathName: pathName, + ), + } + // Positioned.fill( + // left: -634, + // child: CustomPaint( + // painter: VerticalLinePainter(), + // ), + // ), + // ], + // ), + )); }); } } diff --git a/lib/src/core/my_toolbar.dart b/lib/src/core/my_toolbar.dart index a04e819..20195f3 100644 --- a/lib/src/core/my_toolbar.dart +++ b/lib/src/core/my_toolbar.dart @@ -37,12 +37,12 @@ import 'package:responsive_framework/responsive_framework.dart'; // } class ToolbarProvider extends ChangeNotifier { - double? providersmaxBarsHeight = maxBarsHeight; // didnt use for now - double? providersminBarsHeight = minBarsHeight; // didnt use for now + // double? providersmaxBarsHeight = maxBarsHeight; // didnt used for now + // double? providersminBarsHeight = minBarsHeight; // didnt used for now Color scrolledPlaceColor = effectColorDark; double toolbarHeight = maxBarsHeight; - Duration duration = Duration(milliseconds: toolbarAnimationDuration); + Duration duration = Duration(milliseconds: routeDurationMs); void updateToolbar(Color color, double height, Duration newDuration) { duration = newDuration; @@ -59,10 +59,10 @@ class MyToolbar extends StatefulWidget { final UiModeController uiModeController; @override - State createState() => _MyToolbarProvider(); + State createState() => _MyToolbarState(); } -class _MyToolbarProvider extends State +class _MyToolbarState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _heightAnimation; diff --git a/lib/src/features/home/presentation/home_screen.dart b/lib/src/features/home/presentation/home_screen.dart index fd01551..1d12631 100644 --- a/lib/src/features/home/presentation/home_screen.dart +++ b/lib/src/features/home/presentation/home_screen.dart @@ -292,7 +292,7 @@ class _HomeScreenState extends State onDoubleTap: _handleDoubleTap, child: InteractiveViewer( transformationController: _transformationController, - scaleEnabled: true, // issues + scaleEnabled: false, // issues minScale: 1, maxScale: 2, child: Material( @@ -410,16 +410,13 @@ class _HomeScreenState extends State onPressed: () { notNavigatedFromRefresh = true; - // ! logoAnimate = true; Future.delayed( Duration( - milliseconds: - toolbarAnimationDuration), + milliseconds: routeDurationMs), () { logoAnimate = false; }); - // ! _onRoute(); _updateToolbar( @@ -430,7 +427,7 @@ class _HomeScreenState extends State .lastToolbarScrolledPlaceColorLight, ProjectsScreen .lastToolbarHeightBeforePush, - toolbarAnimationDuration); + routeDurationMs); // _updateBottombar( // widget.uiModeController // .darkModeSet @@ -440,7 +437,7 @@ class _HomeScreenState extends State // .lastToolbarScrolledPlaceColorLight, // ProjectsScreen // .lastToolbarHeightBeforePush, - // toolbarAnimationDuration); + // routeDurationMs); Navigator.pushNamed( context, '/projects'); }, diff --git a/lib/src/features/home/presentation/page_not_found.dart b/lib/src/features/home/presentation/page_not_found.dart new file mode 100644 index 0000000..2851b16 --- /dev/null +++ b/lib/src/features/home/presentation/page_not_found.dart @@ -0,0 +1,225 @@ +import 'package:arifayduran_dev/src/config/theme.dart'; +import 'package:arifayduran_dev/src/core/my_toolbar.dart'; +import 'package:arifayduran_dev/src/features/home/presentation/home_screen.dart'; +import 'package:arifayduran_dev/src/features/settings/application/controllers/ui_mode_controller.dart'; +// import 'package:arifayduran_dev/src/features/settings/application/services/deactivated/routes_service.dart'; // not using since observer +import 'package:arifayduran_dev/src/features/settings/data/session_settings.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +class PageNotFoundScreen extends StatefulWidget { + const PageNotFoundScreen( + {super.key, required this.pathName, required this.uiModeController}); + + final UiModeController uiModeController; + static const routeName = '/page_not_found'; + final String pathName; + + static double lastToolbarHeightBeforePush = maxBarsHeight; + static Color lastToolbarScrolledPlaceColorDark = effectColorDark; + static Color lastToolbarScrolledPlaceColorLight = effectColorLight; + + @override + State createState() => _PageNotFoundScreenState(); +} + +class _PageNotFoundScreenState extends State { + late bool isBackOrGoHome; + + @override + void initState() { + super.initState(); + + isBackOrGoHome = notNavigatedFromRefresh; + + widget.uiModeController.addListener(() { + if (mounted) { + setState(() { + _updateToolbar( + widget.uiModeController.darkModeSet + ? effectColorDark + : effectColorLight, + maxBarsHeight, + 0); + // _updateBottombar( + // widget.uiModeController.darkModeSet + // ? effectColorDark + // : effectColorLight, + // maxBarsHeight, + // 0); + }); + } + }); + + WidgetsBinding.instance.addPostFrameCallback((_) { + loadedScreens["PageNotFoundScreen"] = true; + }); + } + + void _updateToolbar(Color color, double height, int ms) { + Provider.of(context, listen: false) + .updateToolbar(color, height, Duration(milliseconds: ms)); + } + + // void _updateBottombar(Color color, double height, int ms) { + // Provider.of(context, listen: false) + // .updateBottombar(color, height, Duration(milliseconds: ms)); + // } + + void _onRoute() { + // HomeScreen.lastToolbarHeightBeforePush = _getToolbarSize(); + // double opacity = (_scrollController.position.pixels / + // (MediaQuery.of(context).size.height - 50 - 200)) + // .clamp(0.0, 1.0); + + // HomeScreen.lastToolbarScrolledPlaceColorDark = + // Color.lerp(_effectColorDark, _destinationColorDark, opacity)!; + // HomeScreen.lastToolbarScrolledPlaceColorLight = + // Color.lerp(_effectColorLight, _destinationColorDark, opacity)!; + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + setState(() {}); + } + + @override + Widget build(BuildContext context) { + final double height = MediaQuery.of(context).size.height; + final double width = MediaQuery.of(context).size.width; + // final nameStyle = Theme.of(context).textTheme.displayMedium; + final descriptionStyle = Theme.of(context).textTheme.headlineMedium; + + return PopScope( + canPop: true, + onPopInvokedWithResult: (willPop, result) { + logoAnimate = true; + Future.delayed(Duration(milliseconds: routeDurationMs), () { + logoAnimate = false; + }); + + _onRoute(); + _updateToolbar( + widget.uiModeController.darkModeSet + ? HomeScreen.lastToolbarScrolledPlaceColorDark + : HomeScreen.lastToolbarScrolledPlaceColorLight, + HomeScreen.lastToolbarHeightBeforePush, + routeDurationMs); + // _updateBottombar( + // widget.uiModeController.darkModeSet + // ? HomeScreen.lastToolbarScrolledPlaceColorDark + // : HomeScreen.lastToolbarScrolledPlaceColorLight, + // HomeScreen.lastToolbarHeightBeforePush, + // routeDurationMs); + if (notNavigatedFromRefresh) { + willPop = false; + if (!Navigator.of(context).canPop()) { + return; + } + Navigator.pop(context); + } else {} + notNavigatedFromRefresh = false; + }, + child: SizedBox( + height: height, + width: width, + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // const AnimatedTextBody( + // text: "Testtextwasgeht", + // hoverColor: Colors.grey, + // initColor: Colors.white, + // maxSize: 50, + // midSize: 40, + // minSize: 30, + // fontWeight: FontWeight.w500, + // ), + // ), + Text( + AppLocalizations.of(context)! + .pageNotFound(widget.pathName), // arifayduran.dev... + style: descriptionStyle?.copyWith(), + ), + + const SizedBox( + height: 70, + ), + TextButton( + onPressed: () { + if (notNavigatedFromRefresh) { + // RouteService().updateLastVisitedRoute('/'); // not using since observer + + logoAnimate = true; + Future.delayed(Duration(milliseconds: routeDurationMs), () { + logoAnimate = false; + }); + + _onRoute(); + _updateToolbar( + widget.uiModeController.darkModeSet + ? HomeScreen.lastToolbarScrolledPlaceColorDark + : HomeScreen.lastToolbarScrolledPlaceColorLight, + HomeScreen.lastToolbarHeightBeforePush, + routeDurationMs); + // _updateBottombar( + // widget.uiModeController.darkModeSet + // ? HomeScreen.lastToolbarScrolledPlaceColorDark + // : HomeScreen.lastToolbarScrolledPlaceColorLight, + // HomeScreen.lastToolbarHeightBeforePush, + // routeDurationMs); + + if (!Navigator.of(context).canPop()) { + return; + } + + SchedulerBinding.instance.addPostFrameCallback((_) { + if (mounted && Navigator.canPop(context)) { + Navigator.pop(context); + } + }); + } else { + logoAnimate = true; + Future.delayed(Duration(milliseconds: routeDurationMs), () { + logoAnimate = false; + }); + + _onRoute(); + _updateToolbar( + widget.uiModeController.darkModeSet + ? HomeScreen.lastToolbarScrolledPlaceColorDark + : HomeScreen.lastToolbarScrolledPlaceColorLight, + HomeScreen.lastToolbarHeightBeforePush, + routeDurationMs); + // _updateBottombar( + // widget.uiModeController.darkModeSet + // ? HomeScreen.lastToolbarScrolledPlaceColorDark + // : HomeScreen.lastToolbarScrolledPlaceColorLight, + // HomeScreen.lastToolbarHeightBeforePush, + // routeDurationMs); + + Navigator.pushNamed(context, "/"); + } + notNavigatedFromRefresh = false; + }, + style: ButtonStyle( + backgroundColor: WidgetStatePropertyAll( + widget.uiModeController.darkModeSet ? mainRed : white)), + child: Text( + isBackOrGoHome + ? AppLocalizations.of(context)!.back + : AppLocalizations.of(context)!.goToHome, + style: descriptionStyle?.copyWith(), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/src/features/projects/presentation/projects_screen.dart b/lib/src/features/projects/presentation/projects_screen.dart index fce12f9..c2c33ac 100644 --- a/lib/src/features/projects/presentation/projects_screen.dart +++ b/lib/src/features/projects/presentation/projects_screen.dart @@ -8,7 +8,9 @@ import 'package:arifayduran_dev/src/features/settings/application/controllers/ui import 'package:arifayduran_dev/src/features/settings/data/session_settings.dart'; import 'package:arifayduran_dev/src/presentation/widgets/tooltip_and_selectable.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class ProjectsScreen extends StatefulWidget { const ProjectsScreen({super.key, required this.uiModeController}); @@ -26,10 +28,14 @@ class ProjectsScreen extends StatefulWidget { class _ProjectsScreenState extends State with AutomaticKeepAliveClientMixin { + late bool isBackOrGoHome; + @override void initState() { super.initState(); + isBackOrGoHome = notNavigatedFromRefresh; + widget.uiModeController.addListener(() { if (mounted) { setState(() { @@ -97,25 +103,30 @@ class _ProjectsScreenState extends State return PopScope( canPop: true, onPopInvokedWithResult: (willPop, result) { + logoAnimate = true; + Future.delayed(Duration(milliseconds: routeDurationMs), () { + logoAnimate = false; + }); + _onRoute(); _updateToolbar( widget.uiModeController.darkModeSet ? HomeScreen.lastToolbarScrolledPlaceColorDark : HomeScreen.lastToolbarScrolledPlaceColorLight, HomeScreen.lastToolbarHeightBeforePush, - toolbarAnimationDuration); + routeDurationMs); // _updateBottombar( // widget.uiModeController.darkModeSet // ? HomeScreen.lastToolbarScrolledPlaceColorDark // : HomeScreen.lastToolbarScrolledPlaceColorLight, // HomeScreen.lastToolbarHeightBeforePush, - // toolbarAnimationDuration); + // routeDurationMs); if (notNavigatedFromRefresh) { willPop = false; if (!Navigator.of(context).canPop()) { return; } - Navigator.pop(context, "/"); + Navigator.pop(context); } else {} notNavigatedFromRefresh = false; }, @@ -158,43 +169,63 @@ class _ProjectsScreenState extends State if (notNavigatedFromRefresh) { // RouteService().updateLastVisitedRoute('/'); // not using since observer + logoAnimate = true; + Future.delayed(Duration(milliseconds: routeDurationMs), () { + logoAnimate = false; + }); + _onRoute(); _updateToolbar( widget.uiModeController.darkModeSet ? HomeScreen.lastToolbarScrolledPlaceColorDark : HomeScreen.lastToolbarScrolledPlaceColorLight, HomeScreen.lastToolbarHeightBeforePush, - toolbarAnimationDuration); + routeDurationMs); // _updateBottombar( // widget.uiModeController.darkModeSet // ? HomeScreen.lastToolbarScrolledPlaceColorDark // : HomeScreen.lastToolbarScrolledPlaceColorLight, // HomeScreen.lastToolbarHeightBeforePush, - // toolbarAnimationDuration); + // routeDurationMs); + if (!Navigator.of(context).canPop()) { return; } - Navigator.pop(context, "/"); + + SchedulerBinding.instance.addPostFrameCallback((_) { + if (mounted && Navigator.canPop(context)) { + Navigator.pop(context); + } + }); } else { + logoAnimate = true; + Future.delayed(Duration(milliseconds: routeDurationMs), () { + logoAnimate = false; + }); + _onRoute(); _updateToolbar( widget.uiModeController.darkModeSet ? HomeScreen.lastToolbarScrolledPlaceColorDark : HomeScreen.lastToolbarScrolledPlaceColorLight, HomeScreen.lastToolbarHeightBeforePush, - toolbarAnimationDuration); + routeDurationMs); // _updateBottombar( // widget.uiModeController.darkModeSet // ? HomeScreen.lastToolbarScrolledPlaceColorDark // : HomeScreen.lastToolbarScrolledPlaceColorLight, // HomeScreen.lastToolbarHeightBeforePush, - // toolbarAnimationDuration); + // routeDurationMs); + Navigator.pushNamed(context, "/"); } - notNavigatedFromRefresh = false; + notNavigatedFromRefresh = + false; }, child: Text( - "Zurück", + isBackOrGoHome + ? AppLocalizations.of(context)!.back + : AppLocalizations.of(context)!.goToHome, style: descriptionStyle?.copyWith(), ), ), diff --git a/lib/src/features/settings/application/services/route_observer.dart b/lib/src/features/settings/application/services/route_observer.dart index ba23042..24921e0 100644 --- a/lib/src/features/settings/application/services/route_observer.dart +++ b/lib/src/features/settings/application/services/route_observer.dart @@ -9,17 +9,33 @@ class RouteObserverService extends RouteObserver { @override void didPush(Route route, Route? previousRoute) { super.didPush(route, previousRoute); + debugPrint( + 'PUSH: ${route.settings.name} (von ${previousRoute?.settings.name})'); _saveRoute(route.settings.name ?? '/'); } @override void didPop(Route route, Route? previousRoute) { super.didPop(route, previousRoute); + debugPrint( + 'POP: ${route.settings.name} (zurück zu ${previousRoute?.settings.name})'); if (previousRoute != null) { _saveRoute(previousRoute.settings.name ?? '/'); } } + @override + void didRemove(Route route, Route? previousRoute) { + debugPrint( + 'REMOVE: ${route.settings.name} (vorher war ${previousRoute?.settings.name})'); + } + + @override + void didReplace({Route? newRoute, Route? oldRoute}) { + debugPrint( + 'REPLACE: ${oldRoute?.settings.name} → ${newRoute?.settings.name}'); + } + void _saveRoute(String route) async { routeHistory.add(route); if (isPlatformWeb) { diff --git a/lib/src/features/settings/data/session_settings.dart b/lib/src/features/settings/data/session_settings.dart index 95cf6ef..bd2885e 100644 --- a/lib/src/features/settings/data/session_settings.dart +++ b/lib/src/features/settings/data/session_settings.dart @@ -37,7 +37,7 @@ RouteObserverService routeObserver = RouteObserverService(); List? routeHistory; String? initialRoute; -int toolbarAnimationDuration = 1000; +int routeDurationMs = 700; late MyToolbar myToolbar; // late MyBottombar myBottombar; @@ -50,4 +50,5 @@ double logoSpace = 0; Map loadedScreens = { "HomeScreen": false, "ProjectsScreen": false, + "PageNotFoundScreen": false, }; diff --git a/lib/src/presentation/svg/hover_logo.dart b/lib/src/presentation/svg/hover_logo.dart index 5dcebf6..c9e08d6 100644 --- a/lib/src/presentation/svg/hover_logo.dart +++ b/lib/src/presentation/svg/hover_logo.dart @@ -5,6 +5,7 @@ import 'package:arifayduran_dev/src/presentation/svg/svg_color_mapper.dart'; import 'package:arifayduran_dev/src/presentation/svg/svg_shadow_painter_oval.dart'; import 'package:arifayduran_dev/src/presentation/widgets/tooltip_and_selectable.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; import 'package:flutter_svg/svg.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; @@ -44,7 +45,7 @@ class _HoverLogoState extends State { @override Widget build(BuildContext context) { - final toolbarHeight = Provider.of(context).toolbarHeight; + double toolbarHeight = Provider.of(context).toolbarHeight; logoSpace = toolbarHeight * 1.8 * 1.3454258675 * _widthFactor; return MouseRegion( @@ -62,7 +63,18 @@ class _HoverLogoState extends State { _deactivateHover(); }, onTap: () { - Navigator.pushNamed(context, "/"); + if (ModalRoute.of(context)?.settings.name != '/') { + if (notNavigatedFromRefresh) { + SchedulerBinding.instance.addPostFrameCallback((_) { + if (mounted && Navigator.canPop(context)) { + Navigator.popUntil(context, ModalRoute.withName('/')); + } + }); + } else { + Navigator.pushNamed(context, "/"); + } + notNavigatedFromRefresh = false; + } }, child: TooltipAndSelectable( isSelectable: false, @@ -71,7 +83,7 @@ class _HoverLogoState extends State { child: AnimatedContainer( duration: Duration( milliseconds: logoAnimate - ? toolbarAnimationDuration + ? routeDurationMs : isHovered ? 300 : 0),