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

Generated by: LCOV version 1.14