LCOV - code coverage report
Current view: top level - src - beam_guard.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 15 15 100.0 %
Date: 2021-07-18 19:09:57 Functions: 0 0 -

          Line data    Source code
       1             : import 'package:beamer/src/utils.dart';
       2             : import 'package:flutter/widgets.dart';
       3             : 
       4             : import './beam_location.dart';
       5             : import './beam_page.dart';
       6             : 
       7             : /// Checks whether current [BeamLocation] is allowed to be beamed to
       8             : /// and provides steps to be executed following a failed check.
       9             : ///
      10             : /// If neither [beamTo], [beamToNamed] nor [showPage] is specified,
      11             : /// the guard will just block navigation, i.e. nothing will happen.
      12             : class BeamGuard {
      13           1 :   const BeamGuard({
      14             :     required this.pathBlueprints,
      15             :     required this.check,
      16             :     this.onCheckFailed,
      17             :     this.beamTo,
      18             :     this.beamToNamed,
      19             :     this.showPage,
      20             :     this.guardNonMatching = false,
      21             :     this.replaceCurrentStack = true,
      22             :   });
      23             : 
      24             :   /// A list of path strings or regular expressions (using dart's RegExp class) that are to be guarded.
      25             :   ///
      26             :   /// For strings:
      27             :   /// Asterisk wildcard is supported to denote "anything".
      28             :   ///
      29             :   /// For example, '/books/*' will match '/books/1', '/books/2/genres', etc.
      30             :   /// but will not match '/books'. To match '/books' and everything after it,
      31             :   /// use '/books*'.
      32             :   ///
      33             :   /// See [_hasMatch] for more details.
      34             :   ///
      35             :   /// For RegExp:
      36             :   /// You can use RegExp instances and the delegate will check for a match using [RegExp.hasMatch]
      37             :   ///
      38             :   /// For example, `RegExp('/books/')` will match '/books/1', '/books/2/genres', etc.
      39             :   /// but will not match '/books'. To match '/books' and everything after it,
      40             :   /// use `RegExp('/books')`
      41             :   final List<Pattern> pathBlueprints;
      42             : 
      43             :   /// What check should be performed on a given [location],
      44             :   /// the one to which beaming has been requested.
      45             :   ///
      46             :   /// [context] is also injected to fetch data up the tree if necessary.
      47             :   final bool Function(BuildContext context, BeamLocation location) check;
      48             : 
      49             :   /// Arbitrary closure to execute when [check] fails.
      50             :   ///
      51             :   /// This will run before and regardless of [beamTo], [beamToNamed], [showPage].
      52             :   final void Function(BuildContext context, BeamLocation location)?
      53             :       onCheckFailed;
      54             : 
      55             :   /// If guard [check] returns `false`, build a [BeamLocation] to be beamed to.
      56             :   ///
      57             :   /// [showPage] has precedence over this attribute.
      58             :   final BeamLocation Function(BuildContext context)? beamTo;
      59             : 
      60             :   /// If guard [check] returns `false`, beam to this URI string.
      61             :   ///
      62             :   /// [showPage] has precedence over this attribute.
      63             :   final String? beamToNamed;
      64             : 
      65             :   /// If guard [check] returns `false`, put this page onto navigation stack.
      66             :   ///
      67             :   /// This has precedence over [beamTo] and [beamToNamed].
      68             :   final BeamPage? showPage;
      69             : 
      70             :   /// Whether to [check] all the path blueprints defined in [pathBlueprints]
      71             :   /// or [check] all the paths that **are not** in [pathBlueprints].
      72             :   ///
      73             :   /// `false` meaning former and `true` meaning latter.
      74             :   final bool guardNonMatching;
      75             : 
      76             :   /// Whether or not to replace the current [BeamLocation]'s stack of pages.
      77             :   final bool replaceCurrentStack;
      78             : 
      79             :   /// Matches [location]'s pathBlueprint to [pathBlueprints].
      80             :   ///
      81             :   /// If asterisk is present, it is enough that the pre-asterisk substring is
      82             :   /// contained within location's pathBlueprint.
      83             :   /// Else, the path (i.e. the pre-query substring) of the location's uri
      84             :   /// must be equal to the pathBlueprint.
      85           1 :   bool _hasMatch(BeamLocation location) {
      86           2 :     for (final pathBlueprint in pathBlueprints) {
      87             :       final path =
      88           5 :           Uri.parse(location.state.routeInformation.location ?? '/').path;
      89           1 :       if (pathBlueprint is String) {
      90           1 :         final asteriskIndex = pathBlueprint.indexOf('*');
      91           2 :         if (asteriskIndex != -1) {
      92           3 :           if (location.state.routeInformation.location
      93           1 :               .toString()
      94           2 :               .contains(pathBlueprint.substring(0, asteriskIndex))) {
      95             :             return true;
      96             :           }
      97             :         } else {
      98           1 :           if (pathBlueprint == path) {
      99             :             return true;
     100             :           }
     101             :         }
     102             :       } else {
     103           1 :         final regexp = Utils.tryCastToRegExp(pathBlueprint);
     104           1 :         return regexp.hasMatch(path);
     105             :       }
     106             :     }
     107             :     return false;
     108             :   }
     109             : 
     110             :   /// Whether or not the guard should [check] the [location].
     111           1 :   bool shouldGuard(BeamLocation location) {
     112           3 :     return guardNonMatching ? !_hasMatch(location) : _hasMatch(location);
     113             :   }
     114             : }

Generated by: LCOV version 1.14