back method

dynamic back({
  1. String? name,
  2. dynamic result,
  3. int step = 1,
  4. bool toInitial = false,
})

Implementation

back({String? name, dynamic result, int step = 1, bool toInitial = false}) async {
  /// no route to pop
  if (_routes.isEmpty || _routes.length == 1) {
    _log('No Route To Pop, Navigation Back Action Ignored');
    return;
  }
  int popCount = 0;
  int maxPopCount = _routes.length - 1;

  /// if name is provided, pop to the page with the given name
  if (name != null) {
    int index = _routes.indexWhere((e) => e.name == name);
    if (index == -1) {
      return _log('No Page Matched :$name, Navigation Back Action Ignored');
    }

    /// eg: A -> B -> C
    /// pop to A
    /// _index = 2、 index = 0 and the popCount is 2
    popCount = _index - index;
  } else {
    /// pop count of step
    popCount = min(step, maxPopCount);
  }
  if (toInitial) {
    popCount = maxPopCount;
  }
  if (popCount == 0) {
    return;
  }

  final curRouteId = _routes.last.id;
  final curRouteName = _routes.last.name;

  /// pop routes
  for (int i = popCount; i > 0; i--) {
    final route = _routes.removeLast();
    route.controller?.onWillDispose();

    /// popped multiple routes, only the last route will receive the result
    /// eg: A -> B -> C
    /// pop to A
    /// B and C will not receive the result、 future.catchError will get the [StackRoutePoppedUnexpectedlyException]
    if (i == 1 && _routes.last.completer != null && _routes.last.completer!.isCompleted == false) {
      /// B : i = 1
      debugPrint('_routes.last[${_routes.last.id}] complete with result: $result');
      _routes.last.completer?.complete(result);
    } else if (i != 1) {
      if (route.completer != null && route.completer!.isCompleted == false) {
        debugPrint('removed route[${route.id}] complete with cancel');
        route.completer?.complete(StackRoutePoppedUnexpectedlyException());
      }
    }
  }

  /// emit global navigation event [GBOnStackRouteWillChange] if route did popped
  if (curRouteId != _routes.last.id) {
    GBOnStackRouteWillChange(
      data: GBOnStackRouteWillChangeData(
        routeId: curRouteId,
        routeName: curRouteName,
        targetRouteId: _routes.last.id,
        targetRouteName: _routes.last.name,
        type: toInitial ? StackRouteChangeType.popTop : StackRouteChangeType.pop,
        isInitialRoute: _index == 0,
      ),
    ).emit();

    if (_index == 0) {
      /// emit global navigation event [GBOnStackRouteIsInitial]
      GBOnStackRouteIsInitial(data: true).emit();
    }
  }

  /// request rebuild navigator
  notifyListeners();

  /// notify last route that it's focused
  WidgetsBinding.instance.addPostFrameCallback((_) {
    _routes.last.controller?.onFocused.call(true);
  });
}