dart format
This commit is contained in:
+86
-78
@@ -95,7 +95,9 @@ class _AppState extends State<App> with WidgetsBindingObserver {
|
||||
if (!mounted) return;
|
||||
NotificationController.onForegroundMessageHandler(message, context);
|
||||
});
|
||||
FirebaseMessaging.onBackgroundMessage(NotificationController.onBackgroundMessageHandler);
|
||||
FirebaseMessaging.onBackgroundMessage(
|
||||
NotificationController.onBackgroundMessageHandler,
|
||||
);
|
||||
|
||||
FirebaseMessaging.onMessageOpenedApp.listen((message) {
|
||||
if (!mounted) return;
|
||||
@@ -119,83 +121,89 @@ class _AppState extends State<App> with WidgetsBindingObserver {
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => BlocBuilder<SettingsCubit, model.Settings>(
|
||||
builder: (context, _) {
|
||||
final bottomBarModules = AppModule.getBottomBarModules(context);
|
||||
final totalTabs = bottomBarModules.length + 1;
|
||||
final currentIndex = Main.bottomNavigator.index;
|
||||
Widget build(
|
||||
BuildContext context,
|
||||
) => BlocBuilder<SettingsCubit, model.Settings>(
|
||||
builder: (context, _) {
|
||||
final bottomBarModules = AppModule.getBottomBarModules(context);
|
||||
final totalTabs = bottomBarModules.length + 1;
|
||||
final currentIndex = Main.bottomNavigator.index;
|
||||
|
||||
// The bottom-bar layout is identified by the ordered list of module
|
||||
// names plus the trailing 'more' slot. Whenever this layout changes
|
||||
// — slot count, reordering, or hiding a module — we recreate the
|
||||
// entire PersistentTabView via the [layoutKey] below. The package
|
||||
// caches per-tab navigator state by index in `_navigatorKeys`, and
|
||||
// its internal `alignLength` only ever appends or trims at the end.
|
||||
// So when the module sitting at e.g. index 3 changes, the navigator
|
||||
// at that index still serves the old screen's route stack and the
|
||||
// user sees stale content. Re-mounting clears those stacks; the
|
||||
// trade-off (losing in-tab pushed routes on a settings change) is
|
||||
// acceptable since the user explicitly re-shaped the bar.
|
||||
final layoutKey = ValueKey('${bottomBarModules.map((m) => m.module.name).join('|')}|more');
|
||||
|
||||
if (totalTabs != _knownTotalTabs) {
|
||||
var targetIndex = currentIndex;
|
||||
if (_userOnLastTab) {
|
||||
targetIndex = totalTabs - 1;
|
||||
} else if (currentIndex >= totalTabs) {
|
||||
targetIndex = totalTabs - 1;
|
||||
}
|
||||
// Re-mounting PTV with a new key constructs fresh internals from
|
||||
// its controller's current index. If the controller still points
|
||||
// past the new tab list, Style6BottomNavBar (and others) crash on
|
||||
// out-of-range access during initState. Replace the controller
|
||||
// atomically with one initialised at the safe target index so the
|
||||
// new PTV mounts cleanly.
|
||||
if (targetIndex != currentIndex) {
|
||||
Main.bottomNavigator.removeListener(_onTabControllerChanged);
|
||||
Main.bottomNavigator = PersistentTabController(initialIndex: targetIndex);
|
||||
Main.bottomNavigator.addListener(_onTabControllerChanged);
|
||||
_userOnLastTab = targetIndex == totalTabs - 1;
|
||||
}
|
||||
}
|
||||
|
||||
_knownTotalTabs = totalTabs;
|
||||
|
||||
return PersistentTabView(
|
||||
key: layoutKey,
|
||||
controller: Main.bottomNavigator,
|
||||
navBarOverlap: const NavBarOverlap.none(),
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
handleAndroidBackButtonPress: true,
|
||||
screenTransitionAnimation: const ScreenTransitionAnimation(
|
||||
curve: Curves.easeOutQuad,
|
||||
duration: Duration(milliseconds: 200),
|
||||
),
|
||||
tabs: [
|
||||
...bottomBarModules.map((e) => e.toBottomTab(context)),
|
||||
PersistentTabConfig(
|
||||
screen: const Breaker(breaker: BreakerArea.more, child: Overhang()),
|
||||
item: ItemConfig(
|
||||
activeForegroundColor: Theme.of(context).primaryColor,
|
||||
inactiveForegroundColor: Theme.of(context).colorScheme.secondary,
|
||||
icon: const Icon(Icons.apps),
|
||||
title: 'Mehr',
|
||||
),
|
||||
),
|
||||
],
|
||||
navBarBuilder: (config) => Style6BottomNavBar(
|
||||
// Style6BottomNavBar builds its internal animation controller list
|
||||
// in initState and never grows it on didUpdateWidget. Keying by the
|
||||
// item count forces a fresh State whenever the slot count changes,
|
||||
// which avoids a RangeError when more tabs slide in.
|
||||
key: ValueKey(config.items.length),
|
||||
navBarConfig: config,
|
||||
navBarDecoration: NavBarDecoration(
|
||||
border: const Border(top: BorderSide(width: 1, color: Colors.grey)),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
// The bottom-bar layout is identified by the ordered list of module
|
||||
// names plus the trailing 'more' slot. Whenever this layout changes
|
||||
// — slot count, reordering, or hiding a module — we recreate the
|
||||
// entire PersistentTabView via the [layoutKey] below. The package
|
||||
// caches per-tab navigator state by index in `_navigatorKeys`, and
|
||||
// its internal `alignLength` only ever appends or trims at the end.
|
||||
// So when the module sitting at e.g. index 3 changes, the navigator
|
||||
// at that index still serves the old screen's route stack and the
|
||||
// user sees stale content. Re-mounting clears those stacks; the
|
||||
// trade-off (losing in-tab pushed routes on a settings change) is
|
||||
// acceptable since the user explicitly re-shaped the bar.
|
||||
final layoutKey = ValueKey(
|
||||
'${bottomBarModules.map((m) => m.module.name).join('|')}|more',
|
||||
);
|
||||
|
||||
if (totalTabs != _knownTotalTabs) {
|
||||
var targetIndex = currentIndex;
|
||||
if (_userOnLastTab) {
|
||||
targetIndex = totalTabs - 1;
|
||||
} else if (currentIndex >= totalTabs) {
|
||||
targetIndex = totalTabs - 1;
|
||||
}
|
||||
// Re-mounting PTV with a new key constructs fresh internals from
|
||||
// its controller's current index. If the controller still points
|
||||
// past the new tab list, Style6BottomNavBar (and others) crash on
|
||||
// out-of-range access during initState. Replace the controller
|
||||
// atomically with one initialised at the safe target index so the
|
||||
// new PTV mounts cleanly.
|
||||
if (targetIndex != currentIndex) {
|
||||
Main.bottomNavigator.removeListener(_onTabControllerChanged);
|
||||
Main.bottomNavigator = PersistentTabController(
|
||||
initialIndex: targetIndex,
|
||||
);
|
||||
Main.bottomNavigator.addListener(_onTabControllerChanged);
|
||||
_userOnLastTab = targetIndex == totalTabs - 1;
|
||||
}
|
||||
}
|
||||
|
||||
_knownTotalTabs = totalTabs;
|
||||
|
||||
return PersistentTabView(
|
||||
key: layoutKey,
|
||||
controller: Main.bottomNavigator,
|
||||
navBarOverlap: const NavBarOverlap.none(),
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
handleAndroidBackButtonPress: true,
|
||||
screenTransitionAnimation: const ScreenTransitionAnimation(
|
||||
curve: Curves.easeOutQuad,
|
||||
duration: Duration(milliseconds: 200),
|
||||
),
|
||||
tabs: [
|
||||
...bottomBarModules.map((e) => e.toBottomTab(context)),
|
||||
PersistentTabConfig(
|
||||
screen: const Breaker(breaker: BreakerArea.more, child: Overhang()),
|
||||
item: ItemConfig(
|
||||
activeForegroundColor: Theme.of(context).primaryColor,
|
||||
inactiveForegroundColor: Theme.of(context).colorScheme.secondary,
|
||||
icon: const Icon(Icons.apps),
|
||||
title: 'Mehr',
|
||||
),
|
||||
),
|
||||
],
|
||||
navBarBuilder: (config) => Style6BottomNavBar(
|
||||
// Style6BottomNavBar builds its internal animation controller list
|
||||
// in initState and never grows it on didUpdateWidget. Keying by the
|
||||
// item count forces a fresh State whenever the slot count changes,
|
||||
// which avoids a RangeError when more tabs slide in.
|
||||
key: ValueKey(config.items.length),
|
||||
navBarConfig: config,
|
||||
navBarDecoration: NavBarDecoration(
|
||||
border: const Border(top: BorderSide(width: 1, color: Colors.grey)),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user