navi: honor Screen.canPop across back/swipe pop paths

canPop was documented as gating the back button / swipe but was ignored by
ScreenBackHandler, XRouterBack.didPopRoute, and XRouter.canPop, so a stack
entry with canPop=false was still poppable by gesture or system back. Make it
authoritative in all three so a non-poppable pushed entry (e.g. an activation
screen) can't be backed out from under the user.
This commit is contained in:
agra
2026-05-29 20:05:37 +03:00
parent 2398c8ad35
commit e8f8882f2e
2 changed files with 5 additions and 4 deletions

View File

@@ -77,7 +77,8 @@ class XRouter extends BackButtonDispatcher
late final _overlayEntry = OverlayEntry(builder: _buildContent); late final _overlayEntry = OverlayEntry(builder: _buildContent);
bool get canPop { bool get canPop {
if (stack.isNotEmpty) return true; final top = stack.lastOrNull;
if (top != null) return top.canPop;
if (home is ScreenShell) { if (home is ScreenShell) {
for (final screen in (home as ScreenShell).pages) { for (final screen in (home as ScreenShell).pages) {
if (!screen.popped) return true; if (!screen.popped) return true;
@@ -225,7 +226,7 @@ class XRouterBack extends RootBackButtonDispatcher {
} }
if (router.home.handleBack()) return true; if (router.home.handleBack()) return true;
final page = router.stack.lastOrNull; final page = router.stack.lastOrNull;
if (page != null) { if (page != null && page.canPop) {
page.pop(); page.pop();
return true; return true;
} }

View File

@@ -75,7 +75,7 @@ class ScreenStackState extends State<ScreenStack> with TickerProviderStateMixin
} }
void _updateCanPop() { void _updateCanPop() {
final canPop = _entries.any((e) => !e.removing); final canPop = _entries.any((e) => !e.removing && e.page.canPop);
if (canPop == _canPop) return; if (canPop == _canPop) return;
_canPop = canPop; _canPop = canPop;
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
@@ -258,7 +258,7 @@ class ScreenStackState extends State<ScreenStack> with TickerProviderStateMixin
ScreenBackHandler( ScreenBackHandler(
key: entry.key, key: entry.key,
entry: entry, entry: entry,
enabled: entry == top && _canPop, enabled: entry == top && _canPop && entry.page.canPop,
onPop: () => entry.page.pop(), onPop: () => entry.page.pop(),
), ),
], ],