Skip to content

Commit b264e48

Browse files
committed
Merge remote-tracking branch 'origin/main' into feature/social-login-loading-gates
# Conflicts: # lib/presentation/shared/router/go_router.dart
2 parents 0823f9c + 77608a3 commit b264e48

3 files changed

Lines changed: 357 additions & 53 deletions

File tree

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:go_router/go_router.dart';
3+
4+
enum AppRouteTransition {
5+
fade,
6+
standard,
7+
bottomNavFromLeft,
8+
bottomNavFromRight,
9+
scheduleFlow,
10+
}
11+
12+
CustomTransitionPage<T> buildAppRoutePage<T>({
13+
required LocalKey key,
14+
required Widget child,
15+
AppRouteTransition transition = AppRouteTransition.standard,
16+
}) {
17+
final spec = _AppRouteTransitionSpec.fromTransition(transition);
18+
19+
return CustomTransitionPage<T>(
20+
key: key,
21+
transitionDuration: spec.duration,
22+
reverseTransitionDuration: spec.reverseDuration,
23+
child: child,
24+
transitionsBuilder: (context, animation, secondaryAnimation, child) {
25+
return _AppRouteTransitionView(
26+
animation: animation,
27+
transition: transition,
28+
child: child,
29+
);
30+
},
31+
);
32+
}
33+
34+
class _AppRouteTransitionSpec {
35+
const _AppRouteTransitionSpec({
36+
required this.duration,
37+
required this.reverseDuration,
38+
});
39+
40+
final Duration duration;
41+
final Duration reverseDuration;
42+
43+
static _AppRouteTransitionSpec fromTransition(AppRouteTransition transition) {
44+
switch (transition) {
45+
case AppRouteTransition.fade:
46+
return const _AppRouteTransitionSpec(
47+
duration: Duration(milliseconds: 180),
48+
reverseDuration: Duration(milliseconds: 140),
49+
);
50+
case AppRouteTransition.standard:
51+
return const _AppRouteTransitionSpec(
52+
duration: Duration(milliseconds: 260),
53+
reverseDuration: Duration(milliseconds: 220),
54+
);
55+
case AppRouteTransition.bottomNavFromLeft:
56+
case AppRouteTransition.bottomNavFromRight:
57+
return const _AppRouteTransitionSpec(
58+
duration: Duration(milliseconds: 220),
59+
reverseDuration: Duration(milliseconds: 180),
60+
);
61+
case AppRouteTransition.scheduleFlow:
62+
return const _AppRouteTransitionSpec(
63+
duration: Duration(milliseconds: 200),
64+
reverseDuration: Duration(milliseconds: 160),
65+
);
66+
}
67+
}
68+
}
69+
70+
class _AppRouteTransitionView extends StatelessWidget {
71+
const _AppRouteTransitionView({
72+
required this.animation,
73+
required this.transition,
74+
required this.child,
75+
});
76+
77+
final Animation<double> animation;
78+
final AppRouteTransition transition;
79+
final Widget child;
80+
81+
@override
82+
Widget build(BuildContext context) {
83+
switch (transition) {
84+
case AppRouteTransition.fade:
85+
return FadeTransition(
86+
opacity: _curvedOpacityAnimation(animation, begin: 0),
87+
child: child,
88+
);
89+
case AppRouteTransition.standard:
90+
return FadeTransition(
91+
opacity: _curvedOpacityAnimation(animation, begin: 0.08),
92+
child: SlideTransition(
93+
position: _curvedOffsetAnimation(
94+
animation,
95+
begin: const Offset(0, 0.032),
96+
),
97+
child: child,
98+
),
99+
);
100+
case AppRouteTransition.bottomNavFromLeft:
101+
return FadeTransition(
102+
opacity: _curvedOpacityAnimation(animation, begin: 0.2),
103+
child: SlideTransition(
104+
position: _curvedOffsetAnimation(
105+
animation,
106+
begin: const Offset(-0.16, 0),
107+
),
108+
child: child,
109+
),
110+
);
111+
case AppRouteTransition.bottomNavFromRight:
112+
return FadeTransition(
113+
opacity: _curvedOpacityAnimation(animation, begin: 0.2),
114+
child: SlideTransition(
115+
position: _curvedOffsetAnimation(
116+
animation,
117+
begin: const Offset(0.16, 0),
118+
),
119+
child: child,
120+
),
121+
);
122+
case AppRouteTransition.scheduleFlow:
123+
return FadeTransition(
124+
opacity: _curvedOpacityAnimation(animation, begin: 0),
125+
child: ScaleTransition(
126+
scale: Tween<double>(begin: 0.985, end: 1).animate(
127+
CurvedAnimation(parent: animation, curve: Curves.easeOutCubic),
128+
),
129+
child: child,
130+
),
131+
);
132+
}
133+
}
134+
135+
Animation<double> _curvedOpacityAnimation(
136+
Animation<double> animation, {
137+
required double begin,
138+
}) {
139+
return Tween<double>(
140+
begin: begin,
141+
end: 1,
142+
).animate(CurvedAnimation(parent: animation, curve: Curves.easeOutCubic));
143+
}
144+
145+
Animation<Offset> _curvedOffsetAnimation(
146+
Animation<double> animation, {
147+
required Offset begin,
148+
}) {
149+
return Tween<Offset>(
150+
begin: begin,
151+
end: Offset.zero,
152+
).animate(CurvedAnimation(parent: animation, curve: Curves.easeOutCubic));
153+
}
154+
}

