├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── code-health.md │ └── feature_request.md ├── actions │ └── submit-test │ │ └── action.yml ├── auto_assign.yml ├── pull_request_template.md └── workflows │ ├── ci.yml │ ├── test-e2e.yml │ ├── test-submit.yml │ └── todo-to-issue.yml ├── .gitignore ├── .idea ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── externalDependencies.xml └── ktfmt.xml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── app ├── build.gradle ├── proguard-rules.pro ├── schemas │ └── org.groundplatform.android.persistence.local.room.LocalDatabase │ │ ├── 120.json │ │ ├── 121.json │ │ └── 122.json └── src │ ├── debug │ ├── AndroidManifest.xml │ ├── ic_launcher-playstore.png │ ├── java │ │ └── org │ │ │ └── groundplatform │ │ │ └── android │ │ │ └── HiltTestActivity.kt │ ├── local │ │ └── google-services.json │ ├── res │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ └── values │ │ │ └── ic_launcher_background.xml │ └── resources │ │ └── jacoco-agent.properties │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── licenses │ │ │ └── cc0_license.txt │ ├── ic_launcher-playstore.png │ ├── ic_launcher-web.png │ ├── java │ │ └── org │ │ │ └── groundplatform │ │ │ └── android │ │ │ ├── AbstractActivity.kt │ │ │ ├── Config.kt │ │ │ ├── ExcludeFromJacocoGeneratedReport.kt │ │ │ ├── FirebaseCrashLogger.kt │ │ │ ├── GroundApplication.kt │ │ │ ├── GroundApplicationModule.kt │ │ │ ├── LocalDatabaseModule.kt │ │ │ ├── MainActivity.kt │ │ │ ├── MainUiState.kt │ │ │ ├── MainViewModel.kt │ │ │ ├── PermissionDeniedDialog.kt │ │ │ ├── SettingsActivity.kt │ │ │ ├── coroutines │ │ │ ├── CoroutineDispatchersModule.kt │ │ │ └── CoroutineScopesModule.kt │ │ │ ├── model │ │ │ ├── AuditInfo.kt │ │ │ ├── Role.kt │ │ │ ├── Survey.kt │ │ │ ├── SurveyListItem.kt │ │ │ ├── TermsOfService.kt │ │ │ ├── User.kt │ │ │ ├── geometry │ │ │ │ ├── Coordinates.kt │ │ │ │ ├── Geometry.kt │ │ │ │ └── InvalidGeometryException.kt │ │ │ ├── imagery │ │ │ │ ├── OfflineArea.kt │ │ │ │ └── TileSource.kt │ │ │ ├── job │ │ │ │ ├── Job.kt │ │ │ │ └── Style.kt │ │ │ ├── locationofinterest │ │ │ │ └── LocationOfInterest.kt │ │ │ ├── mutation │ │ │ │ ├── LocationOfInterestMutation.kt │ │ │ │ ├── Mutation.kt │ │ │ │ └── SubmissionMutation.kt │ │ │ ├── submission │ │ │ │ ├── CaptureLocationTaskData.kt │ │ │ │ ├── DateTimeTaskData.kt │ │ │ │ ├── DraftSubmission.kt │ │ │ │ ├── GeometryTaskData.kt │ │ │ │ ├── MultipleChoiceTaskData.kt │ │ │ │ ├── NumberTaskData.kt │ │ │ │ ├── PhotoTaskData.kt │ │ │ │ ├── SkippedTaskData.kt │ │ │ │ ├── Submission.kt │ │ │ │ ├── SubmissionData.kt │ │ │ │ ├── TaskData.kt │ │ │ │ ├── TextTaskData.kt │ │ │ │ ├── UploadQueueEntry.kt │ │ │ │ └── ValueDelta.kt │ │ │ └── task │ │ │ │ ├── Condition.kt │ │ │ │ ├── MultipleChoice.kt │ │ │ │ ├── Option.kt │ │ │ │ └── Task.kt │ │ │ ├── persistence │ │ │ ├── local │ │ │ │ ├── LocalDataConsistencyException.kt │ │ │ │ ├── LocalDataStoreModule.kt │ │ │ │ ├── LocalValueStore.kt │ │ │ │ ├── SharedPreferencesModule.kt │ │ │ │ ├── room │ │ │ │ │ ├── IntEnum.kt │ │ │ │ │ ├── LocalDataStoreException.kt │ │ │ │ │ ├── LocalDatabase.kt │ │ │ │ │ ├── converter │ │ │ │ │ │ ├── ConverterExt.kt │ │ │ │ │ │ ├── GeometryWrapperTypeConverter.kt │ │ │ │ │ │ ├── JsonArrayTypeConverter.kt │ │ │ │ │ │ ├── JsonObjectTypeConverter.kt │ │ │ │ │ │ ├── LoiPropertiesMapConverter.kt │ │ │ │ │ │ ├── StyleTypeConverter.kt │ │ │ │ │ │ ├── SubmissionDataConverter.kt │ │ │ │ │ │ ├── SubmissionDeltasConverter.kt │ │ │ │ │ │ └── ValueJsonConverter.kt │ │ │ │ │ ├── dao │ │ │ │ │ │ ├── BaseDao.kt │ │ │ │ │ │ ├── ConditionDao.kt │ │ │ │ │ │ ├── DraftSubmissionDao.kt │ │ │ │ │ │ ├── ExpressionDao.kt │ │ │ │ │ │ ├── JobDao.kt │ │ │ │ │ │ ├── LocationOfInterestDao.kt │ │ │ │ │ │ ├── LocationOfInterestMutationDao.kt │ │ │ │ │ │ ├── MultipleChoiceDao.kt │ │ │ │ │ │ ├── OfflineAreaDao.kt │ │ │ │ │ │ ├── OptionDao.kt │ │ │ │ │ │ ├── SubmissionDao.kt │ │ │ │ │ │ ├── SubmissionMutationDao.kt │ │ │ │ │ │ ├── SurveyDao.kt │ │ │ │ │ │ ├── TaskDao.kt │ │ │ │ │ │ └── UserDao.kt │ │ │ │ │ ├── entity │ │ │ │ │ │ ├── AuditInfoEntity.kt │ │ │ │ │ │ ├── ConditionEntity.kt │ │ │ │ │ │ ├── DraftSubmissionEntity.kt │ │ │ │ │ │ ├── ExpressionEntity.kt │ │ │ │ │ │ ├── GeometryWrapper.kt │ │ │ │ │ │ ├── JobEntity.kt │ │ │ │ │ │ ├── LocationOfInterestEntity.kt │ │ │ │ │ │ ├── LocationOfInterestMutationEntity.kt │ │ │ │ │ │ ├── MultipleChoiceEntity.kt │ │ │ │ │ │ ├── OfflineAreaEntity.kt │ │ │ │ │ │ ├── OptionEntity.kt │ │ │ │ │ │ ├── StyleEntity.kt │ │ │ │ │ │ ├── SubmissionEntity.kt │ │ │ │ │ │ ├── SubmissionMutationEntity.kt │ │ │ │ │ │ ├── SurveyEntity.kt │ │ │ │ │ │ ├── TaskEntity.kt │ │ │ │ │ │ └── UserEntity.kt │ │ │ │ │ ├── fields │ │ │ │ │ │ ├── EntityDeletionState.kt │ │ │ │ │ │ ├── ExpressionEntityType.kt │ │ │ │ │ │ ├── MatchEntityType.kt │ │ │ │ │ │ ├── MultipleChoiceEntityType.kt │ │ │ │ │ │ ├── MutationEntitySyncStatus.kt │ │ │ │ │ │ ├── MutationEntityType.kt │ │ │ │ │ │ ├── OfflineAreaEntityState.kt │ │ │ │ │ │ ├── TaskEntityType.kt │ │ │ │ │ │ ├── TileSetEntityState.kt │ │ │ │ │ │ └── UserDetails.kt │ │ │ │ │ ├── relations │ │ │ │ │ │ ├── ConditionEntityAndRelations.kt │ │ │ │ │ │ ├── JobEntityAndRelations.kt │ │ │ │ │ │ ├── SurveyEntityAndRelations.kt │ │ │ │ │ │ └── TaskEntityAndRelations.kt │ │ │ │ │ └── stores │ │ │ │ │ │ ├── RoomLocationOfInterestStore.kt │ │ │ │ │ │ ├── RoomOfflineAreaStore.kt │ │ │ │ │ │ ├── RoomSubmissionStore.kt │ │ │ │ │ │ ├── RoomSurveyStore.kt │ │ │ │ │ │ └── RoomUserStore.kt │ │ │ │ └── stores │ │ │ │ │ ├── LocalLocationOfInterestStore.kt │ │ │ │ │ ├── LocalMutationStore.kt │ │ │ │ │ ├── LocalOfflineAreaStore.kt │ │ │ │ │ ├── LocalSubmissionStore.kt │ │ │ │ │ ├── LocalSurveyStore.kt │ │ │ │ │ └── LocalUserStore.kt │ │ │ ├── remote │ │ │ │ ├── DataStoreException.kt │ │ │ │ ├── RemoteDataStore.kt │ │ │ │ ├── RemotePersistenceModule.kt │ │ │ │ ├── RemoteStorageManager.kt │ │ │ │ └── firebase │ │ │ │ │ ├── FirebaseFirestoreProvider.kt │ │ │ │ │ ├── FirebaseMessagingService.kt │ │ │ │ │ ├── FirebaseStorageManager.kt │ │ │ │ │ ├── FirestoreDataStore.kt │ │ │ │ │ ├── FirestoreUuidGenerator.kt │ │ │ │ │ ├── base │ │ │ │ │ ├── FluentCollectionReference.kt │ │ │ │ │ ├── FluentDocumentReference.kt │ │ │ │ │ └── FluentFirestore.kt │ │ │ │ │ ├── protobuf │ │ │ │ │ ├── FirestoreToProtobufExt.kt │ │ │ │ │ ├── MessageLiteReflectionExt.kt │ │ │ │ │ ├── ModelToProtoExt.kt │ │ │ │ │ └── ProtobufToFirestoreExt.kt │ │ │ │ │ └── schema │ │ │ │ │ ├── AuditInfoConverter.kt │ │ │ │ │ ├── CaptureLocationResultConverter.kt │ │ │ │ │ ├── ConditionConverter.kt │ │ │ │ │ ├── GeometryConverter.kt │ │ │ │ │ ├── GroundFirestore.kt │ │ │ │ │ ├── JobCollectionReference.kt │ │ │ │ │ ├── JobConverter.kt │ │ │ │ │ ├── LoiCollectionReference.kt │ │ │ │ │ ├── LoiConverter.kt │ │ │ │ │ ├── LoiDocumentReference.kt │ │ │ │ │ ├── MultipleChoiceConverter.kt │ │ │ │ │ ├── OptionConverter.kt │ │ │ │ │ ├── SubmissionCollectionReference.kt │ │ │ │ │ ├── SubmissionDocumentReference.kt │ │ │ │ │ ├── SurveyConverter.kt │ │ │ │ │ ├── SurveyDocumentReference.kt │ │ │ │ │ ├── SurveysCollectionReference.kt │ │ │ │ │ ├── TaskConverter.kt │ │ │ │ │ ├── TermsOfServiceCollectionReference.kt │ │ │ │ │ ├── TermsOfServiceConverter.kt │ │ │ │ │ ├── TermsOfServiceDocument.kt │ │ │ │ │ └── TermsOfServiceDocumentReference.kt │ │ │ ├── sync │ │ │ │ ├── LocalMutationSyncWorker.kt │ │ │ │ ├── MediaUploadWorkManager.kt │ │ │ │ ├── MediaUploadWorker.kt │ │ │ │ ├── MutationSyncWorkManager.kt │ │ │ │ ├── SurveySyncService.kt │ │ │ │ ├── SurveySyncWorker.kt │ │ │ │ ├── WorkManagerModule.kt │ │ │ │ └── WorkRequestBuilder.kt │ │ │ └── uuid │ │ │ │ └── OfflineUuidGenerator.kt │ │ │ ├── repository │ │ │ ├── LocationOfInterestRepository.kt │ │ │ ├── MapStateRepository.kt │ │ │ ├── MutationRepository.kt │ │ │ ├── OfflineAreaRepository.kt │ │ │ ├── SubmissionRepository.kt │ │ │ ├── SurveyRepository.kt │ │ │ ├── TermsOfServiceRepository.kt │ │ │ ├── UserMediaRepository.kt │ │ │ └── UserRepository.kt │ │ │ ├── system │ │ │ ├── ActivityResult.kt │ │ │ ├── ActivityStreams.kt │ │ │ ├── FusedLocationProviderClient.kt │ │ │ ├── GeocodingManager.kt │ │ │ ├── GoogleApiManager.kt │ │ │ ├── LocationManager.kt │ │ │ ├── NetworkManager.kt │ │ │ ├── PermissionsManager.kt │ │ │ ├── RequestPermissionsResult.kt │ │ │ ├── SettingsClient.kt │ │ │ ├── SettingsManager.kt │ │ │ ├── SystemModule.kt │ │ │ ├── auth │ │ │ │ ├── AnonymousAuthenticationManager.kt │ │ │ │ ├── AuthenticationManager.kt │ │ │ │ ├── AuthenticationModule.kt │ │ │ │ ├── BaseAuthenticationManager.kt │ │ │ │ ├── GoogleAuthenticationManager.kt │ │ │ │ └── SignInState.kt │ │ │ └── channel │ │ │ │ └── LocationSharedFlowCallback.kt │ │ │ ├── ui │ │ │ ├── IconFactory.kt │ │ │ ├── common │ │ │ │ ├── AbstractDialogFragment.kt │ │ │ │ ├── AbstractFragment.kt │ │ │ │ ├── AbstractMapContainerFragment.kt │ │ │ │ ├── AbstractViewModel.kt │ │ │ │ ├── BackPressListener.kt │ │ │ │ ├── BaseMapViewModel.kt │ │ │ │ ├── BindingAdapters.kt │ │ │ │ ├── EphemeralPopups.kt │ │ │ │ ├── LocationOfInterestHelper.kt │ │ │ │ ├── MapConfig.kt │ │ │ │ ├── ProgressDialogs.kt │ │ │ │ ├── SharedViewModel.kt │ │ │ │ ├── ViewModelFactory.kt │ │ │ │ ├── ViewModelKey.kt │ │ │ │ └── ViewModelModule.kt │ │ │ ├── compose │ │ │ │ ├── ConfirmationDialog.kt │ │ │ │ ├── HtmlText.kt │ │ │ │ ├── HyperlinkText.kt │ │ │ │ └── Toolbar.kt │ │ │ ├── datacollection │ │ │ │ ├── DataCollectionFragment.kt │ │ │ │ ├── DataCollectionViewModel.kt │ │ │ │ ├── DataCollectionViewPagerAdapter.kt │ │ │ │ ├── DataCollectionViewPagerAdapterFactory.kt │ │ │ │ ├── DataSubmissionConfirmationScreen.kt │ │ │ │ ├── TaskDataHandler.kt │ │ │ │ ├── TaskPosition.kt │ │ │ │ ├── TaskSequenceHandler.kt │ │ │ │ ├── UiState.kt │ │ │ │ ├── components │ │ │ │ │ ├── ButtonAction.kt │ │ │ │ │ ├── InstructionsDialog.kt │ │ │ │ │ ├── LoiNameDialog.kt │ │ │ │ │ ├── TaskButton.kt │ │ │ │ │ ├── TaskView.kt │ │ │ │ │ ├── TaskViewFactory.kt │ │ │ │ │ └── TextTaskInput.kt │ │ │ │ └── tasks │ │ │ │ │ ├── AbstractTaskFragment.kt │ │ │ │ │ ├── AbstractTaskMapFragment.kt │ │ │ │ │ ├── AbstractTaskViewModel.kt │ │ │ │ │ ├── date │ │ │ │ │ ├── DateTaskFragment.kt │ │ │ │ │ └── DateTaskViewModel.kt │ │ │ │ │ ├── instruction │ │ │ │ │ ├── InstructionTaskFragment.kt │ │ │ │ │ └── InstructionTaskViewModel.kt │ │ │ │ │ ├── location │ │ │ │ │ ├── CaptureLocationTaskFragment.kt │ │ │ │ │ ├── CaptureLocationTaskMapFragment.kt │ │ │ │ │ └── CaptureLocationTaskViewModel.kt │ │ │ │ │ ├── multiplechoice │ │ │ │ │ ├── MultipleChoiceItem.kt │ │ │ │ │ ├── MultipleChoiceItemView.kt │ │ │ │ │ ├── MultipleChoiceTaskFragment.kt │ │ │ │ │ └── MultipleChoiceTaskViewModel.kt │ │ │ │ │ ├── number │ │ │ │ │ ├── NumberTaskFragment.kt │ │ │ │ │ └── NumberTaskViewModel.kt │ │ │ │ │ ├── photo │ │ │ │ │ ├── PhotoTaskFragment.kt │ │ │ │ │ └── PhotoTaskViewModel.kt │ │ │ │ │ ├── point │ │ │ │ │ ├── DropPinTaskFragment.kt │ │ │ │ │ ├── DropPinTaskMapFragment.kt │ │ │ │ │ └── DropPinTaskViewModel.kt │ │ │ │ │ ├── polygon │ │ │ │ │ ├── DrawAreaTaskFragment.kt │ │ │ │ │ ├── DrawAreaTaskMapFragment.kt │ │ │ │ │ └── DrawAreaTaskViewModel.kt │ │ │ │ │ ├── text │ │ │ │ │ ├── TextTaskFragment.kt │ │ │ │ │ └── TextTaskViewModel.kt │ │ │ │ │ └── time │ │ │ │ │ ├── TimeTaskFragment.kt │ │ │ │ │ └── TimeTaskViewModel.kt │ │ │ ├── home │ │ │ │ ├── AboutFragment.kt │ │ │ │ ├── DataSharingTermsDialog.kt │ │ │ │ ├── HomeScreenFragment.kt │ │ │ │ ├── HomeScreenViewModel.kt │ │ │ │ ├── UserDetailsDialog.kt │ │ │ │ └── mapcontainer │ │ │ │ │ ├── AdaptiveSpacingItemDecorator.kt │ │ │ │ │ ├── HomeScreenMapContainerFragment.kt │ │ │ │ │ ├── HomeScreenMapContainerViewModel.kt │ │ │ │ │ ├── MapTypeAdapter.kt │ │ │ │ │ ├── MapTypeDialogFragment.kt │ │ │ │ │ ├── MapTypeViewModel.kt │ │ │ │ │ └── jobs │ │ │ │ │ ├── ActionButton.kt │ │ │ │ │ ├── DataCollectionEntryPointData.kt │ │ │ │ │ ├── JobMapComposables.kt │ │ │ │ │ ├── JobSelectionModal.kt │ │ │ │ │ ├── JobSelectionRow.kt │ │ │ │ │ └── LoiJobSheet.kt │ │ │ ├── map │ │ │ │ ├── Bounds.kt │ │ │ │ ├── CameraPosition.kt │ │ │ │ ├── CameraUpdateRequest.kt │ │ │ │ ├── Feature.kt │ │ │ │ ├── FeatureType.kt │ │ │ │ ├── MapFragment.kt │ │ │ │ ├── MapProviderModule.kt │ │ │ │ ├── MapType.kt │ │ │ │ └── gms │ │ │ │ │ ├── ClippingTileProvider.kt │ │ │ │ │ ├── ConverterExt.kt │ │ │ │ │ ├── GmsExt.kt │ │ │ │ │ ├── GoogleMapsFragment.kt │ │ │ │ │ ├── TemplateUrlTileProvider.kt │ │ │ │ │ ├── features │ │ │ │ │ ├── FeatureClusterItem.kt │ │ │ │ │ ├── FeatureClusterManager.kt │ │ │ │ │ ├── FeatureClusterRenderer.kt │ │ │ │ │ ├── FeatureManager.kt │ │ │ │ │ ├── LineStringRenderer.kt │ │ │ │ │ ├── MapsItemManager.kt │ │ │ │ │ ├── MapsItemRenderer.kt │ │ │ │ │ ├── PointRenderer.kt │ │ │ │ │ ├── PolygonRenderer.kt │ │ │ │ │ └── TooltipMarkerRenderer.kt │ │ │ │ │ └── mog │ │ │ │ │ ├── ImageEditor.kt │ │ │ │ │ ├── LatLngBoundsExt.kt │ │ │ │ │ ├── MathExt.kt │ │ │ │ │ ├── MogClient.kt │ │ │ │ │ ├── MogCollection.kt │ │ │ │ │ ├── MogImageMetadata.kt │ │ │ │ │ ├── MogMetadata.kt │ │ │ │ │ ├── MogMetadataReader.kt │ │ │ │ │ ├── MogProviderModule.kt │ │ │ │ │ ├── MogSource.kt │ │ │ │ │ ├── MogTile.kt │ │ │ │ │ ├── MogTileDownloader.kt │ │ │ │ │ ├── MogTileMetadata.kt │ │ │ │ │ ├── MogTileProvider.kt │ │ │ │ │ ├── MogTileReader.kt │ │ │ │ │ ├── MogTilesRequest.kt │ │ │ │ │ ├── PixelBounds.kt │ │ │ │ │ ├── PixelCoordinates.kt │ │ │ │ │ ├── README.md │ │ │ │ │ ├── SeekableInputStream.kt │ │ │ │ │ ├── TiffTag.kt │ │ │ │ │ ├── TiffTagDataType.kt │ │ │ │ │ ├── TileCoordinates.kt │ │ │ │ │ └── UrlInputStream.kt │ │ │ ├── offlineareas │ │ │ │ ├── OfflineAreaDetails.kt │ │ │ │ ├── OfflineAreaListItem.kt │ │ │ │ ├── OfflineAreasFragment.kt │ │ │ │ ├── OfflineAreasViewModel.kt │ │ │ │ ├── selector │ │ │ │ │ ├── DownloadProgressDialog.kt │ │ │ │ │ ├── OfflineAreaSelectorFragment.kt │ │ │ │ │ ├── OfflineAreaSelectorViewModel.kt │ │ │ │ │ └── UiState.kt │ │ │ │ └── viewer │ │ │ │ │ ├── OfflineAreaViewerFragment.kt │ │ │ │ │ └── OfflineAreaViewerViewModel.kt │ │ │ ├── settings │ │ │ │ ├── Keys.kt │ │ │ │ └── SettingsFragment.kt │ │ │ ├── signin │ │ │ │ ├── SignInFragment.kt │ │ │ │ └── SignInViewModel.kt │ │ │ ├── startup │ │ │ │ ├── StartupFragment.kt │ │ │ │ └── StartupViewModel.kt │ │ │ ├── surveyselector │ │ │ │ ├── SurveyListAdapter.kt │ │ │ │ ├── SurveySelectorFragment.kt │ │ │ │ ├── SurveySelectorViewModel.kt │ │ │ │ └── UiState.kt │ │ │ ├── syncstatus │ │ │ │ ├── SyncListItem.kt │ │ │ │ ├── SyncStatusDetail.kt │ │ │ │ ├── SyncStatusFragment.kt │ │ │ │ └── SyncStatusViewModel.kt │ │ │ ├── theme │ │ │ │ ├── Color.kt │ │ │ │ └── Theme.kt │ │ │ ├── tos │ │ │ │ ├── TermsOfServiceFragment.kt │ │ │ │ └── TermsOfServiceViewModel.kt │ │ │ └── util │ │ │ │ ├── BitmapUtil.kt │ │ │ │ ├── ContextExt.kt │ │ │ │ ├── FileUtil.kt │ │ │ │ ├── LocaleAwareMeasureFormatter.kt │ │ │ │ ├── PolygonUtil.kt │ │ │ │ ├── RotateUsingExif.kt │ │ │ │ ├── VibrationHelper.kt │ │ │ │ └── ViewUtil.kt │ │ │ ├── usecases │ │ │ ├── datasharingterms │ │ │ │ └── GetDataSharingTermsUseCase.kt │ │ │ ├── submission │ │ │ │ └── SubmitDataUseCase.kt │ │ │ └── survey │ │ │ │ ├── ActivateSurveyUseCase.kt │ │ │ │ ├── ListAvailableSurveysUseCase.kt │ │ │ │ ├── MakeSurveyAvailableOfflineUseCase.kt │ │ │ │ ├── ReactivateLastSurveyUseCase.kt │ │ │ │ ├── RemoveOfflineSurveyUseCase.kt │ │ │ │ └── SyncSurveyUseCase.kt │ │ │ └── util │ │ │ ├── AsyncSingletonProvider.kt │ │ │ ├── ComposeExt.kt │ │ │ ├── CoordinatesExt.kt │ │ │ ├── Debug.kt │ │ │ ├── Enums.kt │ │ │ ├── FileExt.kt │ │ │ ├── FirebaseFirestoreExt.kt │ │ │ ├── InsetExt.kt │ │ │ ├── ListExt.kt │ │ │ ├── MapExt.kt │ │ │ ├── RangeExt.kt │ │ │ ├── StrictModeExtensions.kt │ │ │ └── ViewExt.kt │ └── res │ │ ├── color │ │ ├── nav_drawer_item.xml │ │ └── task_transparent_btn_selector.xml │ │ ├── drawable-anydpi │ │ ├── ic_arrow_back.xml │ │ ├── ic_gps_lock.xml │ │ ├── ic_history.xml │ │ └── ic_more_vert.xml │ │ ├── drawable-hdpi │ │ ├── ground_logo.png │ │ └── splash_background.png │ │ ├── drawable │ │ ├── baseline_check_24.xml │ │ ├── baseline_close_24.xml │ │ ├── baseline_hourglass_empty_24.xml │ │ ├── baseline_menu_24.xml │ │ ├── baseline_warning_24.xml │ │ ├── cloud_off.xml │ │ ├── cluster_marker.xml │ │ ├── data_submitted.xml │ │ ├── feed.xml │ │ ├── green_gradient.xml │ │ ├── ic_add.xml │ │ ├── ic_circle_marker.xml │ │ ├── ic_content_paste.xml │ │ ├── ic_gps_lock_not_fixed.xml │ │ ├── ic_maps_ar.xml │ │ ├── ic_marker_fill.xml │ │ ├── ic_marker_outline.xml │ │ ├── ic_marker_overlay.xml │ │ ├── ic_offline_pin.xml │ │ ├── ic_photo_grey_600_24dp.xml │ │ ├── ic_plus_sign.xml │ │ ├── ic_question_answer.xml │ │ ├── ic_redo_black.xml │ │ ├── ic_ring_marker.xml │ │ ├── ic_settings.xml │ │ ├── ic_sync.xml │ │ ├── ic_undo_black.xml │ │ ├── info_outline.xml │ │ ├── map_layers.xml │ │ ├── map_type_roadmap.png │ │ ├── map_type_satellite.png │ │ ├── map_type_terrain.png │ │ ├── offline_area_viewport_outline.xml │ │ ├── offline_map_imagery.xml │ │ ├── outline_done_all_24.xml │ │ ├── outline_draw.xml │ │ ├── outline_error_outline_24.xml │ │ ├── outline_photo_camera.xml │ │ ├── outline_pin_drop.xml │ │ ├── swipe_24.xml │ │ ├── task_light_green_btn_selector.xml │ │ └── touch_app_24.xml │ │ ├── font │ │ ├── display_500.xml │ │ ├── display_700.xml │ │ ├── google_sans.ttf │ │ ├── manrope_bold.ttf │ │ ├── manrope_medium.ttf │ │ ├── text_500.xml │ │ ├── text_700.xml │ │ ├── urbanist_bold.ttf │ │ └── urbanist_medium.ttf │ │ ├── layout │ │ ├── basemap_layout.xml │ │ ├── data_collection_frag.xml │ │ ├── date_task_frag.xml │ │ ├── fragment_draw_area_task.xml │ │ ├── home_screen_frag.xml │ │ ├── main_act.xml │ │ ├── map_task_frag.xml │ │ ├── map_type_dialog_fragment.xml │ │ ├── map_type_dialog_item.xml │ │ ├── menu_button.xml │ │ ├── nav_drawer_header.xml │ │ ├── offline_area_selector_frag.xml │ │ ├── offline_area_viewer_frag.xml │ │ ├── offline_areas_frag.xml │ │ ├── photo_task.xml │ │ ├── photo_task_frag.xml │ │ ├── progress_dialog.xml │ │ ├── settings_activity.xml │ │ ├── sign_in_frag.xml │ │ ├── startup_frag.xml │ │ ├── survey_card_item.xml │ │ ├── survey_selector_frag.xml │ │ ├── sync_status_frag.xml │ │ ├── task_frag_action_buttons.xml │ │ ├── task_frag_with_combined_header.xml │ │ ├── task_frag_with_header.xml │ │ └── time_task_frag.xml │ │ ├── menu │ │ ├── nav_drawer_menu.xml │ │ └── survey_options_menu.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── navigation │ │ └── nav_graph.xml │ │ ├── values-es │ │ └── strings.xml │ │ ├── values-fr │ │ └── strings.xml │ │ ├── values-night │ │ └── colors.xml │ │ ├── values-pt │ │ └── strings.xml │ │ ├── values │ │ ├── arrays.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings-untranslated.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ ├── file_paths.xml │ │ └── preferences.xml │ ├── staging │ ├── AndroidManifest.xml │ ├── java │ │ └── org │ │ │ └── groundplatform │ │ │ └── android │ │ │ └── HiltTestActivity.kt │ └── resources │ │ └── jacoco-agent.properties │ └── test │ ├── java │ └── org │ │ └── groundplatform │ │ └── android │ │ ├── BaseHiltTest.kt │ │ ├── FakeData.kt │ │ ├── HiltExt.kt │ │ ├── MainActivityTest.kt │ │ ├── MainViewModelTest.kt │ │ ├── PermissionDeniedDialogTest.kt │ │ ├── RecyclerViewHelper.kt │ │ ├── ResultAssertions.kt │ │ ├── TestAuthenticationModule.kt │ │ ├── TestCoroutineDispatchersModule.kt │ │ ├── TestCoroutineScopesModule.kt │ │ ├── TestLocalDatabaseModule.kt │ │ ├── TestRemoteStorageModule.kt │ │ ├── TestWorkManagerModule.kt │ │ ├── TimberTestRule.kt │ │ ├── UiTestHelper.kt │ │ ├── model │ │ ├── SurveyTest.kt │ │ ├── geometry │ │ │ └── GeometryTest.kt │ │ └── task │ │ │ └── ConditionTest.kt │ │ ├── persistence │ │ ├── local │ │ │ ├── LocalLocationOfInterestStoreTest.kt │ │ │ ├── LocalOfflineAreaStore.kt │ │ │ ├── LocalSubmissionStoreTest.kt │ │ │ ├── LocalSurveyStoreTest.kt │ │ │ ├── LocalUserStoreTest.kt │ │ │ └── room │ │ │ │ └── converter │ │ │ │ └── ValueJsonConverterTest.kt │ │ ├── remote │ │ │ ├── FakeRemoteDataStore.kt │ │ │ ├── FakeRemoteStorageManager.kt │ │ │ └── firebase │ │ │ │ ├── FirebaseMessagingSurveyTest.kt │ │ │ │ ├── FirestoreTestUtil.kt │ │ │ │ ├── protobuf │ │ │ │ ├── FirestoreToProtobufExtTest.kt │ │ │ │ ├── LoiMutationConverterTest.kt │ │ │ │ ├── ModelToProtoExtKtTest.kt │ │ │ │ └── ProtobufToFirestoreExtTest.kt │ │ │ │ └── schema │ │ │ │ ├── AuditInfoConverterTest.kt │ │ │ │ ├── ConditionConverterTest.kt │ │ │ │ ├── GeometryConverterTest.kt │ │ │ │ ├── JobConverterTest.kt │ │ │ │ ├── LoiConverterTest.kt │ │ │ │ ├── MultipleChoiceConverterTest.kt │ │ │ │ ├── SubmissionMutationConverterTest.kt │ │ │ │ ├── SurveyConverterTest.kt │ │ │ │ ├── TaskConverterTest.kt │ │ │ │ └── TermsOfServiceConverterTest.kt │ │ ├── sync │ │ │ ├── FakeWorkManager.kt │ │ │ ├── LocalMutationSyncWorkerTest.kt │ │ │ ├── MediaUploadWorkerTest.kt │ │ │ ├── SurveySyncServiceTest.kt │ │ │ └── SurveySyncWorkerTest.kt │ │ └── uuid │ │ │ └── FakeUuidGenerator.kt │ │ ├── repository │ │ ├── LocationOfInterestRepositoryTest.kt │ │ ├── MapStateRepositoryTest.kt │ │ ├── SurveyRepositoryTest.kt │ │ ├── TermsOfServiceRepositoryTest.kt │ │ ├── UserMediaRepositoryTest.kt │ │ └── UserRepositoryTest.kt │ │ ├── system │ │ ├── GeocodingManagerTest.kt │ │ ├── LocationManagerTest.kt │ │ ├── PermissionsManagerTest.kt │ │ ├── SettingsManagerTest.kt │ │ └── auth │ │ │ └── FakeAuthenticationManager.kt │ │ ├── ui │ │ ├── IconFactoryTest.kt │ │ ├── common │ │ │ └── LocationOfInterestHelperTest.kt │ │ ├── datacollection │ │ │ ├── DataCollectionFragmentTest.kt │ │ │ ├── TaskDataHandlerTest.kt │ │ │ ├── TaskFragmentRunner.kt │ │ │ ├── TaskSequenceHandlerTest.kt │ │ │ └── tasks │ │ │ │ ├── BaseTaskFragmentTest.kt │ │ │ │ ├── date │ │ │ │ └── DateTaskFragmentTest.kt │ │ │ │ ├── instruction │ │ │ │ └── InstructionTaskFragmentTest.kt │ │ │ │ ├── location │ │ │ │ └── CaptureLocationTaskFragmentTest.kt │ │ │ │ ├── multiplechoice │ │ │ │ └── MultipleChoiceTaskFragmentTest.kt │ │ │ │ ├── number │ │ │ │ └── NumberTaskFragmentTest.kt │ │ │ │ ├── photo │ │ │ │ └── PhotoTaskFragmentTest.kt │ │ │ │ ├── point │ │ │ │ └── DropPinTaskFragmentTest.kt │ │ │ │ ├── polygon │ │ │ │ ├── DrawAreaTaskFragmentTest.kt │ │ │ │ └── DrawAreaTaskViewModelTest.kt │ │ │ │ ├── text │ │ │ │ └── TextTaskFragmentTest.kt │ │ │ │ └── time │ │ │ │ └── TimeTaskFragmentTest.kt │ │ ├── home │ │ │ ├── AboutFragmentTest.kt │ │ │ ├── DataSharingTermsDialogTest.kt │ │ │ ├── HomeScreenFragmentTest.kt │ │ │ └── mapcontainer │ │ │ │ ├── HomeScreenMapContainerFragmentTest.kt │ │ │ │ ├── HomeScreenMapContainerViewModelTest.kt │ │ │ │ ├── MapTypeDialogFragmentTest.kt │ │ │ │ └── jobs │ │ │ │ └── LoiJobSheetTest.kt │ │ ├── map │ │ │ ├── CameraPositionTest.kt │ │ │ └── gms │ │ │ │ ├── FeatureClusterManagerTest.kt │ │ │ │ └── mog │ │ │ │ ├── MogCollectionTest.kt │ │ │ │ ├── MogImageMetadataTest.kt │ │ │ │ ├── MogSourceTest.kt │ │ │ │ ├── MogTileMetadataTest.kt │ │ │ │ ├── MogTileRequestTest.kt │ │ │ │ ├── MogTileTest.kt │ │ │ │ ├── PixelCoordinatesTest.kt │ │ │ │ ├── SeekableBufferedInputStreamTest.kt │ │ │ │ ├── SeekableInputStreamTest.kt │ │ │ │ ├── TiffTagDataTypeTest.kt │ │ │ │ ├── TiffTagTest.kt │ │ │ │ └── TileCoordinatesTest.kt │ │ ├── offlineareas │ │ │ ├── OfflineAreasFragmentTest.kt │ │ │ ├── selector │ │ │ │ ├── DownloadProgressDialogTest.kt │ │ │ │ └── OfflineAreaSelectorFragmentTest.kt │ │ │ └── viewer │ │ │ │ ├── OfflineAreaViewerFragmentTest.kt │ │ │ │ └── OfflineAreaViewerViewModelTest.kt │ │ ├── settings │ │ │ └── SettingsFragmentTest.kt │ │ ├── signin │ │ │ └── SignInFragmentTest.kt │ │ ├── surveyselector │ │ │ └── SurveySelectorFragmentTest.kt │ │ ├── syncstatus │ │ │ └── SyncStatusFragmentTest.kt │ │ ├── tos │ │ │ └── TermsOfServiceFragmentTest.kt │ │ └── util │ │ │ └── LocaleAwareMeasureFormatterTest.kt │ │ ├── usecases │ │ ├── datasharingterms │ │ │ └── GetDataSharingTermsUseCaseTest.kt │ │ ├── submission │ │ │ └── SubmitDataUseCaseTest.kt │ │ └── survey │ │ │ ├── ActivateSurveyUseCaseTest.kt │ │ │ ├── ListAvailableSurveysUseCaseTest.kt │ │ │ ├── MakeSurveyAvailableOfflineUseCaseTest.kt │ │ │ ├── ReactivateLastSurveyUseCaseTest.kt │ │ │ ├── RemoveOfflineSurveyUseCaseTest.kt │ │ │ └── SyncSurveyUseCaseTest.kt │ │ └── util │ │ ├── CoordinatesExtTest.kt │ │ ├── PolygonUtilTest.kt │ │ ├── RangeExtTest.kt │ │ └── view │ │ └── ViewMatchers.kt │ ├── proto │ └── test.proto │ └── resources │ └── robolectric.properties ├── build.gradle ├── cloud-builder └── sign │ └── keystore ├── codecov.yml ├── config ├── checkstyle │ ├── checkstyle.gradle │ └── xml.header ├── detekt │ ├── baseline.xml │ ├── detekt.yml │ └── license.template ├── jacoco │ └── jacoco.gradle └── lint │ ├── lint.gradle │ └── lint.xml ├── docs ├── android-architecture-diagram.png └── architecture-docs.md ├── e2eTest ├── build.gradle └── src │ └── main │ └── java │ └── org │ └── groundplatform │ └── android │ └── e2etest │ ├── AutomatorRunner.kt │ ├── SurveyRunnerTest.kt │ └── TestConfig.kt ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.defaults.properties ├── settings.gradle └── third_party └── checkstyle ├── LICENSE ├── METADATA └── google_checks.xml /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset = utf-8 3 | end_of_line = lf 4 | insert_final_newline = false 5 | indent_style = space 6 | indent_size = 4 7 | 8 | [{*.jhm,*.rng,*.wsdl,*.fxml,*.xslt,*.jrxml,*.ant,*.xul,*.xsl,*.xsd,*.tld,*.jnlp,*.xml}] 9 | indent_size = 2 10 | 11 | [*.json] 12 | indent_size = 2 13 | 14 | [*.java] 15 | indent_size = 2 16 | 17 | [{*.yaml,*.yml}] 18 | indent_size = 2 19 | 20 | [*.kt] 21 | indent_size = 2 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a bug report to help us improve 4 | title: '' 5 | labels: 'type: bug' 6 | assignees: '' 7 | type: 'Bug' 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **App version** 14 | Android: 15 | 16 | **To Reproduce** 17 | Steps to reproduce the behavior: 18 | 1. Go to '...' 19 | 2. Click on '....' 20 | 3. Scroll down to '....' 21 | 4. See error 22 | 23 | **Expected behavior** 24 | A clear and concise description of what you expected to happen. 25 | 26 | **Actual behavior** 27 | A clear and concise description of what you actually saw happen. 28 | 29 | **Screenshots** 30 | If applicable, add screenshots to help explain your problem. 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/code-health.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Code health 3 | about: Code improvements, cleanup, and TODOs 4 | title: "[Code health] Description" 5 | labels: 'type: code health' 6 | assignees: '' 7 | type: 'Task' 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Request a new feature 4 | title: "[AppFeatureNameHere] Description" 5 | labels: 'priority: p2, type: feature request' 6 | assignees: '' 7 | type: 'Feature' 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Fixes # 5 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | 19 | @... PTAL? 20 | -------------------------------------------------------------------------------- /.github/workflows/test-submit.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2024 The Ground Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | name: Submission Test 15 | 16 | on: 17 | issue_comment: 18 | types: [created] 19 | 20 | jobs: 21 | submitTest: 22 | if: github.event.issue.pull_request && contains(github.event.comment.body, '/submitTest') 23 | name: Submit to survey 24 | runs-on: ubuntu-latest 25 | timeout-minutes: 15 26 | steps: 27 | - name: Checkout code 28 | uses: actions/checkout@v4 29 | - name: Run submit-test 30 | uses: ./.github/actions/submit-test 31 | with: 32 | android-repository: ${{ github.repository }} 33 | google-maps-key: ${{ secrets.GOOGLE_MAPS_KEY }} 34 | use-repo-data: true 35 | upload-artifacts: false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | **/google-services.json 3 | secrets.properties 4 | !app/src/debug/local/google-services.json 5 | !.gitignore 6 | !gradle/ 7 | 8 | # Taken from Android.gitignore https://github.com/github/gitignore/blob/master/Android.gitignore 9 | # 10 | # Built application files 11 | *.apk 12 | *.ap_ 13 | 14 | # Files for the Dalvik VM 15 | *.dex 16 | 17 | # Java class files 18 | *.class 19 | 20 | # Generated files 21 | bin/ 22 | gen/ 23 | out/ 24 | 25 | # Gradle files 26 | .gradle/ 27 | build/ 28 | 29 | # Local configuration file (sdk path, etc) 30 | local.properties 31 | 32 | # Proguard folder generated by Eclipse 33 | proguard/ 34 | 35 | # Log Files 36 | *.log 37 | 38 | # Android Studio captures folder 39 | captures/ 40 | 41 | # IntelliJ 42 | *.iml 43 | 44 | # Code styling configuration 45 | # https://github.com/google/styleguide/blob/gh-pages/intellij-java-google-style.xml 46 | !/.idea/codeStyles/ 47 | !/.editorconfig 48 | !/.idea/externalDependencies.xml 49 | !/.idea/ktfmt.xml 50 | 51 | # Ctags 52 | **/tags 53 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/externalDependencies.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/ktfmt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/debug/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/debug/java/org/groundplatform/android/HiltTestActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android 17 | 18 | import dagger.hilt.android.AndroidEntryPoint 19 | 20 | @AndroidEntryPoint class HiltTestActivity : AbstractActivity() 21 | -------------------------------------------------------------------------------- /app/src/debug/local/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "334087903719", 4 | "project_id": "local", 5 | "storage_bucket": "local.appspot.com" 6 | }, 7 | "client": [ 8 | { 9 | "client_info": { 10 | "mobilesdk_app_id": "1:334087903719:android:277f0bf3c1887739f40542", 11 | "android_client_info": { 12 | "package_name": "org.groundplatform.android" 13 | } 14 | }, 15 | "oauth_client": [ 16 | { 17 | "client_id": "local.apps.googleusercontent.com", 18 | "client_type": 3 19 | } 20 | ], 21 | "api_key": [ 22 | { 23 | "current_key": "AIzaSyBKXBjsrQzgpbhgP9RwuOG6xWww83eKi_Q" 24 | } 25 | ], 26 | "services": { 27 | "appinvite_service": { 28 | "other_platform_oauth_client": [] 29 | } 30 | } 31 | } 32 | ], 33 | "configuration_version": "1" 34 | } -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/debug/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 20 | #FFFFFF 21 | -------------------------------------------------------------------------------- /app/src/debug/resources/jacoco-agent.properties: -------------------------------------------------------------------------------- 1 | output=none -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ground-android/60d4cc3ae9ba06d656d1e8161fa5f93a7c7e8b81/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/ExcludeFromJacocoGeneratedReport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android 17 | 18 | // https://stackoverflow.com/questions/47824761/how-would-i-add-an-annotation-to-exclude-a-method-from-a-jacoco-code-coverage-re 19 | @Retention(AnnotationRetention.RUNTIME) 20 | @Target(AnnotationTarget.FUNCTION) 21 | annotation class ExcludeFromJacocoGeneratedReport 22 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/MainUiState.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.groundplatform.android 18 | 19 | sealed class MainUiState { 20 | 21 | data object OnPermissionDenied : MainUiState() 22 | 23 | data object OnUserSignedOut : MainUiState() 24 | 25 | data object OnUserSigningIn : MainUiState() 26 | 27 | data object TosNotAccepted : MainUiState() 28 | 29 | data object NoActiveSurvey : MainUiState() 30 | 31 | data object ShowHomeScreen : MainUiState() 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/SettingsActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android 17 | 18 | import android.os.Bundle 19 | import dagger.hilt.android.AndroidEntryPoint 20 | import org.groundplatform.android.databinding.SettingsActivityBinding 21 | 22 | @AndroidEntryPoint 23 | class SettingsActivity : AbstractActivity() { 24 | override fun onCreate(savedInstanceState: Bundle?) { 25 | super.onCreate(savedInstanceState) 26 | 27 | val binding = SettingsActivityBinding.inflate(layoutInflater) 28 | setContentView(binding.root) 29 | 30 | with(binding.settingsToolbar) { 31 | setSupportActionBar(this) 32 | setNavigationOnClickListener { finish() } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/Role.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model 17 | 18 | enum class Role { 19 | DATA_COLLECTOR, 20 | OWNER, 21 | SURVEY_ORGANIZER, 22 | VIEWER, 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/SurveyListItem.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.groundplatform.android.model 18 | 19 | data class SurveyListItem( 20 | val id: String, 21 | val title: String, 22 | val description: String, 23 | val availableOffline: Boolean, 24 | ) 25 | 26 | fun Survey.toListItem(availableOffline: Boolean): SurveyListItem = 27 | SurveyListItem(id, title, description, availableOffline) 28 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/TermsOfService.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model 17 | 18 | /** If present in remote db, terms of service must be accepted by user after sign in. */ 19 | data class TermsOfService(val id: String, val text: String?) 20 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/User.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model 17 | 18 | /** Represents a single application user. */ 19 | data class User( 20 | val id: String, 21 | val email: String, 22 | val displayName: String, 23 | val photoUrl: String? = null, 24 | val isAnonymous: Boolean = false, 25 | ) 26 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/geometry/Coordinates.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model.geometry 17 | 18 | import kotlinx.serialization.Serializable 19 | 20 | /** A pair of latitude and longitude coordinates in decimal degrees. */ 21 | @Serializable 22 | data class Coordinates(val lat: Double, val lng: Double) : Comparable { 23 | override fun compareTo(other: Coordinates): Int = 24 | compareValuesBy(this, other, { it.lat }, { it.lng }) 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/geometry/InvalidGeometryException.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model.geometry 17 | 18 | /** 19 | * Represents types of geometry errors. 20 | * 21 | * Typically thrown when a construction does not satisfy definitional constraints for a given 22 | * geometry. 23 | */ 24 | class InvalidGeometryException(override val message: String) : Throwable(message) 25 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/imagery/OfflineArea.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model.imagery 17 | 18 | import org.groundplatform.android.ui.map.Bounds 19 | import org.groundplatform.android.ui.map.gms.mog.TileCoordinates 20 | 21 | /** An area is a contiguous set of tiles that task a geodesic rectangle. */ 22 | data class OfflineArea( 23 | val id: String, 24 | val state: State, 25 | val bounds: Bounds, 26 | val name: String, 27 | /** The range of zoom levels downloaded. */ 28 | val zoomRange: IntRange, 29 | ) { 30 | val tiles 31 | get() = zoomRange.flatMap { TileCoordinates.withinBounds(bounds, it) } 32 | 33 | enum class State { 34 | PENDING, 35 | IN_PROGRESS, 36 | DOWNLOADED, 37 | FAILED, 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/imagery/TileSource.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model.imagery 17 | 18 | import org.groundplatform.android.ui.map.Bounds 19 | 20 | /** Represents a single source of tiled map imagery. */ 21 | sealed class TileSource 22 | 23 | data class LocalTileSource(val localFilePath: String, val clipBounds: List) : TileSource() 24 | 25 | data class RemoteMogTileSource(val remotePath: String) : TileSource() 26 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/job/Style.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model.job 17 | 18 | data class Style(val color: String) 19 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/submission/CaptureLocationTaskData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model.submission 17 | 18 | import org.groundplatform.android.model.geometry.Point 19 | import org.groundplatform.android.proto.Task 20 | 21 | /** User-provided response to a "capture location" data collection [Task]. */ 22 | data class CaptureLocationTaskData( 23 | val location: Point, 24 | val altitude: Double?, // in metres 25 | val accuracy: Double?, // in metres 26 | ) : TaskData { 27 | 28 | override fun isEmpty(): Boolean = false 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/submission/DateTimeTaskData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model.submission 17 | 18 | import kotlinx.serialization.Serializable 19 | 20 | /** A user-provided response to a date and time question task. */ 21 | @Serializable 22 | data class DateTimeTaskData(val timeInMillis: Long) : TaskData { 23 | 24 | override fun isEmpty(): Boolean = timeInMillis == 0L 25 | 26 | companion object { 27 | fun fromMillis(timeInMillis: Long): TaskData = DateTimeTaskData(timeInMillis) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/submission/DraftSubmission.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model.submission 17 | 18 | /** Represents a single instance of data being collected by the user. */ 19 | data class DraftSubmission( 20 | val id: String, 21 | val jobId: String, 22 | val loiId: String?, 23 | val loiName: String?, 24 | val surveyId: String, 25 | val deltas: List, 26 | val currentTaskId: String?, 27 | ) 28 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/submission/NumberTaskData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model.submission 17 | 18 | import kotlinx.serialization.Serializable 19 | 20 | /** A user provided response to a number question task. */ 21 | @Serializable 22 | data class NumberTaskData(val number: String) : TaskData { 23 | val value: Double 24 | get() = number.toDouble() 25 | 26 | override fun isEmpty(): Boolean = number.isEmpty() 27 | 28 | companion object { 29 | fun fromNumber(number: String): TaskData? = 30 | if (number.isEmpty() || number.toDoubleOrNull() == null) null else NumberTaskData(number) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/submission/PhotoTaskData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model.submission 17 | 18 | import kotlinx.serialization.Serializable 19 | import org.groundplatform.android.model.job.Job 20 | import org.groundplatform.android.model.locationofinterest.LocationOfInterest 21 | 22 | /** Represents a single photo associated with a given [LocationOfInterest] and [Job]. */ 23 | @Serializable 24 | class PhotoTaskData(val remoteFilename: String) : TaskData { 25 | 26 | override fun isEmpty(): Boolean = remoteFilename.isEmpty() 27 | 28 | override fun toString(): String = remoteFilename 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/submission/SkippedTaskData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model.submission 17 | 18 | import kotlinx.serialization.Serializable 19 | 20 | /** User skipped the response for the given task. */ 21 | @Serializable 22 | class SkippedTaskData : TaskData { 23 | 24 | override fun isEmpty(): Boolean = true 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/submission/TaskData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model.submission 17 | 18 | /** User-provided value for a single data collection [Task]. */ 19 | interface TaskData { 20 | fun isEmpty(): Boolean 21 | } 22 | 23 | fun TaskData?.isNullOrEmpty(): Boolean = this?.isEmpty() ?: true 24 | 25 | fun TaskData?.isNotNullOrEmpty(): Boolean = !this.isNullOrEmpty() 26 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/submission/TextTaskData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model.submission 17 | 18 | import kotlinx.serialization.Serializable 19 | 20 | /** A user-provided value to a text question task. */ 21 | @Serializable 22 | data class TextTaskData(val text: String) : TaskData { 23 | override fun isEmpty(): Boolean = text.trim { it <= ' ' }.isEmpty() 24 | 25 | companion object { 26 | fun fromString(text: String): TaskData? = if (text.isEmpty()) null else TextTaskData(text) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/submission/ValueDelta.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model.submission 17 | 18 | import org.groundplatform.android.model.task.Task 19 | 20 | /** 21 | * Represents a change to an individual value in a submission. 22 | * 23 | * @property taskId the id of the task task being updated. 24 | * @property taskType the type of task being updated. 25 | * @property newTaskData the new value of the value, or empty if removed. 26 | */ 27 | data class ValueDelta(val taskId: String, val taskType: Task.Type, val newTaskData: TaskData?) 28 | -------------------------------------------------------------------------------- /app/src/main/java/org/groundplatform/android/model/task/MultipleChoice.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.groundplatform.android.model.task 17 | 18 | import kotlinx.collections.immutable.PersistentList 19 | import kotlinx.collections.immutable.persistentListOf 20 | import kotlinx.serialization.Serializable 21 | 22 | /** A question task with pre-defined options for the user to choose from. */ 23 | @Serializable 24 | data class MultipleChoice 25 | @JvmOverloads 26 | constructor( 27 | val options: PersistentList