@@ -213,51 +213,26 @@ class AppState extends ChangeNotifier {
213213 // Settings must init first — other modules read its values
214214 await _settingsState.init ();
215215
216- // Initialize changelog service
217- await ChangelogService ().init ();
218-
219216 // Fire-and-forget tile preview fetch (existing pattern)
220217 _fetchMissingTilePreviews ();
221218
222- // Check if we should add default profiles (first launch OR no profiles of each type exist)
223- const firstLaunchKey = 'profiles_defaults_initialized' ;
224- final prefsForProfiles = await SharedPreferences .getInstance ();
225- final isFirstLaunch = ! (prefsForProfiles.getBool (firstLaunchKey) ?? false );
226-
227- final existingOperatorProfiles = await OperatorProfileService ().load ();
228- final existingNodeProfiles = await ProfileService ().load ();
229-
230- final shouldAddOperatorDefaults = isFirstLaunch || existingOperatorProfiles.isEmpty;
231- final shouldAddNodeDefaults = isFirstLaunch || existingNodeProfiles.isEmpty;
232-
233- await _operatorProfileState.init (addDefaults: shouldAddOperatorDefaults);
234- await _profileState.init (addDefaults: shouldAddNodeDefaults);
235-
236- // Set up callback to clear stale sessions when profiles are deleted
219+ // Run independent init steps in parallel.
220+ // Each step is wrapped in try-catch so a failure in one doesn't
221+ // prevent the others from completing via Future.wait.
222+ await Future .wait ([
223+ _guardInit ('changelog' , () => ChangelogService ().init ()),
224+ _initProfiles (),
225+ _guardInit ('suspected locations' , () => _suspectedLocationState.initLocal ()),
226+ _guardInit ('upload queue' , () => _uploadQueueState.init ()),
227+ _guardInit ('auth' , () => _authState.init (_settingsState.uploadMode)),
228+ _initOfflineData (),
229+ ]);
230+
231+ // Post-parallel setup (depends on results above)
237232 _profileState.setProfileDeletedCallback (_onProfileDeleted);
238-
239- if (isFirstLaunch) {
240- await prefsForProfiles.setBool (firstLaunchKey, true );
241- }
242-
243- // Local-only init for suspected locations (no network)
244- await _suspectedLocationState.initLocal ();
245- await _uploadQueueState.init ();
246- // Local-only auth init (no network)
247- await _authState.init (_settingsState.uploadMode);
248-
249- // Set up callback to repopulate pending nodes after cache clears
250233 NodeProviderWithCache .instance.setOnCacheClearedCallback (() {
251234 _uploadQueueState.repopulateCacheFromQueue ();
252235 });
253-
254- // Initialize OfflineAreaService to ensure offline areas are loaded
255- await OfflineAreaService ().ensureInitialized ();
256-
257- // Preload offline nodes into cache for immediate display
258- await NodeDataManager ().preloadOfflineNodes ();
259-
260- // Start uploader if conditions are met
261236 _startUploader ();
262237
263238 _isInitialized = true ;
@@ -288,9 +263,55 @@ class AppState extends ChangeNotifier {
288263 }
289264 }
290265
266+ /// Load profiles and handle first-launch defaults.
267+ Future <void > _initProfiles () async {
268+ try {
269+ final prefs = await SharedPreferences .getInstance ();
270+ const firstLaunchKey = 'profiles_defaults_initialized' ;
271+ final isFirstLaunch = ! (prefs.getBool (firstLaunchKey) ?? false );
272+
273+ final existingOperatorProfiles = await OperatorProfileService ().load ();
274+ final existingNodeProfiles = await ProfileService ().load ();
275+
276+ final shouldAddOperatorDefaults = isFirstLaunch || existingOperatorProfiles.isEmpty;
277+ final shouldAddNodeDefaults = isFirstLaunch || existingNodeProfiles.isEmpty;
278+
279+ await _operatorProfileState.init (addDefaults: shouldAddOperatorDefaults);
280+ await _profileState.init (addDefaults: shouldAddNodeDefaults);
281+
282+ if (isFirstLaunch) {
283+ await prefs.setBool (firstLaunchKey, true );
284+ }
285+ } catch (e, stackTrace) {
286+ debugPrint ('[AppState] Error initializing profiles: $e ' );
287+ debugPrint ('[AppState] Stack trace: $stackTrace ' );
288+ }
289+ }
290+
291+ /// Initialize offline area service and preload offline nodes.
292+ Future <void > _initOfflineData () async {
293+ try {
294+ await OfflineAreaService ().ensureInitialized ();
295+ await NodeDataManager ().preloadOfflineNodes ();
296+ } catch (e, stackTrace) {
297+ debugPrint ('[AppState] Error initializing offline data: $e ' );
298+ debugPrint ('[AppState] Stack trace: $stackTrace ' );
299+ }
300+ }
301+
302+ /// Run an init step inside try-catch so it can't break Future.wait.
303+ Future <void > _guardInit (String label, Future <void > Function () fn) async {
304+ try {
305+ await fn ();
306+ } catch (e, stackTrace) {
307+ debugPrint ('[AppState] Error initializing $label : $e ' );
308+ debugPrint ('[AppState] Stack trace: $stackTrace ' );
309+ }
310+ }
311+
291312 void _startMessageCheckTimer () {
292313 _messageCheckTimer? .cancel ();
293-
314+
294315 // Check messages every 10 minutes when logged in
295316 _messageCheckTimer = Timer .periodic (
296317 const Duration (minutes: 10 ),
0 commit comments