NavigationController.tabbed constructor

NavigationController.tabbed({
  1. required List<NavigationBranch> branches,
  2. NavigationBranchId? initialBranchId,
  3. NavigationAnalyticsSink? analyticsSink,
})

Constructs a tabbed controller with independent per-branch stacks.

branches must be non-empty and have unique NavigationBranch.ids. When initialBranchId is omitted, the first branch is active. The active branch's NavigationBranch.initialNavigation seeds analytics.

Implementation

factory NavigationController.tabbed({
  required List<NavigationBranch> branches,
  NavigationBranchId? initialBranchId,
  NavigationAnalyticsSink? analyticsSink,
}) {
  if (branches.isEmpty) {
    throw ArgumentError.value(
      branches,
      'branches',
      'At least one branch is required.',
    );
  }
  final seen = <NavigationBranchId>{};
  final branchMap = <NavigationBranchId, List<ViewNavigationType>>{};
  final metadataMap = <NavigationBranchId, _BranchMetadata>{};
  for (final branch in branches) {
    if (!seen.add(branch.id)) {
      throw ArgumentError.value(
        branch.id,
        'branches',
        'Duplicate branch id.',
      );
    }
    branchMap[branch.id] = [branch.initialNavigation];
    metadataMap[branch.id] = _BranchMetadata(
      wantsKeepAlive: branch.wantsKeepAlive,
      screenName: branch.resolvedScreenName,
    );
  }
  final activeId = initialBranchId ?? branches.first.id;
  if (!branchMap.containsKey(activeId)) {
    throw ArgumentError.value(
      initialBranchId,
      'initialBranchId',
      'Not a registered branch id.',
    );
  }
  return NavigationController._(
    branches: branchMap,
    branchMetadata: metadataMap,
    activeBranchId: activeId,
    initialNavigation: branchMap[activeId]!.first,
    analyticsSink: analyticsSink,
  );
}