diff --git a/app/lib/screens/app_onboarding/loading_screen.dart b/app/lib/screens/app_onboarding/loading_screen.dart index 2f9ef0a96..eab436d62 100644 --- a/app/lib/screens/app_onboarding/loading_screen.dart +++ b/app/lib/screens/app_onboarding/loading_screen.dart @@ -80,6 +80,8 @@ class _LoadingScreenState extends State { subject = await _fetchRemoteSubject(selectedStudyObjectId); } } catch (exception) { + debugPrint( + "Could not login and retrieve the study subject: $exception"); if (exception is SocketException) { subject = await Cache.loadSubject(); StudyULogger.info("Offline mode with cached subject: $subject"); diff --git a/app/lib/util/cache.dart b/app/lib/util/cache.dart index 6ec61c131..47d57fdbe 100644 --- a/app/lib/util/cache.dart +++ b/app/lib/util/cache.dart @@ -16,13 +16,29 @@ class Cache { assert(subject == (await loadSubject())); } - static Future loadSubject() async { + static Future loadSubject({StudySubject? backupSubject}) async { // debugPrint("Load subject from cache"); if (await SecureStorage.containsKey(cacheSubjectKey)) { - return StudySubject.fromJson( - jsonDecode((await SecureStorage.read(cacheSubjectKey))!) - as Map, - ); + final cachedSubjectStr = await SecureStorage.read(cacheSubjectKey); + final cachedSubject = + jsonDecode(cachedSubjectStr!) as Map; + try { + return StudySubject.fromJson(cachedSubject); + } catch (e) { + StudyULogger.warning( + "Failed to parse cached subject: $cachedSubjectStr", + ); + if (backupSubject != null) { + // Only take progress from cached subject and rest from backup, + // as the cached subject might be outdated or corrupted + final cachedProgress = (cachedSubject['progress'] as List?) + ?.map((e) => SubjectProgress.fromJson(e as Map)) + .toList(); + backupSubject.progress = cachedProgress ?? backupSubject.progress; + return backupSubject; + } + throw Exception("No backup subject provided"); + } } else { throw Exception("No cached subject found"); } @@ -69,7 +85,7 @@ class Cache { if (!(await SecureStorage.containsKey(cacheSubjectKey))) { return remoteSubject; } - final localSubject = await loadSubject(); + final localSubject = await loadSubject(backupSubject: remoteSubject); // local and remote subject are equal, nothing to synchronize if (localSubject == remoteSubject) return remoteSubject; // remote subject belongs to a different study