LCOV - code coverage report
Current view: top level - src - navigation_2_helpers.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 19 57 33.3 %
Date: 2021-04-29 14:25:52 Functions: 0 0 -

          Line data    Source code
       1             : part of 'main.dart';
       2             : 
       3             : /// A helper to create a material app
       4             : /// DO NOT use this on top of a VRouter, this will break the navigation
       5             : /// instead use VRouter as the topmost MaterialApp
       6             : /// DO use this in your widget instead of the traditional [MaterialApp]
       7             : /// Note that if you ever use [MaterialApp] instead of [VMaterialApp],
       8             : /// you risk breaking the entire navigation system.
       9             : class VMaterialApp<T extends Object> extends StatelessWidget {
      10             :   final Widget child;
      11             : 
      12           0 :   const VMaterialApp({
      13             :     Key? key,
      14             :     required this.child,
      15             :     this.backButtonDispatcher,
      16             :     this.builder,
      17             :     this.title = '',
      18             :     this.onGenerateTitle,
      19             :     this.color,
      20             :     this.theme,
      21             :     this.darkTheme,
      22             :     this.highContrastTheme,
      23             :     this.highContrastDarkTheme,
      24             :     this.themeMode = ThemeMode.system,
      25             :     this.locale,
      26             :     this.localizationsDelegates,
      27             :     this.localeListResolutionCallback,
      28             :     this.localeResolutionCallback,
      29             :     this.supportedLocales = const <Locale>[Locale('en', 'US')],
      30             :     this.debugShowMaterialGrid = false,
      31             :     this.showPerformanceOverlay = false,
      32             :     this.checkerboardRasterCacheImages = false,
      33             :     this.checkerboardOffscreenLayers = false,
      34             :     this.showSemanticsDebugger = false,
      35             :     this.debugShowCheckedModeBanner = true,
      36             :     this.shortcuts,
      37             :     this.actions,
      38           0 :   }) : super(key: key);
      39             : 
      40           0 :   @override
      41             :   Widget build(BuildContext context) {
      42           0 :     return MaterialApp.router(
      43           0 :       routerDelegate: VRouterDelegateHelper<T>(child: child),
      44           0 :       routeInformationParser: VRouteInformationParser(),
      45           0 :       backButtonDispatcher: backButtonDispatcher,
      46           0 :       builder: builder,
      47           0 :       title: title ?? '',
      48           0 :       onGenerateTitle: onGenerateTitle,
      49           0 :       color: color,
      50           0 :       theme: theme,
      51           0 :       darkTheme: darkTheme,
      52           0 :       highContrastTheme: highContrastTheme,
      53           0 :       highContrastDarkTheme: highContrastDarkTheme,
      54           0 :       themeMode: themeMode,
      55           0 :       locale: locale,
      56           0 :       localizationsDelegates: localizationsDelegates,
      57           0 :       localeListResolutionCallback: localeListResolutionCallback,
      58           0 :       localeResolutionCallback: localeResolutionCallback,
      59           0 :       supportedLocales: supportedLocales ?? const <Locale>[Locale('en', 'US')],
      60           0 :       debugShowMaterialGrid: debugShowMaterialGrid ?? false,
      61           0 :       showPerformanceOverlay: showPerformanceOverlay ?? false,
      62           0 :       checkerboardRasterCacheImages: checkerboardRasterCacheImages ?? false,
      63           0 :       checkerboardOffscreenLayers: checkerboardOffscreenLayers ?? false,
      64           0 :       showSemanticsDebugger: showSemanticsDebugger ?? false,
      65           0 :       debugShowCheckedModeBanner: debugShowCheckedModeBanner ?? true,
      66           0 :       shortcuts: shortcuts,
      67           0 :       actions: actions,
      68             :     );
      69             :   }
      70             : 
      71             :   /// {@macro flutter.widgets.widgetsApp.backButtonDispatcher}
      72             :   final BackButtonDispatcher? backButtonDispatcher;
      73             : 
      74             :   /// {@macro flutter.widgets.widgetsApp.builder}
      75             :   ///
      76             :   /// Material specific features such as [showDialog] and [showMenu], and widgets
      77             :   /// such as [Tooltip], [PopupMenuButton], also require a [Navigator] to properly
      78             :   /// function.
      79             :   final TransitionBuilder? builder;
      80             : 
      81             :   /// {@macro flutter.widgets.widgetsApp.title}
      82             :   ///
      83             :   /// This value is passed unmodified to [WidgetsApp.title].
      84             :   final String? title;
      85             : 
      86             :   /// {@macro flutter.widgets.widgetsApp.onGenerateTitle}
      87             :   ///
      88             :   /// This value is passed unmodified to [WidgetsApp.onGenerateTitle].
      89             :   final GenerateAppTitle? onGenerateTitle;
      90             : 
      91             :   /// Default visual properties, like colors fonts and shapes, for this app's
      92             :   /// material widgets.
      93             :   ///
      94             :   /// A second [darkTheme] [ThemeData] value, which is used to provide a dark
      95             :   /// version of the user interface can also be specified. [themeMode] will
      96             :   /// control which theme will be used if a [darkTheme] is provided.
      97             :   ///
      98             :   /// The default value of this property is the value of [ThemeData.light()].
      99             :   ///
     100             :   /// See also:
     101             :   ///
     102             :   ///  * [themeMode], which controls which theme to use.
     103             :   ///  * [MediaQueryData.platformBrightness], which indicates the platform's
     104             :   ///    desired brightness and is used to automatically toggle between [theme]
     105             :   ///    and [darkTheme] in [MaterialApp].
     106             :   ///  * [ThemeData.brightness], which indicates the [Brightness] of a theme's
     107             :   ///    colors.
     108             :   final ThemeData? theme;
     109             : 
     110             :   /// The [ThemeData] to use when a 'dark mode' is requested by the system.
     111             :   ///
     112             :   /// Some host platforms allow the users to select a system-wide 'dark mode',
     113             :   /// or the application may want to offer the user the ability to choose a
     114             :   /// dark theme just for this application. This is theme that will be used for
     115             :   /// such cases. [themeMode] will control which theme will be used.
     116             :   ///
     117             :   /// This theme should have a [ThemeData.brightness] set to [Brightness.dark].
     118             :   ///
     119             :   /// Uses [theme] instead when null. Defaults to the value of
     120             :   /// [ThemeData.light()] when both [darkTheme] and [theme] are null.
     121             :   ///
     122             :   /// See also:
     123             :   ///
     124             :   ///  * [themeMode], which controls which theme to use.
     125             :   ///  * [MediaQueryData.platformBrightness], which indicates the platform's
     126             :   ///    desired brightness and is used to automatically toggle between [theme]
     127             :   ///    and [darkTheme] in [MaterialApp].
     128             :   ///  * [ThemeData.brightness], which is typically set to the value of
     129             :   ///    [MediaQueryData.platformBrightness].
     130             :   final ThemeData? darkTheme;
     131             : 
     132             :   /// The [ThemeData] to use when 'high contrast' is requested by the system.
     133             :   ///
     134             :   /// Some host platforms (for example, iOS) allow the users to increase
     135             :   /// contrast through an accessibility setting.
     136             :   ///
     137             :   /// Uses [theme] instead when null.
     138             :   ///
     139             :   /// See also:
     140             :   ///
     141             :   ///  * [MediaQueryData.highContrast], which indicates the platform's
     142             :   ///    desire to increase contrast.
     143             :   final ThemeData? highContrastTheme;
     144             : 
     145             :   /// The [ThemeData] to use when a 'dark mode' and 'high contrast' is requested
     146             :   /// by the system.
     147             :   ///
     148             :   /// Some host platforms (for example, iOS) allow the users to increase
     149             :   /// contrast through an accessibility setting.
     150             :   ///
     151             :   /// This theme should have a [ThemeData.brightness] set to [Brightness.dark].
     152             :   ///
     153             :   /// Uses [darkTheme] instead when null.
     154             :   ///
     155             :   /// See also:
     156             :   ///
     157             :   ///  * [MediaQueryData.highContrast], which indicates the platform's
     158             :   ///    desire to increase contrast.
     159             :   final ThemeData? highContrastDarkTheme;
     160             : 
     161             :   /// Determines which theme will be used by the application if both [theme]
     162             :   /// and [darkTheme] are provided.
     163             :   ///
     164             :   /// If set to [ThemeMode.system], the choice of which theme to use will
     165             :   /// be based on the user's system preferences. If the [MediaQuery.platformBrightnessOf]
     166             :   /// is [Brightness.light], [theme] will be used. If it is [Brightness.dark],
     167             :   /// [darkTheme] will be used (unless it is null, in which case [theme]
     168             :   /// will be used.
     169             :   ///
     170             :   /// If set to [ThemeMode.light] the [theme] will always be used,
     171             :   /// regardless of the user's system preference.
     172             :   ///
     173             :   /// If set to [ThemeMode.dark] the [darkTheme] will be used
     174             :   /// regardless of the user's system preference. If [darkTheme] is null
     175             :   /// then it will fallback to using [theme].
     176             :   ///
     177             :   /// The default value is [ThemeMode.system].
     178             :   ///
     179             :   /// See also:
     180             :   ///
     181             :   ///  * [theme], which is used when a light mode is selected.
     182             :   ///  * [darkTheme], which is used when a dark mode is selected.
     183             :   ///  * [ThemeData.brightness], which indicates to various parts of the
     184             :   ///    system what kind of theme is being used.
     185             :   final ThemeMode? themeMode;
     186             : 
     187             :   /// {@macro flutter.widgets.widgetsApp.color}
     188             :   final Color? color;
     189             : 
     190             :   /// {@macro flutter.widgets.widgetsApp.locale}
     191             :   final Locale? locale;
     192             : 
     193             :   /// {@macro flutter.widgets.widgetsApp.localizationsDelegates}
     194             :   ///
     195             :   /// Internationalized apps that require translations for one of the locales
     196             :   /// listed in [GlobalMaterialLocalizations] should specify this parameter
     197             :   /// and list the [supportedLocales] that the application can handle.
     198             :   ///
     199             :   /// ```dart
     200             :   /// import 'package:flutter_localizations/flutter_localizations.dart';
     201             :   /// MaterialApp(
     202             :   ///   localizationsDelegates: [
     203             :   ///     // ... app-specific localization delegate[s] here
     204             :   ///     GlobalMaterialLocalizations.delegate,
     205             :   ///     GlobalWidgetsLocalizations.delegate,
     206             :   ///   ],
     207             :   ///   supportedLocales: [
     208             :   ///     const Locale('en', 'US'), // English
     209             :   ///     const Locale('he', 'IL'), // Hebrew
     210             :   ///     // ... other locales the app supports
     211             :   ///   ],
     212             :   ///   // ...
     213             :   /// )
     214             :   /// ```
     215             :   ///
     216             :   /// ## Adding localizations for a new locale
     217             :   ///
     218             :   /// The information that follows applies to the unusual case of an app
     219             :   /// adding translations for a language not already supported by
     220             :   /// [GlobalMaterialLocalizations].
     221             :   ///
     222             :   /// Delegates that produce [WidgetsLocalizations] and [MaterialLocalizations]
     223             :   /// are included automatically. Apps can provide their own versions of these
     224             :   /// localizations by creating implementations of
     225             :   /// [LocalizationsDelegate<WidgetsLocalizations>] or
     226             :   /// [LocalizationsDelegate<MaterialLocalizations>] whose load methods return
     227             :   /// custom versions of [WidgetsLocalizations] or [MaterialLocalizations].
     228             :   ///
     229             :   /// For example: to add support to [MaterialLocalizations] for a
     230             :   /// locale it doesn't already support, say `const Locale('foo', 'BR')`,
     231             :   /// one could just extend [DefaultMaterialLocalizations]:
     232             :   ///
     233             :   /// ```dart
     234             :   /// class FooLocalizations extends DefaultMaterialLocalizations {
     235             :   ///   FooLocalizations(Locale locale) : super(locale);
     236             :   ///   @override
     237             :   ///   String get okButtonLabel {
     238             :   ///     if (locale == const Locale('foo', 'BR'))
     239             :   ///       return 'foo';
     240             :   ///     return super.okButtonLabel;
     241             :   ///   }
     242             :   /// }
     243             :   ///
     244             :   /// ```
     245             :   ///
     246             :   /// A `FooLocalizationsDelegate` is essentially just a method that constructs
     247             :   /// a `FooLocalizations` object. We return a [SynchronousFuture] here because
     248             :   /// no asynchronous work takes place upon "loading" the localizations object.
     249             :   ///
     250             :   /// ```dart
     251             :   /// class FooLocalizationsDelegate extends LocalizationsDelegate<MaterialLocalizations> {
     252             :   ///   const FooLocalizationsDelegate();
     253             :   ///   @override
     254             :   ///   Future<FooLocalizations> load(Locale locale) {
     255             :   ///     return SynchronousFuture(FooLocalizations(locale));
     256             :   ///   }
     257             :   ///   @override
     258             :   ///   bool shouldReload(FooLocalizationsDelegate old) => false;
     259             :   /// }
     260             :   /// ```
     261             :   ///
     262             :   /// Constructing a [MaterialApp] with a `FooLocalizationsDelegate` overrides
     263             :   /// the automatically included delegate for [MaterialLocalizations] because
     264             :   /// only the first delegate of each [LocalizationsDelegate.type] is used and
     265             :   /// the automatically included delegates are added to the end of the app's
     266             :   /// [localizationsDelegates] list.
     267             :   ///
     268             :   /// ```dart
     269             :   /// MaterialApp(
     270             :   ///   localizationsDelegates: [
     271             :   ///     const FooLocalizationsDelegate(),
     272             :   ///   ],
     273             :   ///   // ...
     274             :   /// )
     275             :   /// ```
     276             :   /// See also:
     277             :   ///
     278             :   ///  * [supportedLocales], which must be specified along with
     279             :   ///    [localizationsDelegates].
     280             :   ///  * [GlobalMaterialLocalizations], a [localizationsDelegates] value
     281             :   ///    which provides material localizations for many languages.
     282             :   ///  * The Flutter Internationalization Tutorial,
     283             :   ///    <https://flutter.dev/tutorials/internationalization/>.
     284             :   final Iterable<LocalizationsDelegate<dynamic>>? localizationsDelegates;
     285             : 
     286             :   /// {@macro flutter.widgets.widgetsApp.localeListResolutionCallback}
     287             :   ///
     288             :   /// This callback is passed along to the [WidgetsApp] built by this widget.
     289             :   final LocaleListResolutionCallback? localeListResolutionCallback;
     290             : 
     291             :   /// {@macro flutter.widgets.LocaleResolutionCallback}
     292             :   ///
     293             :   /// This callback is passed along to the [WidgetsApp] built by this widget.
     294             :   final LocaleResolutionCallback? localeResolutionCallback;
     295             : 
     296             :   /// {@macro flutter.widgets.widgetsApp.supportedLocales}
     297             :   ///
     298             :   /// It is passed along unmodified to the [WidgetsApp] built by this widget.
     299             :   ///
     300             :   /// See also:
     301             :   ///
     302             :   ///  * [localizationsDelegates], which must be specified for localized
     303             :   ///    applications.
     304             :   ///  * [GlobalMaterialLocalizations], a [localizationsDelegates] value
     305             :   ///    which provides material localizations for many languages.
     306             :   ///  * The Flutter Internationalization Tutorial,
     307             :   ///    <https://flutter.dev/tutorials/internationalization/>.
     308             :   final Iterable<Locale>? supportedLocales;
     309             : 
     310             :   /// Turns on a performance overlay.
     311             :   ///
     312             :   /// See also:
     313             :   ///
     314             :   ///  * <https://flutter.dev/debugging/#performanceoverlay>
     315             :   final bool? showPerformanceOverlay;
     316             : 
     317             :   /// Turns on checkerboarding of raster cache images.
     318             :   final bool? checkerboardRasterCacheImages;
     319             : 
     320             :   /// Turns on checkerboarding of layers rendered to offscreen bitmaps.
     321             :   final bool? checkerboardOffscreenLayers;
     322             : 
     323             :   /// Turns on an overlay that shows the accessibility information
     324             :   /// reported by the framework.
     325             :   final bool? showSemanticsDebugger;
     326             : 
     327             :   /// {@macro flutter.widgets.widgetsApp.debugShowCheckedModeBanner}
     328             :   final bool? debugShowCheckedModeBanner;
     329             : 
     330             :   /// {@macro flutter.widgets.widgetsApp.shortcuts}
     331             :   /// {@tool snippet}
     332             :   /// This example shows how to add a single shortcut for
     333             :   /// [LogicalKeyboardKey.select] to the default shortcuts without needing to
     334             :   /// add your own [Shortcuts] widget.
     335             :   ///
     336             :   /// Alternatively, you could insert a [Shortcuts] widget with just the mapping
     337             :   /// you want to add between the [WidgetsApp] and its child and get the same
     338             :   /// effect.
     339             :   ///
     340             :   /// ```dart
     341             :   /// Widget build(BuildContext context) {
     342             :   ///   return WidgetsApp(
     343             :   ///     shortcuts: <LogicalKeySet, Intent>{
     344             :   ///       ... WidgetsApp.defaultShortcuts,
     345             :   ///       LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(),
     346             :   ///     },
     347             :   ///     color: const Color(0xFFFF0000),
     348             :   ///     builder: (BuildContext context, Widget child) {
     349             :   ///       return const Placeholder();
     350             :   ///     },
     351             :   ///   );
     352             :   /// }
     353             :   /// ```
     354             :   /// {@end-tool}
     355             :   /// {@macro flutter.widgets.widgetsApp.shortcuts.seeAlso}
     356             :   final Map<LogicalKeySet, Intent>? shortcuts;
     357             : 
     358             :   /// {@macro flutter.widgets.widgetsApp.actions}
     359             :   /// {@tool snippet}
     360             :   /// This example shows how to add a single action handling an
     361             :   /// [ActivateAction] to the default actions without needing to
     362             :   /// add your own [Actions] widget.
     363             :   ///
     364             :   /// Alternatively, you could insert a [Actions] widget with just the mapping
     365             :   /// you want to add between the [WidgetsApp] and its child and get the same
     366             :   /// effect.
     367             :   ///
     368             :   /// ```dart
     369             :   /// Widget build(BuildContext context) {
     370             :   ///   return WidgetsApp(
     371             :   ///     actions: <Type, Action<Intent>>{
     372             :   ///       ... WidgetsApp.defaultActions,
     373             :   ///       ActivateAction: CallbackAction(
     374             :   ///         onInvoke: (Intent intent) {
     375             :   ///           // Do something here...
     376             :   ///           return null;
     377             :   ///         },
     378             :   ///       ),
     379             :   ///     },
     380             :   ///     color: const Color(0xFFFF0000),
     381             :   ///     builder: (BuildContext context, Widget child) {
     382             :   ///       return const Placeholder();
     383             :   ///     },
     384             :   ///   );
     385             :   /// }
     386             :   /// ```
     387             :   /// {@end-tool}
     388             :   /// {@macro flutter.widgets.widgetsApp.actions.seeAlso}
     389             :   final Map<Type, Action<Intent>>? actions;
     390             : 
     391             :   /// Turns on a [GridPaper] overlay that paints a baseline grid
     392             :   /// Material apps.
     393             :   ///
     394             :   /// Only available in checked mode.
     395             :   ///
     396             :   /// See also:
     397             :   ///
     398             :   ///  * <https://material.io/design/layout/spacing-methods.html>
     399             :   final bool? debugShowMaterialGrid;
     400             : }
     401             : 
     402             : /// This is a helper to create a router in which we nest
     403             : /// a [VRouterDelegateHelper]
     404             : class VRouterHelper extends StatelessWidget {
     405             :   /// The pages that will be displayed in the [VRouterDelegateHelper]
     406             :   /// Navigator
     407             :   final List<Page> pages;
     408             : 
     409             :   /// The key of the [VRouterDelegateHelper] navigator
     410             :   final GlobalKey<NavigatorState>? navigatorKey;
     411             : 
     412             :   /// The observers of the [VRouterDelegateHelper] navigator
     413             :   final List<NavigatorObserver>? observers;
     414             : 
     415             :   /// The [BackButtonDispatcher] of the router
     416             :   final BackButtonDispatcher? backButtonDispatcher;
     417             : 
     418             :   /// The function that will be called when [Navigator.pop]
     419             :   /// is called in a page contained in this router
     420             :   final bool Function(Route<dynamic>, dynamic)? onPopPage;
     421             : 
     422             :   /// The function that will be called when a system pop
     423             :   /// (hardware back button in android) is called in a page
     424             :   /// contained in this router
     425             :   final Future<bool> Function()? onSystemPopPage;
     426             : 
     427           3 :   const VRouterHelper({
     428             :     Key? key,
     429             :     required this.pages,
     430             :     this.navigatorKey,
     431             :     this.observers,
     432             :     this.backButtonDispatcher,
     433             :     this.onPopPage,
     434             :     this.onSystemPopPage,
     435           3 :   }) : super(key: key);
     436             : 
     437           3 :   @override
     438             :   Widget build(BuildContext context) {
     439           3 :     return Router(
     440           3 :       backButtonDispatcher: backButtonDispatcher,
     441           3 :       routerDelegate: VRouterDelegateHelper(
     442           3 :         pages: pages,
     443           3 :         navigatorKey: navigatorKey,
     444           3 :         observers: observers,
     445           3 :         onPopPage: onPopPage,
     446           3 :         onSystemPopPage: onSystemPopPage,
     447             :       ),
     448             :     );
     449             :   }
     450             : }
     451             : 
     452             : /// A routerDelegate which automatically creates a Navigator
     453             : /// See the details of each attribute to see what they can be used for
     454             : class VRouterDelegateHelper<T extends Object> extends RouterDelegate<T>
     455             :     with ChangeNotifier {
     456             :   final GlobalKey<NavigatorState>? navigatorKey;
     457             :   final List<NavigatorObserver>? observers;
     458             :   final Widget? child;
     459             :   final List<Page>? pages;
     460             :   final bool Function(Route<dynamic>, dynamic)? onPopPage;
     461             :   final Future<bool> Function()? onSystemPopPage;
     462             : 
     463           3 :   VRouterDelegateHelper({
     464             :     this.child,
     465             :     this.pages,
     466             :     this.navigatorKey,
     467             :     this.observers,
     468             :     this.onPopPage,
     469             :     this.onSystemPopPage,
     470           0 :   }) : assert(pages != null || child != null);
     471             : 
     472           3 :   @override
     473             :   Widget build(BuildContext context) {
     474           3 :     if (pages != null) {
     475           3 :       return Navigator(
     476           3 :         key: navigatorKey,
     477           3 :         observers: observers ?? [],
     478           3 :         pages: pages!,
     479           3 :         onPopPage: onPopPage,
     480             :       );
     481             :     }
     482           0 :     if (child != null) {
     483           0 :       return child!;
     484             :     }
     485             : 
     486           0 :     return Center(
     487           0 :       child: CircularProgressIndicator(),
     488             :     );
     489             :   }
     490             : 
     491             :   @override
     492           0 :   Future<void> setNewRoutePath(configuration) async => null;
     493             : 
     494             :   @override
     495           0 :   Future<bool> popRoute() async {
     496           0 :     if (onSystemPopPage != null) {
     497           0 :       await onSystemPopPage!();
     498             :       return true;
     499             :     }
     500             :     return false;
     501             :   }
     502             : }

Generated by: LCOV version 1.14