lib/presentation/shared/router/go_router.dart

Lines changed: 93 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_pr
2525
import 'package:on_time_front/presentation/schedule_create/screens/schedule_create_screen.dart';
2626
import 'package:on_time_front/presentation/schedule_create/screens/schedule_edit_screen.dart';
2727
import 'package:on_time_front/presentation/shared/components/bottom_nav_bar_scaffold.dart';
28+
import 'package:on_time_front/presentation/shared/router/app_route_transition.dart';
2829
import 'package:on_time_front/presentation/shared/router/route_arguments.dart';
2930
import 'package:on_time_front/presentation/shared/utils/stream_to_listenable.dart';
3031
import 'package:on_time_front/presentation/startup/screens/startup_screen.dart';
@@ -57,25 +58,43 @@ GoRouter goRouterConfig(
5758
routes: [
5859
GoRoute(
5960
path: '/startup',
60-
builder: (context, state) => const StartupScreen(),
61+
pageBuilder: (context, state) => _buildAppRoutePage(
62+
state: state,
63+
transition: AppRouteTransition.fade,
64+
child: const StartupScreen(),
65+
),
6166
),
6267
GoRoute(
6368
path: '/allowNotification',
64-
builder: (context, state) {
65-
return NotificationAllowScreen();
66-
},
69+
pageBuilder: (context, state) => _buildAppRoutePage(
70+
state: state,
71+
transition: AppRouteTransition.fade,
72+
child: NotificationAllowScreen(),
73+
),
6774
),
6875
GoRoute(
6976
path: '/allowAlarm',
70-
builder: (context, state) => const AlarmAllowScreen(),
77+
pageBuilder: (context, state) => _buildAppRoutePage(
78+
state: state,
79+
transition: AppRouteTransition.fade,
80+
child: const AlarmAllowScreen(),
81+
),
7182
),
7283
GoRoute(
7384
path: '/onboarding',
74-
builder: (context, state) => OnboardingScreen(),
85+
pageBuilder: (context, state) => _buildAppRoutePage(
86+
state: state,
87+
transition: AppRouteTransition.fade,
88+
child: OnboardingScreen(),
89+
),
7590
routes: [
7691
GoRoute(
7792
path: '/start',
78-
builder: (context, state) => OnboardingStartScreen(),
93+
pageBuilder: (context, state) => _buildAppRoutePage(
94+
state: state,
95+
transition: AppRouteTransition.fade,
96+
child: OnboardingStartScreen(),
97+
),
7998
),
8099
],
81100
),
@@ -84,58 +103,86 @@ GoRouter goRouterConfig(
84103
routes: [
85104
GoRoute(
86105
path: '/home',
87-
pageBuilder: (context, state) => _buildBottomNavSlidePage(
106+
pageBuilder: (context, state) => _buildAppRoutePage(
88107
state: state,
89-
beginOffset: const Offset(-1, 0),
108+
transition: AppRouteTransition.bottomNavFromLeft,
90109
child: HomeScreenTmp(),
91110
),
92111
),
93112
GoRoute(
94113
path: '/myPage',
95-
pageBuilder: (context, state) => _buildBottomNavSlidePage(
114+
pageBuilder: (context, state) => _buildAppRoutePage(
96115
state: state,
97-
beginOffset: const Offset(1, 0),
116+
transition: AppRouteTransition.bottomNavFromRight,
98117
child: MyPageScreen(),
99118
),
100119
),
101120
],
102121
),
103122
GoRoute(
104123
path: '/defaultPreparationSpareTimeEdit',
105-
builder: (context, state) => PreparationSpareTimeEditScreen(),
124+
pageBuilder: (context, state) => _buildAppRoutePage(
125+
state: state,
126+
child: PreparationSpareTimeEditScreen(),
127+
),
128+
),
129+
GoRoute(
130+
path: '/signIn',
131+
pageBuilder: (context, state) => _buildAppRoutePage(
132+
state: state,
133+
transition: AppRouteTransition.fade,
134+
child: SignInMainScreen(),
135+
),
106136
),
107-
GoRoute(path: '/signIn', builder: (context, state) => SignInMainScreen()),
108137
GoRoute(
109138
path: '/calendar',
110-
builder: (context, state) =>
111-
CalendarScreen(initialDate: calendarInitialDateFromState(state)),
139+
pageBuilder: (context, state) => _buildAppRoutePage(
140+
state: state,
141+
child: CalendarScreen(
142+
initialDate: calendarInitialDateFromState(state),
143+
),
144+
),
112145
),
113146
GoRoute(
114147
path: '/scheduleCreate',
115-
builder: (context, state) => ScheduleCreateScreen(),
148+
pageBuilder: (context, state) =>
149+
_buildAppRoutePage(state: state, child: ScheduleCreateScreen()),
116150
),
117151
GoRoute(
118152
path: '/scheduleEdit/:scheduleId',
119-
builder: (context, state) =>
120-
ScheduleEditScreen(scheduleId: state.pathParameters['scheduleId']!),
153+
pageBuilder: (context, state) => _buildAppRoutePage(
154+
state: state,
155+
child: ScheduleEditScreen(
156+
scheduleId: state.pathParameters['scheduleId']!,
157+
),
158+
),
121159
),
122160
GoRoute(
123161
path: '/preparationEdit',
124-
builder: (context, state) => const PreparationEditForm(),
162+
pageBuilder: (context, state) => _buildAppRoutePage(
163+
state: state,
164+
child: const PreparationEditForm(),
165+
),
125166
),
126167
GoRoute(
127168
path: '/scheduleStart',
128169
name: 'scheduleStart',
129-
builder: (context, state) {
170+
pageBuilder: (context, state) {
130171
final extra = scheduleStartRouteExtraFromState(state);
131-
return _ScheduleStartRouteGate(extra: extra);
172+
return _buildAppRoutePage(
173+
state: state,
174+
transition: AppRouteTransition.scheduleFlow,
175+
child: _ScheduleStartRouteGate(extra: extra),
176+
);
132177
},
133178
),
134179
GoRoute(
135180
path: '/alarmScreen',
136-
builder: (context, state) {
137-
return AlarmScreen();
138-
},
181+
pageBuilder: (context, state) => _buildAppRoutePage(
182+
state: state,
183+
transition: AppRouteTransition.scheduleFlow,
184+
child: AlarmScreen(),
185+
),
139186
),
140187
GoRoute(
141188
path: '/earlyLate',
@@ -144,19 +191,31 @@ GoRouter goRouterConfig(
144191
? '/home'
145192
: null;
146193
},
147-
builder: (context, state) {
194+
pageBuilder: (context, state) {
148195
final arguments = earlyLateRouteArgumentsFromState(state);
149196
if (arguments == null) {
150-
return const LoadingScreen();
197+
return _buildAppRoutePage(
198+
state: state,
199+
transition: AppRouteTransition.scheduleFlow,
200+
child: const LoadingScreen(),
201+
);
151202
}
152203

153-
return EarlyLateScreen(
154-
earlyLateTime: arguments.earlyLateTime,
155-
isLate: arguments.isLate,
204+
return _buildAppRoutePage(
205+
state: state,
206+
transition: AppRouteTransition.scheduleFlow,
207+
child: EarlyLateScreen(
208+
earlyLateTime: arguments.earlyLateTime,
209+
isLate: arguments.isLate,
210+
),
156211
);
157212
},
158213
),
159-
GoRoute(path: '/moving', builder: (context, state) => MovingScreen()),
214+
GoRoute(
215+
path: '/moving',
216+
pageBuilder: (context, state) =>
217+
_buildAppRoutePage(state: state, child: MovingScreen()),
218+
),
160219
],
161220
);
162221
}
@@ -198,34 +257,15 @@ String? appRedirectLocation({
198257
}
199258
}
200259

201-
CustomTransitionPage<void> _buildBottomNavSlidePage({
260+
CustomTransitionPage<void> _buildAppRoutePage({
202261
required GoRouterState state,
203-
required Offset beginOffset,
262+
AppRouteTransition transition = AppRouteTransition.standard,
204263
required Widget child,
205264
}) {
206-
final slideTween = Tween<Offset>(
207-
begin: beginOffset,
208-
end: Offset.zero,
209-
).chain(CurveTween(curve: Curves.easeOutCubic));
210-
final secondarySlideTween = Tween<Offset>(
211-
begin: Offset.zero,
212-
end: beginOffset,
213-
).chain(CurveTween(curve: Curves.easeOutCubic));
214-
215-
return CustomTransitionPage<void>(
265+
return buildAppRoutePage<void>(
216266
key: state.pageKey,
217-
transitionDuration: const Duration(milliseconds: 280),
218-
reverseTransitionDuration: const Duration(milliseconds: 280),
267+
transition: transition,
219268
child: child,
220-
transitionsBuilder: (context, animation, secondaryAnimation, child) {
221-
return SlideTransition(
222-
position: secondaryAnimation.drive(secondarySlideTween),
223-
child: SlideTransition(
224-
position: animation.drive(slideTween),
225-
child: child,
226-
),
227-
);
228-
},
229269
);
230270
}
231271

0 commit comments

Comments
 (0)