feat: enforce hierarchical back navigation and home-only exit
This commit is contained in:
@@ -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/memory_screen.dart';
|
||||||
import '../../features/settings/ui/screens/edit_profile_screen.dart';
|
import '../../features/settings/ui/screens/edit_profile_screen.dart';
|
||||||
|
|
||||||
final _protectedRoutes = [
|
final _homeSecondLevelRoutes = [
|
||||||
AppRoutes.homeMain,
|
AppRoutes.homeMain,
|
||||||
AppRoutes.contactsList,
|
|
||||||
AppRoutes.contactsAdd,
|
|
||||||
AppRoutes.calendarDayWeek,
|
AppRoutes.calendarDayWeek,
|
||||||
AppRoutes.calendarMonth,
|
AppRoutes.calendarMonth,
|
||||||
'/calendar/events',
|
|
||||||
AppRoutes.todoList,
|
AppRoutes.todoList,
|
||||||
AppRoutes.settingsMain,
|
AppRoutes.settingsMain,
|
||||||
|
];
|
||||||
|
|
||||||
|
final _protectedRoutes = [
|
||||||
|
..._homeSecondLevelRoutes,
|
||||||
|
AppRoutes.contactsList,
|
||||||
|
AppRoutes.contactsAdd,
|
||||||
|
'/calendar/events',
|
||||||
AppRoutes.settingsFeatures,
|
AppRoutes.settingsFeatures,
|
||||||
AppRoutes.settingsMemory,
|
AppRoutes.settingsMemory,
|
||||||
AppRoutes.settingsEditProfile,
|
AppRoutes.settingsEditProfile,
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ class _CalendarDayWeekScreenState extends State<CalendarDayWeekScreen>
|
|||||||
canPop: false,
|
canPop: false,
|
||||||
onPopInvokedWithResult: (didPop, result) {
|
onPopInvokedWithResult: (didPop, result) {
|
||||||
if (!didPop) {
|
if (!didPop) {
|
||||||
returnToHomePreserveState(context);
|
returnToHomePreserveState(context, forceGoHome: true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
@@ -702,7 +702,7 @@ class _CalendarDayWeekScreenState extends State<CalendarDayWeekScreen>
|
|||||||
_calendarManager.setViewType(CalendarViewType.day);
|
_calendarManager.setViewType(CalendarViewType.day);
|
||||||
context.push(AppRoutes.calendarMonth);
|
context.push(AppRoutes.calendarMonth);
|
||||||
},
|
},
|
||||||
onHomeTap: () => returnToHomePreserveState(context),
|
onHomeTap: () => returnToHomePreserveState(context, forceGoHome: true),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ class _CalendarMonthScreenState extends State<CalendarMonthScreen>
|
|||||||
canPop: false,
|
canPop: false,
|
||||||
onPopInvokedWithResult: (didPop, result) {
|
onPopInvokedWithResult: (didPop, result) {
|
||||||
if (!didPop) {
|
if (!didPop) {
|
||||||
returnToHomePreserveState(context);
|
returnToHomePreserveState(context, forceGoHome: true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
@@ -522,7 +522,7 @@ class _CalendarMonthScreenState extends State<CalendarMonthScreen>
|
|||||||
context.push(AppRoutes.todoList);
|
context.push(AppRoutes.todoList);
|
||||||
},
|
},
|
||||||
onCalendarTap: () {},
|
onCalendarTap: () {},
|
||||||
onHomeTap: () => returnToHomePreserveState(context),
|
onHomeTap: () => returnToHomePreserveState(context, forceGoHome: true),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,11 @@ enum HomeReturnAction { pop, goHome }
|
|||||||
HomeReturnAction resolveHomeReturnAction({
|
HomeReturnAction resolveHomeReturnAction({
|
||||||
required bool canPop,
|
required bool canPop,
|
||||||
required bool isAuthEntry,
|
required bool isAuthEntry,
|
||||||
|
bool forceGoHome = false,
|
||||||
}) {
|
}) {
|
||||||
|
if (forceGoHome) {
|
||||||
|
return HomeReturnAction.goHome;
|
||||||
|
}
|
||||||
if (isAuthEntry) {
|
if (isAuthEntry) {
|
||||||
return HomeReturnAction.goHome;
|
return HomeReturnAction.goHome;
|
||||||
}
|
}
|
||||||
@@ -21,10 +25,12 @@ HomeReturnAction resolveHomeReturnAction({
|
|||||||
void returnToHomePreserveState(
|
void returnToHomePreserveState(
|
||||||
BuildContext context, {
|
BuildContext context, {
|
||||||
bool isAuthEntry = false,
|
bool isAuthEntry = false,
|
||||||
|
bool forceGoHome = false,
|
||||||
}) {
|
}) {
|
||||||
final action = resolveHomeReturnAction(
|
final action = resolveHomeReturnAction(
|
||||||
canPop: context.canPop(),
|
canPop: context.canPop(),
|
||||||
isAuthEntry: isAuthEntry,
|
isAuthEntry: isAuthEntry,
|
||||||
|
forceGoHome: forceGoHome,
|
||||||
);
|
);
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case HomeReturnAction.pop:
|
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/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/models/user_response.dart';
|
||||||
import 'package:social_app/features/users/data/users_api.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';
|
import '../widgets/settings_page_scaffold.dart';
|
||||||
|
|
||||||
const settingsProfileEditButtonKey = ValueKey('settings_profile_edit_button');
|
const settingsProfileEditButtonKey = ValueKey('settings_profile_edit_button');
|
||||||
@@ -90,7 +91,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SettingsPageScaffold(
|
return SettingsPageScaffold(
|
||||||
title: '设置',
|
title: '设置',
|
||||||
onBack: () => context.pop(),
|
onBack: () => returnToHomePreserveState(context, forceGoHome: true),
|
||||||
body: Column(
|
body: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ class _TodoQuadrantsScreenState extends State<TodoQuadrantsScreen> {
|
|||||||
canPop: false,
|
canPop: false,
|
||||||
onPopInvokedWithResult: (didPop, result) {
|
onPopInvokedWithResult: (didPop, result) {
|
||||||
if (!didPop) {
|
if (!didPop) {
|
||||||
returnToHomePreserveState(context);
|
returnToHomePreserveState(context, forceGoHome: true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
@@ -563,7 +563,7 @@ class _TodoQuadrantsScreenState extends State<TodoQuadrantsScreen> {
|
|||||||
context.push('${AppRoutes.calendarDayWeek}?date=$dateStr');
|
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() {
|
void main() {
|
||||||
group('resolveHomeReturnAction', () {
|
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', () {
|
test('business route with back stack prefers pop', () {
|
||||||
final action = resolveHomeReturnAction(canPop: true, isAuthEntry: false);
|
final action = resolveHomeReturnAction(canPop: true, isAuthEntry: false);
|
||||||
expect(action, HomeReturnAction.pop);
|
expect(action, HomeReturnAction.pop);
|
||||||
|
|||||||
Reference in New Issue
Block a user