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:
@@ -77,7 +77,8 @@ class XRouter extends BackButtonDispatcher
|
||||
late final _overlayEntry = OverlayEntry(builder: _buildContent);
|
||||
|
||||
bool get canPop {
|
||||
if (stack.isNotEmpty) return true;
|
||||
final top = stack.lastOrNull;
|
||||
if (top != null) return top.canPop;
|
||||
if (home is ScreenShell) {
|
||||
for (final screen in (home as ScreenShell).pages) {
|
||||
if (!screen.popped) return true;
|
||||
@@ -225,7 +226,7 @@ class XRouterBack extends RootBackButtonDispatcher {
|
||||
}
|
||||
if (router.home.handleBack()) return true;
|
||||
final page = router.stack.lastOrNull;
|
||||
if (page != null) {
|
||||
if (page != null && page.canPop) {
|
||||
page.pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ class ScreenStackState extends State<ScreenStack> with TickerProviderStateMixin
|
||||
}
|
||||
|
||||
void _updateCanPop() {
|
||||
final canPop = _entries.any((e) => !e.removing);
|
||||
final canPop = _entries.any((e) => !e.removing && e.page.canPop);
|
||||
if (canPop == _canPop) return;
|
||||
_canPop = canPop;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
@@ -258,7 +258,7 @@ class ScreenStackState extends State<ScreenStack> with TickerProviderStateMixin
|
||||
ScreenBackHandler(
|
||||
key: entry.key,
|
||||
entry: entry,
|
||||
enabled: entry == top && _canPop,
|
||||
enabled: entry == top && _canPop && entry.page.canPop,
|
||||
onPop: () => entry.page.pop(),
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user