LCOV - code coverage report
Current view: top level - src - beam_state.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 52 52 100.0 %
Date: 2021-09-11 22:34:03 Functions: 0 0 -

          Line data    Source code
       1             : import 'dart:convert';
       2             : 
       3             : import 'package:flutter/foundation.dart';
       4             : import 'package:flutter/widgets.dart';
       5             : 
       6             : import './utils.dart';
       7             : import './beam_location.dart';
       8             : 
       9             : /// A class to mix with when defining a custom state for [BeamLocation].
      10             : ///
      11             : /// [fromRouteInformation] and [toRouteInformation] need to be implemented in
      12             : /// order to notify the platform of current [RouteInformation] that corresponds
      13             : /// to the state.
      14             : mixin RouteInformationSerializable<T> {
      15             :   T fromRouteInformation(RouteInformation routeInformation);
      16             :   RouteInformation toRouteInformation();
      17          18 :   RouteInformation get routeInformation => toRouteInformation();
      18             : }
      19             : 
      20             : /// A pre-made state for [BeamLocation].
      21             : ///
      22             : /// This can be used when one does not desire to define its own state.
      23             : class BeamState with RouteInformationSerializable<BeamState> {
      24           9 :   BeamState({
      25             :     this.pathPatternSegments = const <String>[],
      26             :     this.pathParameters = const <String, String>{},
      27             :     this.queryParameters = const <String, String>{},
      28             :     this.routeState,
      29           9 :   }) : assert(() {
      30           9 :           json.encode(routeState);
      31             :           return true;
      32             :         }()) {
      33           9 :     configure();
      34             :   }
      35             : 
      36             :   /// Creates a [BeamState] from given [uri] and optional [data].
      37             :   ///
      38             :   /// If [beamLocation] is given, then it will take into consideration
      39             :   /// its `pathPatterns` to populate the [pathParameters] attribute.
      40             :   ///
      41             :   /// See [Utils.createBeamState].
      42           9 :   factory BeamState.fromUri(
      43             :     Uri uri, {
      44             :     BeamLocation? beamLocation,
      45             :     Object? routeState,
      46             :   }) {
      47           9 :     return Utils.createBeamState(
      48             :       uri,
      49             :       beamLocation: beamLocation,
      50             :       routeState: routeState,
      51             :     );
      52             :   }
      53             : 
      54             :   /// Creates a [BeamState] from given [uriString] and optional [data].
      55             :   ///
      56             :   /// If [beamLocation] is given, then it will take into consideration
      57             :   /// its path blueprints to populate the [pathParameters] attribute.
      58             :   ///
      59             :   /// See [BeamState.fromUri].
      60           1 :   factory BeamState.fromUriString(
      61             :     String uriString, {
      62             :     BeamLocation? beamLocation,
      63             :     Object? routeState,
      64             :   }) {
      65           1 :     uriString = Utils.trimmed(uriString);
      66           1 :     final uri = Uri.parse(uriString);
      67           1 :     return BeamState.fromUri(
      68             :       uri,
      69             :       beamLocation: beamLocation,
      70             :       routeState: routeState,
      71             :     );
      72             :   }
      73             : 
      74             :   /// Creates a [BeamState] from given [routeInformation].
      75             :   ///
      76             :   /// If [beamLocation] is given, then it will take into consideration
      77             :   /// its path blueprints to populate the [pathParameters] attribute.
      78             :   ///
      79             :   /// See [BeamState.fromUri].
      80           9 :   factory BeamState.fromRouteInformation(
      81             :     RouteInformation routeInformation, {
      82             :     BeamLocation? beamLocation,
      83             :   }) {
      84           9 :     return BeamState.fromUri(
      85          18 :       Uri.parse(routeInformation.location ?? '/'),
      86             :       beamLocation: beamLocation,
      87           9 :       routeState: routeInformation.state,
      88             :     );
      89             :   }
      90             : 
      91             :   /// Path segments of the current URI,
      92             :   /// in the form as it's defined in [BeamLocation.pathPatterns].
      93             :   ///
      94             :   /// If current URI is '/books/1', this will be `['books', ':bookId']`.
      95             :   final List<String> pathPatternSegments;
      96             : 
      97             :   /// Path parameters from the URI,
      98             :   /// in the form as it's defined in [BeamLocation.pathPatterns].
      99             :   ///
     100             :   /// If current URI is '/books/1', this will be `{'bookId': '1'}`.
     101             :   final Map<String, String> pathParameters;
     102             : 
     103             :   /// Query parameters of the current URI.
     104             :   ///
     105             :   /// If current URI is '/books?title=str', this will be `{'title': 'str'}`.
     106             :   final Map<String, String> queryParameters;
     107             : 
     108             :   /// An object that will be passed to [RouteInformation.state]
     109             :   /// that is stored as a part of browser history entry.
     110             :   ///
     111             :   /// This needs to be serializable.
     112             :   final Object? routeState;
     113             : 
     114             :   late Uri _uriBlueprint;
     115             : 
     116             :   /// Current URI object in the "blueprint form",
     117             :   /// as it's defined in [BeamLocation.pathPatterns].
     118             :   ///
     119             :   /// This is constructed from [pathPatternSegments] and [queryParameters].
     120             :   /// See more at [configure].
     121           4 :   Uri get uriBlueprint => _uriBlueprint;
     122             : 
     123             :   late Uri _uri;
     124             : 
     125             :   /// Current URI object in the "real form",
     126             :   /// as it should be shown in browser's URL bar.
     127             :   ///
     128             :   /// This is constructed from [pathPatternSegments] and [queryParameters],
     129             :   /// with the addition of replacing each pathPatternSegment of the form ':*'
     130             :   /// with a coresponding value from [pathParameters].
     131             :   ///
     132             :   /// See more at [configure].
     133          18 :   Uri get uri => _uri;
     134             : 
     135             :   /// Copies this with configuration for specific [BeamLocation].
     136           1 :   BeamState copyForLocation(BeamLocation beamLocation, Object? routeState) {
     137           1 :     return Utils.createBeamState(
     138           1 :       uri,
     139             :       beamLocation: beamLocation,
     140             :       routeState: routeState,
     141             :     );
     142             :   }
     143             : 
     144             :   /// Returns a configured copy of this.
     145           3 :   BeamState copyWith({
     146             :     List<String>? pathPatternSegments,
     147             :     Map<String, String>? pathParameters,
     148             :     Map<String, String>? queryParameters,
     149             :     Object? routeState,
     150             :   }) =>
     151           3 :       BeamState(
     152           2 :         pathPatternSegments: pathPatternSegments ?? this.pathPatternSegments,
     153           1 :         pathParameters: pathParameters ?? this.pathParameters,
     154           2 :         queryParameters: queryParameters ?? this.queryParameters,
     155           3 :         routeState: routeState ?? this.routeState,
     156           3 :       )..configure();
     157             : 
     158             :   /// Constructs [uriBlueprint] and [uri].
     159           9 :   void configure() {
     160          18 :     _uriBlueprint = Uri(
     161          27 :       path: '/' + pathPatternSegments.join('/'),
     162          24 :       queryParameters: queryParameters.isEmpty ? null : queryParameters,
     163             :     );
     164          18 :     final pathSegments = pathPatternSegments.toList();
     165          27 :     for (int i = 0; i < pathSegments.length; i++) {
     166          45 :       if (pathSegments[i].isNotEmpty && pathSegments[i][0] == ':') {
     167          12 :         final key = pathSegments[i].substring(1);
     168          12 :         if (pathParameters.containsKey(key)) {
     169          18 :           pathSegments[i] = pathParameters[key]!;
     170             :         }
     171             :       }
     172             :     }
     173          18 :     _uri = Uri(
     174          18 :       path: '/' + pathSegments.join('/'),
     175          24 :       queryParameters: queryParameters.isEmpty ? null : queryParameters,
     176             :     );
     177             :   }
     178             : 
     179           1 :   @override
     180             :   BeamState fromRouteInformation(RouteInformation routeInformation) =>
     181           1 :       BeamState.fromRouteInformation(routeInformation);
     182             : 
     183           7 :   @override
     184           7 :   RouteInformation toRouteInformation() => RouteInformation(
     185          14 :         location: uri.toString(),
     186           7 :         state: routeState,
     187             :       );
     188             : 
     189           1 :   @override
     190           4 :   int get hashCode => hashValues(uri, json.encode(routeState));
     191             : 
     192           1 :   @override
     193             :   bool operator ==(Object other) {
     194           1 :     return other is BeamState &&
     195           3 :         other.uri == uri &&
     196           5 :         json.encode(other.routeState) == json.encode(routeState);
     197             :   }
     198             : }

Generated by: LCOV version 1.14