Skip to content

Commit 204ed6b

Browse files
authored
fix: ios swipe back (#388)
* fix: ios swipe back * style: sort import * fix: use CupertinoPage for iOS * fix: route material * feat: predictive back for android * chore: remove unused import * feat: use builtin transition * fix: import * fix: builders
1 parent 507889c commit 204ed6b

6 files changed

Lines changed: 336 additions & 138 deletions

File tree

lib/app.dart

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
import 'dart:async';
22
import 'dart:io';
33

4+
import 'package:flutter/material.dart';
5+
6+
import 'package:dynamic_system_colors/dynamic_system_colors.dart';
7+
import 'package:i18n_extension/i18n_extension.dart';
8+
import 'package:in_app_update/in_app_update.dart';
9+
import 'package:provider/provider.dart';
10+
411
import 'package:dpip/core/notify.dart';
512
import 'package:dpip/core/providers.dart';
613
import 'package:dpip/models/settings/ui.dart';
714
import 'package:dpip/router.dart';
15+
import 'package:dpip/utils/constants.dart';
816
import 'package:dpip/utils/log.dart';
9-
import 'package:dynamic_system_colors/dynamic_system_colors.dart';
10-
import 'package:flutter/material.dart';
11-
import 'package:i18n_extension/i18n_extension.dart';
12-
import 'package:in_app_update/in_app_update.dart';
13-
import 'package:provider/provider.dart';
1417

1518
class DpipApp extends StatefulWidget {
1619
const DpipApp({super.key});
@@ -86,12 +89,14 @@ class _DpipAppState extends State<DpipApp> with WidgetsBindingObserver {
8689
colorScheme: model.themeColor == null ? lightDynamic : null,
8790
brightness: Brightness.light,
8891
snackBarTheme: const SnackBarThemeData(behavior: SnackBarBehavior.floating),
92+
pageTransitionsTheme: kZoomPageTransitionsTheme,
8993
);
9094
final darkTheme = ThemeData(
9195
colorSchemeSeed: model.themeColor,
9296
colorScheme: model.themeColor == null ? darkDynamic : null,
9397
brightness: Brightness.dark,
9498
snackBarTheme: const SnackBarThemeData(behavior: SnackBarBehavior.floating),
99+
pageTransitionsTheme: kZoomPageTransitionsTheme,
95100
);
96101

97102
return MaterialApp.router(

lib/router.dart

Lines changed: 43 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@ import 'package:dpip/app/welcome/layout.dart';
3838
import 'package:dpip/core/i18n.dart';
3939
import 'package:dpip/core/preference.dart';
4040
import 'package:dpip/route/announcement/announcement.dart';
41+
import 'package:dpip/utils/constants.dart';
42+
import 'package:dpip/utils/extensions/build_context.dart';
4143
import 'package:dpip/utils/log.dart';
42-
import 'package:dpip/widgets/transitions/forward_back.dart';
44+
import 'package:dpip/widgets/shell_wrapper.dart';
4345

4446
final GlobalKey<NavigatorState> _rootNavigatorKey = GlobalKey<NavigatorState>();
4547
final GlobalKey<NavigatorState> _welcomeNavigatorKey = GlobalKey<NavigatorState>();
@@ -51,45 +53,28 @@ final router = GoRouter(
5153
routes: [
5254
ShellRoute(
5355
navigatorKey: _welcomeNavigatorKey,
54-
builder: (context, state, child) => WelcomeLayout(child: child),
56+
builder: (context, state, child) => ShellWrapper(WelcomeLayout(child: child)),
5557
routes: [
56-
GoRoute(
57-
path: WelcomeAboutPage.route,
58-
pageBuilder:
59-
(context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const WelcomeAboutPage()),
60-
),
58+
GoRoute(path: WelcomeAboutPage.route, builder: (context, state) => const Material(child: WelcomeAboutPage())),
6159
GoRoute(
6260
path: WelcomeExpTechPage.route,
63-
pageBuilder:
64-
(context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const WelcomeExpTechPage()),
65-
),
66-
GoRoute(
67-
path: WelcomeNoticePage.route,
68-
pageBuilder:
69-
(context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const WelcomeNoticePage()),
61+
builder: (context, state) => const Material(child: WelcomeExpTechPage()),
7062
),
63+
GoRoute(path: WelcomeNoticePage.route, builder: (context, state) => const Material(child: WelcomeNoticePage())),
7164
GoRoute(
7265
path: WelcomePermissionPage.route,
73-
pageBuilder:
74-
(context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const WelcomePermissionPage()),
66+
builder: (context, state) => const Material(child: WelcomePermissionPage()),
7567
),
7668
],
7769
),
78-
GoRoute(
79-
path: HomePage.route,
80-
pageBuilder: (context, state) => const NoTransitionPage(
81-
child: AppLayout(
82-
child: HomePage(),
83-
),
84-
),
85-
),
70+
GoRoute(path: HomePage.route, builder: (context, state) => const AppLayout(child: HomePage())),
8671
ShellRoute(
8772
navigatorKey: _settingsNavigatorKey,
8873
builder: (context, state, child) {
8974
final title = switch (state.fullPath) {
9075
SettingsLocationPage.route => '所在地'.i18n,
91-
SettingsLocationSelectPage.route => '所在地'.i18n,
92-
final p when p == SettingsLocationSelectCityPage.route() => '所在地'.i18n,
76+
SettingsLocationSelectPage.route => '新增地點'.i18n,
77+
final p when p == SettingsLocationSelectCityPage.route() => '新增地點'.i18n,
9378
SettingsThemePage.route => '主題'.i18n,
9479
SettingsThemeSelectPage.route => '主題'.i18n,
9580
SettingsLocalePage.route => '語言'.i18n,
@@ -111,129 +96,92 @@ final router = GoRouter(
11196
SettingsDonatePage.route => '贊助我們'.i18n,
11297
_ => '設定'.i18n,
11398
};
114-
return SettingsLayout(title: title, child: child);
99+
100+
return ShellWrapper(
101+
SettingsLayout(
102+
title: title,
103+
child: Theme(
104+
data: context.theme.copyWith(pageTransitionsTheme: kFadeForwardPageTransitionsTheme),
105+
child: child,
106+
),
107+
),
108+
);
115109
},
116110
routes: [
117-
GoRoute(
118-
path: SettingsIndexPage.route,
119-
pageBuilder:
120-
(context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsIndexPage()),
121-
),
111+
GoRoute(path: SettingsIndexPage.route, builder: (context, state) => const Material(child: SettingsIndexPage())),
122112
GoRoute(
123113
path: SettingsLocationPage.route,
124-
pageBuilder:
125-
(context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsLocationPage()),
114+
builder: (context, state) => const Material(child: SettingsLocationPage()),
126115
),
127116
GoRoute(
128117
path: SettingsLocationSelectPage.route,
129-
pageBuilder:
130-
(context, state) =>
131-
ForwardBackTransitionPage(key: state.pageKey, child: const SettingsLocationSelectPage()),
118+
builder: (context, state) => const Material(child: SettingsLocationSelectPage()),
132119
),
133120
GoRoute(
134121
path: SettingsLocationSelectCityPage.route(),
135-
pageBuilder:
136-
(context, state) => ForwardBackTransitionPage(
137-
key: state.pageKey,
138-
child: SettingsLocationSelectCityPage(city: state.pathParameters['city']!),
139-
),
140-
),
141-
GoRoute(
142-
path: SettingsThemePage.route,
143-
pageBuilder:
144-
(context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsThemePage()),
122+
builder:
123+
(context, state) => Material(child: SettingsLocationSelectCityPage(city: state.pathParameters['city']!)),
145124
),
125+
GoRoute(path: SettingsThemePage.route, builder: (context, state) => const Material(child: SettingsThemePage())),
146126
GoRoute(
147127
path: SettingsThemeSelectPage.route,
148-
pageBuilder:
149-
(context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsThemeSelectPage()),
128+
builder: (context, state) => const Material(child: SettingsThemeSelectPage()),
150129
),
151130
GoRoute(
152131
path: SettingsLocalePage.route,
153-
pageBuilder:
154-
(context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsLocalePage()),
132+
builder: (context, state) => const Material(child: SettingsLocalePage()),
155133
),
156134
GoRoute(
157135
path: SettingsLocaleSelectPage.route,
158-
pageBuilder:
159-
(context, state) =>
160-
ForwardBackTransitionPage(key: state.pageKey, child: const SettingsLocaleSelectPage()),
161-
),
162-
GoRoute(
163-
path: SettingsUnitPage.route,
164-
pageBuilder:
165-
(context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsUnitPage()),
166-
),
167-
GoRoute(
168-
path: SettingsMapPage.route,
169-
pageBuilder:
170-
(context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsMapPage()),
136+
builder: (context, state) => const Material(child: SettingsLocaleSelectPage()),
171137
),
138+
GoRoute(path: SettingsUnitPage.route, builder: (context, state) => const Material(child: SettingsUnitPage())),
139+
GoRoute(path: SettingsMapPage.route, builder: (context, state) => const Material(child: SettingsMapPage())),
172140
GoRoute(
173141
path: SettingsNotifyPage.route,
174-
pageBuilder:
175-
(context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyPage()),
142+
builder: (context, state) => const Material(child: SettingsNotifyPage()),
176143
routes: [
177144
GoRoute(
178145
path: SettingsNotifyEewPage.name,
179-
pageBuilder:
180-
(context, state) =>
181-
ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyEewPage()),
146+
builder: (context, state) => const Material(child: SettingsNotifyEewPage()),
182147
),
183148
GoRoute(
184149
path: SettingsNotifyMonitorPage.name,
185-
pageBuilder:
186-
(context, state) =>
187-
ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyMonitorPage()),
150+
builder: (context, state) => const Material(child: SettingsNotifyMonitorPage()),
188151
),
189152
GoRoute(
190153
path: SettingsNotifyReportPage.name,
191-
pageBuilder:
192-
(context, state) =>
193-
ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyReportPage()),
154+
builder: (context, state) => const Material(child: SettingsNotifyReportPage()),
194155
),
195156
GoRoute(
196157
path: SettingsNotifyIntensityPage.name,
197-
pageBuilder:
198-
(context, state) =>
199-
ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyIntensityPage()),
158+
builder: (context, state) => const Material(child: SettingsNotifyIntensityPage()),
200159
),
201160
GoRoute(
202161
path: SettingsNotifyThunderstormPage.name,
203-
pageBuilder:
204-
(context, state) =>
205-
ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyThunderstormPage()),
162+
builder: (context, state) => const Material(child: SettingsNotifyThunderstormPage()),
206163
),
207164
GoRoute(
208165
path: SettingsNotifyAdvisoryPage.name,
209-
pageBuilder:
210-
(context, state) =>
211-
ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyAdvisoryPage()),
166+
builder: (context, state) => const Material(child: SettingsNotifyAdvisoryPage()),
212167
),
213168
GoRoute(
214169
path: SettingsNotifyEvacuationPage.name,
215-
pageBuilder:
216-
(context, state) =>
217-
ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyEvacuationPage()),
170+
builder: (context, state) => const Material(child: SettingsNotifyEvacuationPage()),
218171
),
219172
GoRoute(
220173
path: SettingsNotifyTsunamiPage.name,
221-
pageBuilder:
222-
(context, state) =>
223-
ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyTsunamiPage()),
174+
builder: (context, state) => const Material(child: SettingsNotifyTsunamiPage()),
224175
),
225176
GoRoute(
226177
path: SettingsNotifyAnnouncementPage.name,
227-
pageBuilder:
228-
(context, state) =>
229-
ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyAnnouncementPage()),
178+
builder: (context, state) => const Material(child: SettingsNotifyAnnouncementPage()),
230179
),
231180
],
232181
),
233182
GoRoute(
234183
path: SettingsDonatePage.route,
235-
pageBuilder:
236-
(context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsDonatePage()),
184+
builder: (context, state) => const Material(child: SettingsDonatePage()),
237185
),
238186
],
239187
),

