Skip to content

Commit f7d9a93

Browse files
committed
refactor: enforce a minimum display duration for the splash screen
1 parent e745256 commit f7d9a93

File tree

1 file changed

+66
-8
lines changed

1 file changed

+66
-8
lines changed

lib/app/view/app.dart

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,28 +70,68 @@ class _AppView extends StatefulWidget {
7070

7171
class _AppViewState extends State<_AppView> {
7272
late final GoRouter _router;
73-
late final ValueNotifier<AppStatus> _statusNotifier;
73+
// Notifier that GoRouter listens to. We control its value.
74+
late final ValueNotifier<AppStatus> _routerNotifier;
7475
StreamSubscription<PendingDynamicLinkData>? _linkSubscription;
7576

77+
// Flags to manage splash screen duration
78+
bool _isAuthStatusKnown = false;
79+
bool _isMinTimeElapsed = false;
80+
// Store the actual latest status from AppBloc
81+
AppStatus _currentAppStatus = AppStatus.initial;
82+
83+
// Minimum splash duration
84+
static const _minSplashDuration = Duration(seconds: 2);
85+
7686
@override
7787
void initState() {
7888
super.initState();
7989
final appBloc = context.read<AppBloc>();
80-
_statusNotifier = ValueNotifier<AppStatus>(appBloc.state.status);
81-
_router = createRouter(authStatusNotifier: _statusNotifier);
90+
_currentAppStatus = appBloc.state.status; // Store initial status
91+
// Initialize the router notifier with the initial status
92+
_routerNotifier = ValueNotifier<AppStatus>(_currentAppStatus);
93+
_router = createRouter(authStatusNotifier: _routerNotifier);
94+
95+
// Start the minimum time timer
96+
Future.delayed(_minSplashDuration, () {
97+
if (mounted) {
98+
setState(() {
99+
_isMinTimeElapsed = true;
100+
});
101+
_updateRouterNotifier(); // Check if we can navigate away
102+
}
103+
});
82104

83105
// --- Initialize Deep Link Handling ---
84106
_initDynamicLinks();
85107
// ------------------------------------
108+
109+
// Initial check in case status is already known *at the end of initState*
110+
if (_currentAppStatus != AppStatus.initial) {
111+
_isAuthStatusKnown = true;
112+
_updateRouterNotifier();
113+
}
86114
}
87115

88116
@override
89117
void dispose() {
90118
_linkSubscription?.cancel();
91-
_statusNotifier.dispose();
119+
_routerNotifier.dispose(); // Dispose the correct notifier
92120
super.dispose();
93121
}
94122

123+
/// Checks conditions and updates the router notifier if ready.
124+
void _updateRouterNotifier() {
125+
// Only update the router notifier (triggering redirect) if both
126+
// minimum time has passed AND the auth status is known.
127+
if (_isMinTimeElapsed && _isAuthStatusKnown) {
128+
// Update with the *actual* current status
129+
_routerNotifier.value = _currentAppStatus;
130+
}
131+
// Otherwise, the router notifier remains AppStatus.initial, keeping
132+
// the user on the splash screen.
133+
}
134+
95135
/// Initializes Firebase Dynamic Links listeners.
96136
Future<void> _initDynamicLinks() async {
97137
// Handle links received while the app is running
@@ -168,13 +208,31 @@ class _AppViewState extends State<_AppView> {
168208
// The BlocBuilder remains for theme changes.
169209
return BlocListener<AppBloc, AppState>(
170210
// Only listen when the status actually changes
171-
listenWhen: (previous, current) => previous.status != current.status,
211+
// Listen to all status changes from AppBloc
172212
listener: (context, state) {
173-
// Update the ValueNotifier when the AppBloc status changes.
174-
// This triggers the GoRouter's refreshListenable.
175-
_statusNotifier.value = state.status;
213+
// Store the latest actual status
214+
_currentAppStatus = state.status;
215+
216+
// If the status is no longer initial, mark it as known
217+
if (state.status != AppStatus.initial) {
218+
if (!_isAuthStatusKnown) { // Only update state if it changes
219+
setState(() {
220+
_isAuthStatusKnown = true;
221+
});
222+
}
223+
_updateRouterNotifier(); // Check if we can navigate away
224+
}
225+
// If the status somehow reverts to initial (unlikely), reset flag
226+
else if (_isAuthStatusKnown) {
227+
setState(() {
228+
_isAuthStatusKnown = false;
229+
});
230+
// Ensure router notifier reflects initial state again
231+
_routerNotifier.value = AppStatus.initial;
232+
}
176233
},
177234
child: BlocBuilder<AppBloc, AppState>(
235+
// Build only for theme changes, listener handles status
178236
buildWhen:
179237
(previous, current) => previous.themeMode != current.themeMode,
180238
builder: (context, state) {

0 commit comments

Comments
 (0)