feat: enforce hierarchical back navigation and home-only exit

This commit is contained in:
qzl
2026-03-20 15:20:29 +08:00
parent 19a2cd451d
commit cbbed29a75
7 changed files with 31 additions and 11 deletions
+8 -4
View File
@@ -26,15 +26,19 @@ import '../../features/settings/ui/screens/features_screen.dart';
import '../../features/settings/ui/screens/memory_screen.dart';
import '../../features/settings/ui/screens/edit_profile_screen.dart';
final _protectedRoutes = [
final _homeSecondLevelRoutes = [
AppRoutes.homeMain,
AppRoutes.contactsList,
AppRoutes.contactsAdd,
AppRoutes.calendarDayWeek,
AppRoutes.calendarMonth,
'/calendar/events',
AppRoutes.todoList,
AppRoutes.settingsMain,
];
final _protectedRoutes = [
..._homeSecondLevelRoutes,
AppRoutes.contactsList,
AppRoutes.contactsAdd,
'/calendar/events',
AppRoutes.settingsFeatures,
AppRoutes.settingsMemory,
AppRoutes.settingsEditProfile,
@@ -119,7 +119,7 @@ class _CalendarDayWeekScreenState extends State<CalendarDayWeekScreen>
canPop: false,
onPopInvokedWithResult: (didPop, result) {
if (!didPop) {
returnToHomePreserveState(context);
returnToHomePreserveState(context, forceGoHome: true);
}
},
child: SafeArea(
@@ -702,7 +702,7 @@ class _CalendarDayWeekScreenState extends State<CalendarDayWeekScreen>
_calendarManager.setViewType(CalendarViewType.day);
context.push(AppRoutes.calendarMonth);
},
onHomeTap: () => returnToHomePreserveState(context),
onHomeTap: () => returnToHomePreserveState(context, forceGoHome: true),
);
}
}
@@ -105,7 +105,7 @@ class _CalendarMonthScreenState extends State<CalendarMonthScreen>
canPop: false,
onPopInvokedWithResult: (didPop, result) {
if (!didPop) {
returnToHomePreserveState(context);
returnToHomePreserveState(context, forceGoHome: true);
}
},
child: SafeArea(
@@ -522,7 +522,7 @@ class _CalendarMonthScreenState extends State<CalendarMonthScreen>
context.push(AppRoutes.todoList);
},
onCalendarTap: () {},
onHomeTap: () => returnToHomePreserveState(context),
onHomeTap: () => returnToHomePreserveState(context, forceGoHome: true),
);
}
}
@@ -8,7 +8,11 @@ enum HomeReturnAction { pop, goHome }
HomeReturnAction resolveHomeReturnAction({
required bool canPop,
required bool isAuthEntry,
bool forceGoHome = false,
}) {
if (forceGoHome) {
return HomeReturnAction.goHome;
}
if (isAuthEntry) {
return HomeReturnAction.goHome;
}
@@ -21,10 +25,12 @@ HomeReturnAction resolveHomeReturnAction({
void returnToHomePreserveState(
BuildContext context, {
bool isAuthEntry = false,
bool forceGoHome = false,
}) {
final action = resolveHomeReturnAction(
canPop: context.canPop(),
isAuthEntry: isAuthEntry,
forceGoHome: forceGoHome,
);
switch (action) {
case HomeReturnAction.pop:
@@ -20,6 +20,7 @@ import 'package:social_app/features/settings/data/settings_api.dart';
import 'package:social_app/features/settings/data/services/settings_user_cache.dart';
import 'package:social_app/features/users/data/models/user_response.dart';
import 'package:social_app/features/users/data/users_api.dart';
import 'package:social_app/features/home/ui/navigation/home_return_policy.dart';
import '../widgets/settings_page_scaffold.dart';
const settingsProfileEditButtonKey = ValueKey('settings_profile_edit_button');
@@ -90,7 +91,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
Widget build(BuildContext context) {
return SettingsPageScaffold(
title: '设置',
onBack: () => context.pop(),
onBack: () => returnToHomePreserveState(context, forceGoHome: true),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
@@ -298,7 +298,7 @@ class _TodoQuadrantsScreenState extends State<TodoQuadrantsScreen> {
canPop: false,
onPopInvokedWithResult: (didPop, result) {
if (!didPop) {
returnToHomePreserveState(context);
returnToHomePreserveState(context, forceGoHome: true);
}
},
child: SafeArea(
@@ -563,7 +563,7 @@ class _TodoQuadrantsScreenState extends State<TodoQuadrantsScreen> {
context.push('${AppRoutes.calendarDayWeek}?date=$dateStr');
}
},
onHomeTap: () => returnToHomePreserveState(context),
onHomeTap: () => returnToHomePreserveState(context, forceGoHome: true),
);
}
}
@@ -3,6 +3,15 @@ import 'package:social_app/features/home/ui/navigation/home_return_policy.dart';
void main() {
group('resolveHomeReturnAction', () {
test('second-level pages should return to home instead of exiting app', () {
final action = resolveHomeReturnAction(
canPop: false,
isAuthEntry: false,
forceGoHome: true,
);
expect(action, HomeReturnAction.goHome);
});
test('business route with back stack prefers pop', () {
final action = resolveHomeReturnAction(canPop: true, isAuthEntry: false);
expect(action, HomeReturnAction.pop);