lib/utils/constants.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
import 'package:flutter/material.dart';
2+
23
import 'package:maplibre_gl/maplibre_gl.dart';
34

5+
import 'package:dpip/widgets/transitions/predictive_fade_forward.dart';
6+
7+
const kZoomPageTransitionsTheme = PageTransitionsTheme(
8+
builders: {
9+
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
10+
TargetPlatform.android: PredictiveBackPageTransitionsBuilder(),
11+
},
12+
);
13+
14+
const kFadeForwardPageTransitionsTheme = PageTransitionsTheme(
15+
builders: {
16+
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
17+
TargetPlatform.android: PredictiveBackFadeForwardPageTransitionsBuilder(),
18+
},
19+
);
20+
421
const kEmphasizedAnimationStyle = AnimationStyle(
522
curve: Easing.emphasizedDecelerate,
623
duration: Durations.medium4,

lib/widgets/shell_wrapper.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import 'package:flutter/material.dart';
2+
3+
import 'package:go_router/go_router.dart';
4+
5+
class ShellWrapper extends StatelessWidget {
6+
final Widget child;
7+
8+
const ShellWrapper(this.child, {super.key});
9+
10+
bool _canPop(BuildContext context) {
11+
final lastMatch = GoRouter.of(context).routerDelegate.currentConfiguration.matches.lastOrNull;
12+
13+
if (lastMatch is ShellRouteMatch) {
14+
return lastMatch.matches.length == 1;
15+
}
16+
17+
return true;
18+
}
19+
20+
@override
21+
Widget build(BuildContext context) => PopScope(canPop: _canPop(context), child: child);
22+
}

lib/widgets/transitions/forward_back.dart

Lines changed: 0 additions & 38 deletions
This file was deleted.

0 commit comments

Comments
 (0)