From 9f5432d7acd5d2f91dbf1b380247bf2b9347c08b Mon Sep 17 00:00:00 2001 From: Akshay Nandwana Date: Fri, 11 Oct 2024 05:13:28 +0530 Subject: [PATCH 1/2] added null check --- .../LocationOfInterestRepository.kt | 16 ++++++++-- .../ground/repository/SubmissionRepository.kt | 30 ++++++++++--------- .../datacollection/DataCollectionViewModel.kt | 7 +++-- .../ui/syncstatus/SyncStatusViewModel.kt | 10 +++++-- 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/ground/src/main/java/com/google/android/ground/repository/LocationOfInterestRepository.kt b/ground/src/main/java/com/google/android/ground/repository/LocationOfInterestRepository.kt index 5de67ab7c0..81d7bd18d8 100644 --- a/ground/src/main/java/com/google/android/ground/repository/LocationOfInterestRepository.kt +++ b/ground/src/main/java/com/google/android/ground/repository/LocationOfInterestRepository.kt @@ -38,6 +38,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.map +import timber.log.Timber /** * Coordinates persistence and retrieval of [LocationOfInterest] instances from remote, local, and @@ -88,9 +89,18 @@ constructor( } /** This only works if the survey and location of interests are already cached to local db. */ - suspend fun getOfflineLoi(surveyId: String, loiId: String): LocationOfInterest { - val survey = localSurveyStore.getSurveyById(surveyId) ?: error("Survey not found: $surveyId") - return localLoiStore.getLocationOfInterest(survey, loiId) ?: error("LOI not found: $loiId") + suspend fun getOfflineLoi(surveyId: String, loiId: String): LocationOfInterest? { + val survey = localSurveyStore.getSurveyById(surveyId) + if (survey == null) { + Timber.e("LocationOfInterestRepository", "Survey not found: $surveyId") + return null + } + val locationOfInterest = localLoiStore.getLocationOfInterest(survey, loiId) + if (locationOfInterest == null) { + Timber.e("LocationRepository", "LOI not found for survey $surveyId: LOI ID $loiId") + return null + } + return locationOfInterest } /** Saves a new LOI in the local db and enqueues a sync worker. */ diff --git a/ground/src/main/java/com/google/android/ground/repository/SubmissionRepository.kt b/ground/src/main/java/com/google/android/ground/repository/SubmissionRepository.kt index 47a8e1e5b9..c348dca40b 100644 --- a/ground/src/main/java/com/google/android/ground/repository/SubmissionRepository.kt +++ b/ground/src/main/java/com/google/android/ground/repository/SubmissionRepository.kt @@ -56,20 +56,22 @@ constructor( ) { val newId = uuidGenerator.generateUuid() val userId = userRepository.getAuthenticatedUser().id - val job = locationOfInterestRepository.getOfflineLoi(surveyId, locationOfInterestId).job - val mutation = - SubmissionMutation( - job = job, - submissionId = newId, - deltas = deltas, - type = Mutation.Type.CREATE, - syncStatus = SyncStatus.PENDING, - surveyId = surveyId, - locationOfInterestId = locationOfInterestId, - userId = userId, - collectionId = collectionId, - ) - applyAndEnqueue(mutation) + val job = locationOfInterestRepository.getOfflineLoi(surveyId, locationOfInterestId)?.job + job?.let { + val mutation = + SubmissionMutation( + job = job, + submissionId = newId, + deltas = deltas, + type = Mutation.Type.CREATE, + syncStatus = SyncStatus.PENDING, + surveyId = surveyId, + locationOfInterestId = locationOfInterestId, + userId = userId, + collectionId = collectionId, + ) + applyAndEnqueue(mutation) + } } suspend fun getDraftSubmission(draftSubmissionId: String, survey: Survey): DraftSubmission? = diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewModel.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewModel.kt index 7a41fb19e5..0c5d3f38e3 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewModel.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewModel.kt @@ -121,9 +121,10 @@ internal constructor( } else // LOI name pulled from LOI properties, if it exists. flow { - val loi = locationOfInterestRepository.getOfflineLoi(surveyId, loiId) - val label = locationOfInterestHelper.getDisplayLoiName(loi) - emit(label) + locationOfInterestRepository.getOfflineLoi(surveyId, loiId)?.let { + val label = locationOfInterestHelper.getDisplayLoiName(it) + emit(label) + } }) .stateIn(viewModelScope, SharingStarted.Lazily, "") diff --git a/ground/src/main/java/com/google/android/ground/ui/syncstatus/SyncStatusViewModel.kt b/ground/src/main/java/com/google/android/ground/ui/syncstatus/SyncStatusViewModel.kt index 43c25c1ffc..6d383eddb3 100644 --- a/ground/src/main/java/com/google/android/ground/ui/syncstatus/SyncStatusViewModel.kt +++ b/ground/src/main/java/com/google/android/ground/ui/syncstatus/SyncStatusViewModel.kt @@ -31,6 +31,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map +import timber.log.Timber /** * View model for the offline area manager fragment. Handles the current list of downloaded areas. @@ -61,11 +62,16 @@ internal constructor( private suspend fun loadLocationsOfInterestAndPair( mutations: List - ): List = mutations.map { toMutationDetail(it) } + ): List = mutations.mapNotNull { toMutationDetail(it) } - private suspend fun toMutationDetail(mutation: Mutation): MutationDetail { + private suspend fun toMutationDetail(mutation: Mutation): MutationDetail? { val loi = locationOfInterestRepository.getOfflineLoi(mutation.surveyId, mutation.locationOfInterestId) + if (loi == null) { + // If LOI is null, return null to avoid proceeding + Timber.e("MutationDetail", "LOI not found for mutation ${mutation.id}") + return null + } val user = userRepository.getAuthenticatedUser() return MutationDetail( user = user.displayName, From 9d359995c78f948c4865ac075b07526c1fb70aef Mon Sep 17 00:00:00 2001 From: Akshay Nandwana Date: Fri, 11 Oct 2024 05:25:19 +0530 Subject: [PATCH 2/2] return count fix --- .../ground/repository/LocationOfInterestRepository.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/ground/src/main/java/com/google/android/ground/repository/LocationOfInterestRepository.kt b/ground/src/main/java/com/google/android/ground/repository/LocationOfInterestRepository.kt index 81d7bd18d8..4d27dbeaec 100644 --- a/ground/src/main/java/com/google/android/ground/repository/LocationOfInterestRepository.kt +++ b/ground/src/main/java/com/google/android/ground/repository/LocationOfInterestRepository.kt @@ -91,14 +91,12 @@ constructor( /** This only works if the survey and location of interests are already cached to local db. */ suspend fun getOfflineLoi(surveyId: String, loiId: String): LocationOfInterest? { val survey = localSurveyStore.getSurveyById(surveyId) + val locationOfInterest = survey?.let { localLoiStore.getLocationOfInterest(it, loiId) } + if (survey == null) { Timber.e("LocationOfInterestRepository", "Survey not found: $surveyId") - return null - } - val locationOfInterest = localLoiStore.getLocationOfInterest(survey, loiId) - if (locationOfInterest == null) { + } else if (locationOfInterest == null) { Timber.e("LocationRepository", "LOI not found for survey $surveyId: LOI ID $loiId") - return null } return locationOfInterest }