back_stack 0.2.5
back_stack: ^0.2.5 copied to clipboard
You own the back stack. Navigation is a list you push and pop — type-safe, observable, no route graph.
0.2.5 #
BackStackApp<K>— deep links in one function. A single widget bundles theMaterialApp.router+NavStackRouterDelegate+ parser wiring; you supply onlyonLink: (Uri) => [destinations]. OptionaltoLinkprojects the stack back onto the web address bar,onLinkFallbackhandles bad links, andrestorationScopeIdis set by default. Zero new dependencies — it drives Flutter's own Router.BackStack.parentOf<K>(context)(andmaybeParentOf) — reach the stack one level up from a nested child when parent and child share the same key type, so a child screen canBackStack.parentOf<AppKey>(context).pop()the outer flow. (Distinct key subtypes +BackStack.of<ParentKey>remain the more type-safe default.)example/lib/multi_file/now usesBackStackApp— the simplest example also demonstrates deep links (/product/7).
0.2.4 #
- Docs: the README hero snippet is corrected and no longer uses a
switch— it leads withNavEntries(..on<Home>(...),builder: entries.call) over a non-sealedAppKey, so it compiles as shown and mirrors a multi-file app. (The previous snippet declared asealedbase with noconstconstructor and inferredNavStack<Home>, so it didn't compile.) - Adds
example/lib/multi_file/— the simplest multi-file layout:app_key.dart- one file per feature (
home_feature.dart,product_feature.dart) each with its own destination, screen andregister*call, collected inmain.dart. Noswitch, no central list.
- one file per feature (
0.2.3 #
- Fix: a
pop(result)that is vetoed byguard(or collapsed to a no-op byredirect) no longer completes the destination'spushForResultfuture or returnstrue. Previously the awaiter received the result while the screen was still on top — now the result is delivered, andpopreturnstrue, only when the entry actually leaves the stack. (popGuardwas already safe.) - Docs:
NavEntryDecorator.onRemovednotes that it runs during the display's build (defer any rebuild-triggering work withaddPostFrameCallback);NavEntriesdocuments that it matches by exact runtime type, not subtype. - Adds
example/lib/modular_demo.dart(also on GitHub): three feature modules register their ownNavEntriesinto one map, and a singleNavEntryDecoratorwraps every screen and logs teardown ononRemoved.
0.2.2 #
- The main example (
example/lib/main.dart, the one shown on the package page) now demonstratesNavEntries(as the builder) andNavEntryDecorator(ascreen_viewlog + teardown hook) — so both APIs are visible on pub.dev's Example tab. No library code changed.
0.2.1 #
- Add
NavEntries<K>— a registrable destination-type → screen map (..on<Home>(...)), Compose Nav3'sentryProvider. Passbuilder: entries.calltoNavDisplay. Composes across feature files/modules instead of one bigswitch. Theswitchstays the default (compile-time exhaustive); this is the modular option. - Add
NavEntryDecorator<K>— Nav3'sNavEntryDecorator.decoratewraps every screen (providers/DI scopes/tracing; first decorator is outermost) andonRemovedfires when an entry leaves the stack (or the display is disposed) so you can tear down a Bloc/controller/scope tied to a destination. Wire via the newdecorators:onNavDisplay— also forwarded byMultiNavDisplay,NavSceneHost,NavListDetail,NavStackRouterDelegateandMultiNavStackRouterDelegate.
0.2.0 #
- Add
NavStackCodec.of(encode:, decode:, fallback:)— build a deep-link codec inline from two functions instead of subclassingNavStackCodec. - Add
NavStackCodec.fallbackFor(uri)— the stack shown when a link is malformed or unknown (defaults to decoding/; supplyfallback:or override to route to a NotFound screen). - Harden the deep-link boundary:
NavStackRouterDelegatenow decodes without ever throwing — adecodethat throws or returns empty falls back instead of crashing the app, so codecs can parse optimistically. - Fix:
pushForResultno longer hangs (and leaks its awaiter) when the push is blocked byguardor collapsed to a no-op byredirect— the future now resolvesnull, like every other way a screen can leave the stack. - Web + tabs:
MultiNavStackRouterDelegate+MultiNavStackCodecbring URL sync, deep links and OS back to aMultiNavStack(per-tab history) — the multi-tab equivalents ofNavStackRouterDelegate/NavStackCodec. - Restoration + tabs:
RestorableMultiNavStackpersists every tab's stack and the active tab across process death. Both restorable widgets now survive a corrupt/incompatible snapshot by keeping the freshly created stack instead of crashing on cold start. MultiNavDisplaygainslazy(build a tab only once first selected; defaultfalse, unchanged behavior) andobservers.observersis also now forwarded byNavSceneHost,NavListDetailandNavStackRouterDelegate— a cleanNavigatorObserverseam forscreen_viewanalytics.NavListDetailnow preserves paneStateacross the breakpoint. Rotating or resizing between the two-pane and stacked layouts keeps each screen's scroll position and controllers — every entry gets a stableGlobalKey, so Flutter reparents the live screen instead of rebuilding it.- Add
MultiBackStack.of(context)(andMultiNavStackScope) — reach theMultiNavStackhost from any tab screen to switch tabs / read the active index, without passing the host down by hand.
0.1.1 #
- Docs: the demo GIF now uses an absolute URL so it renders on the pub.dev
package page (a relative path inside a raw
<img>tag wasn't rewritten).
0.1.0 #
- Fix:
Hero(shared-element) transitions now animate inside a nestedNavDisplay— e.g. underNavListDetailorMaterialApp(home:). Each display drives its ownHeroControllervia aHeroControllerScope, so a sprite flies between screens instead of snapping. Previously only the root/Router display inherited one. Regression-tested.
0.0.1 #
- Adaptive layout:
NavListDetail(one stack → two-pane on wide, animated stack on narrow) and the generalNavSceneHost+NavSceneStrategyengine (listDetailScene,supportingPaneScene) — Compose Nav3 "scenes" over one list. - Multi-stack:
MultiNavStack+MultiNavDisplaygive a bottom-nav persistent per-tab back stack (IndexedStack), with innermost-first system back. - Custom pages:
TransitionPage(.fade/.slideUp/.scale/.none),DialogPage,SheetPage, and a per-keyNavPagemixin so a destination declares its own transition. ConfirmPopScope: async confirm-before-leave covering the Android system back.RestorableBackStack+NavKeyCodec: full-stack restoration across process death without a URL.NavDisplay.nestedflag routes the system back gesture into a nested stack.- Minimal rebuilds: pages are memoized by entry id, so one push rebuilds exactly
one screen regardless of stack depth (see
benchmark/). popGuard(sync pop veto) andrefreshListenable(re-runredirecton auth change) onNavStack.NavStack: the back stack you own. push / pop / replaceTop / replaceAll / popUntil / edit.BackStack.of(context)reaches it from a screen (auto-provided by NavDisplay).- Auth gating:
redirect(pure transform, applied once — loop-proof) andguard(veto). NavDisplay: renders the stack via the Pages API; system / predictive / hardware back sync into the list automatically (onDidRemovePage).NavKey: type-safe destinations as plain Dart objects.EquatableNavKeymixin gives them value equality so a URL re-decode reuses the live screen.- Identity & State preservation: stable unique id per entry (unique page key);
duplicate destinations are independent;
replaceAll/editreconcile so survivors keep their State and only changed screens rebuild. - Result passing:
pushForResult<T>()->Future<T?>, completed bypop([result])or null on any other removal / dispose (never hangs/leaks). - Router integration:
NavStackRouterDelegate+NavStackRouteInformationParser- a
NavStackCodec(Uri <-> List<NavKey>): web URL sync, deep links (you choose layer-vs-replace), browser/OS/predictive back, and state restoration.
- a
- Leak-safe: leaving the stack disposes the route (proven by test); suite runs
under
leak_tracker_flutter_testing. 42 tests + benchmarks, analyze clean undervery_good_analysis(strict casts/inference/raw-types). - Docs:
doc/PHILOSOPHY.mdmaps Flutter's model + the nav leak/caveat catalog.