From dbf7d25c8b67f95724b01ffec0ca3213b44cca35 Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Thu, 28 Nov 2024 12:24:34 +0000 Subject: [PATCH 01/12] Convert properties to functions --- .../drafts/BulkFinalizationViewModel.kt | 3 ++- .../InstancesDataService.kt | 26 +++++++------------ .../android/mainmenu/MainMenuViewModel.kt | 10 +++---- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/collect_app/src/main/java/org/odk/collect/android/formmanagement/drafts/BulkFinalizationViewModel.kt b/collect_app/src/main/java/org/odk/collect/android/formmanagement/drafts/BulkFinalizationViewModel.kt index f5f2995164d..f23a3b291a7 100644 --- a/collect_app/src/main/java/org/odk/collect/android/formmanagement/drafts/BulkFinalizationViewModel.kt +++ b/collect_app/src/main/java/org/odk/collect/android/formmanagement/drafts/BulkFinalizationViewModel.kt @@ -2,6 +2,7 @@ package org.odk.collect.android.formmanagement.drafts import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.asLiveData import org.odk.collect.android.instancemanagement.FinalizeAllResult import org.odk.collect.android.instancemanagement.InstancesDataService import org.odk.collect.androidshared.data.Consumable @@ -23,7 +24,7 @@ class BulkFinalizationViewModel( private val _isFinalizing = MutableNonNullLiveData(false) val isFinalizing: NonNullLiveData = _isFinalizing - val draftsCount = instancesDataService.editableCount + val draftsCount = instancesDataService.getEditableCount("blah").asLiveData() val isEnabled = settingsProvider.getProtectedSettings().getBoolean(ProtectedProjectKeys.KEY_BULK_FINALIZE) diff --git a/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt b/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt index cdbaad8fa35..06d19a73d0e 100644 --- a/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt +++ b/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt @@ -1,7 +1,5 @@ package org.odk.collect.android.instancemanagement -import androidx.lifecycle.LiveData -import androidx.lifecycle.asLiveData import kotlinx.coroutines.flow.Flow import org.odk.collect.analytics.Analytics import org.odk.collect.android.analytics.AnalyticsEvents @@ -22,8 +20,6 @@ import org.odk.collect.androidshared.data.AppState import org.odk.collect.androidshared.data.getData import org.odk.collect.forms.Form import org.odk.collect.forms.instances.Instance -import org.odk.collect.forms.instances.Instance.STATUS_COMPLETE -import org.odk.collect.forms.instances.Instance.STATUS_SUBMISSION_FAILED import org.odk.collect.metadata.PropertyManager import org.odk.collect.projects.ProjectDependencyFactory import java.io.File @@ -38,17 +34,15 @@ class InstancesDataService( private val onUpdate: () -> Unit ) { - private val _editableCount = appState.getData(DataKeys.INSTANCES_EDITABLE_COUNT, 0) - val editableCount: LiveData = _editableCount.get().asLiveData() - - private val _sendableCount = appState.getData(DataKeys.INSTANCES_SENDABLE_COUNT, 0) - val sendableCount: LiveData = _sendableCount.get().asLiveData() - - private val _sentCount = appState.getData(DataKeys.INSTANCES_SENT_COUNT, 0) - val sentCount: LiveData = _sentCount.get().asLiveData() - + private val editableCount = appState.getData(DataKeys.INSTANCES_EDITABLE_COUNT, 0) + private val sendableCount = appState.getData(DataKeys.INSTANCES_SENDABLE_COUNT, 0) + private val sentCount = appState.getData(DataKeys.INSTANCES_SENT_COUNT, 0) private val instances = appState.getData>(DataKeys.INSTANCES, emptyList()) + fun getEditableCount(projectId: String): Flow = editableCount.get() + fun getSendableCount(projectId: String): Flow = sendableCount.get() + fun getSentCount(projectId: String): Flow = sentCount.get() + fun getInstances(projectId: String): Flow> { return instances.get(projectId) } @@ -71,9 +65,9 @@ class InstancesDataService( Instance.STATUS_VALID ) - _editableCount.set(editableInstances) - _sendableCount.set(sendableInstances) - _sentCount.set(sentInstances) + editableCount.set(editableInstances) + sendableCount.set(sendableInstances) + sentCount.set(sentInstances) instances.set(projectId, instancesRepository.all) onUpdate() diff --git a/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt b/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt index b99578d6f1d..07161b59b1f 100644 --- a/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt +++ b/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt @@ -5,6 +5,7 @@ import android.net.Uri import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.asLiveData import androidx.lifecycle.map import org.odk.collect.android.instancemanagement.InstanceDiskSynchronizer import org.odk.collect.android.instancemanagement.InstancesDataService @@ -114,14 +115,11 @@ class MainMenuViewModel( }) { } } - val editableInstancesCount: LiveData - get() = instancesDataService.editableCount + val editableInstancesCount: LiveData = instancesDataService.getEditableCount("blah").asLiveData() - val sendableInstancesCount: LiveData - get() = instancesDataService.sendableCount + val sendableInstancesCount: LiveData = instancesDataService.getSendableCount("blah").asLiveData() - val sentInstancesCount: LiveData - get() = instancesDataService.sentCount + val sentInstancesCount: LiveData = instancesDataService.getSentCount("blah").asLiveData() fun setSavedForm(uri: Uri?) { if (uri == null) { From c5b595addbde5473700c2640946f4867a598e8c4 Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Thu, 28 Nov 2024 14:43:49 +0000 Subject: [PATCH 02/12] Make instances counts project specific --- .../collect/androidshared/data/AppState.kt | 14 +-- .../odk/collect/androidshared/data/Data.kt | 4 +- .../drafts/BulkFinalizationViewModel.kt | 2 +- .../InstancesDataService.kt | 16 +-- .../android/mainmenu/MainMenuViewModel.kt | 20 ++- .../InstancesDataServiceTest.kt | 119 ++++++++++++++---- 6 files changed, 121 insertions(+), 54 deletions(-) diff --git a/androidshared/src/main/java/org/odk/collect/androidshared/data/AppState.kt b/androidshared/src/main/java/org/odk/collect/androidshared/data/AppState.kt index e18ea2bddbf..511f87a98f8 100644 --- a/androidshared/src/main/java/org/odk/collect/androidshared/data/AppState.kt +++ b/androidshared/src/main/java/org/odk/collect/androidshared/data/AppState.kt @@ -5,11 +5,9 @@ import android.app.Application import android.app.Service import android.content.Context import androidx.fragment.app.Fragment -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow /** * [AppState] can be used as a shared store of state that lives at an "app"/"in-memory" level @@ -48,11 +46,7 @@ class AppState { return map[key] as T? } - fun getLive(key: String, default: T): LiveData { - return get(key, MutableLiveData(default)) - } - - fun getFlow(key: String, default: T): Flow { + fun getFlow(key: String, default: T): StateFlow { return get(key, MutableStateFlow(default)) } @@ -60,10 +54,6 @@ class AppState { map[key] = value } - fun setLive(key: String, value: T?) { - get(key, MutableLiveData()).postValue(value) - } - fun setFlow(key: String, value: T) { get>(key).let { if (it != null) { diff --git a/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt b/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt index 23ceb31936e..d17c1b3b4b1 100644 --- a/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt +++ b/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt @@ -1,9 +1,9 @@ package org.odk.collect.androidshared.data -import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.StateFlow class Data(private val appState: AppState, private val key: String, private val default: T) { - fun get(qualifier: String? = null): Flow { + fun get(qualifier: String? = null): StateFlow { return appState.getFlow("$qualifier:$key", default) } diff --git a/collect_app/src/main/java/org/odk/collect/android/formmanagement/drafts/BulkFinalizationViewModel.kt b/collect_app/src/main/java/org/odk/collect/android/formmanagement/drafts/BulkFinalizationViewModel.kt index f23a3b291a7..3f190bd0b3e 100644 --- a/collect_app/src/main/java/org/odk/collect/android/formmanagement/drafts/BulkFinalizationViewModel.kt +++ b/collect_app/src/main/java/org/odk/collect/android/formmanagement/drafts/BulkFinalizationViewModel.kt @@ -24,7 +24,7 @@ class BulkFinalizationViewModel( private val _isFinalizing = MutableNonNullLiveData(false) val isFinalizing: NonNullLiveData = _isFinalizing - val draftsCount = instancesDataService.getEditableCount("blah").asLiveData() + val draftsCount = instancesDataService.getEditableCount(projectId).asLiveData() val isEnabled = settingsProvider.getProtectedSettings().getBoolean(ProtectedProjectKeys.KEY_BULK_FINALIZE) diff --git a/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt b/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt index 06d19a73d0e..632c8f5971e 100644 --- a/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt +++ b/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt @@ -1,6 +1,6 @@ package org.odk.collect.android.instancemanagement -import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.StateFlow import org.odk.collect.analytics.Analytics import org.odk.collect.android.analytics.AnalyticsEvents import org.odk.collect.android.application.Collect @@ -39,11 +39,11 @@ class InstancesDataService( private val sentCount = appState.getData(DataKeys.INSTANCES_SENT_COUNT, 0) private val instances = appState.getData>(DataKeys.INSTANCES, emptyList()) - fun getEditableCount(projectId: String): Flow = editableCount.get() - fun getSendableCount(projectId: String): Flow = sendableCount.get() - fun getSentCount(projectId: String): Flow = sentCount.get() + fun getEditableCount(projectId: String): StateFlow = editableCount.get(projectId) + fun getSendableCount(projectId: String): StateFlow = sendableCount.get(projectId) + fun getSentCount(projectId: String): StateFlow = sentCount.get(projectId) - fun getInstances(projectId: String): Flow> { + fun getInstances(projectId: String): StateFlow> { return instances.get(projectId) } @@ -65,9 +65,9 @@ class InstancesDataService( Instance.STATUS_VALID ) - editableCount.set(editableInstances) - sendableCount.set(sendableInstances) - sentCount.set(sentInstances) + editableCount.set(projectId, editableInstances) + sendableCount.set(projectId, sendableInstances) + sentCount.set(projectId, sentInstances) instances.set(projectId, instancesRepository.all) onUpdate() diff --git a/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt b/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt index 07161b59b1f..c622f93baae 100644 --- a/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt +++ b/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.asLiveData import androidx.lifecycle.map +import androidx.lifecycle.switchMap import org.odk.collect.android.instancemanagement.InstanceDiskSynchronizer import org.odk.collect.android.instancemanagement.InstancesDataService import org.odk.collect.android.instancemanagement.autosend.AutoSendSettingsProvider @@ -65,6 +66,8 @@ class MainMenuViewModel( } } + private val project = MutableLiveData(projectsDataService.getCurrentProject()) + private val _savedForm = MutableLiveData() val savedForm: LiveData> = _savedForm.map { Consumable(it) } @@ -110,16 +113,25 @@ class MainMenuViewModel( fun refreshInstances() { scheduler.immediate({ InstanceDiskSynchronizer(settingsProvider).doInBackground() - instancesDataService.update(projectsDataService.getCurrentProject().uuid) + + val currentProject = projectsDataService.getCurrentProject() + instancesDataService.update(currentProject.uuid) + project.postValue(currentProject) null }) { } } - val editableInstancesCount: LiveData = instancesDataService.getEditableCount("blah").asLiveData() + val editableInstancesCount: LiveData = project.switchMap { + instancesDataService.getEditableCount(it.uuid).asLiveData() + } - val sendableInstancesCount: LiveData = instancesDataService.getSendableCount("blah").asLiveData() + val sendableInstancesCount: LiveData = project.switchMap { + instancesDataService.getSendableCount(it.uuid).asLiveData() + } - val sentInstancesCount: LiveData = instancesDataService.getSentCount("blah").asLiveData() + val sentInstancesCount: LiveData = project.switchMap { + instancesDataService.getSentCount(it.uuid).asLiveData() + } fun setSavedForm(uri: Uri?) { if (uri == null) { diff --git a/collect_app/src/test/java/org/odk/collect/android/instancemanagement/InstancesDataServiceTest.kt b/collect_app/src/test/java/org/odk/collect/android/instancemanagement/InstancesDataServiceTest.kt index a30eead37ca..c727e6380cd 100644 --- a/collect_app/src/test/java/org/odk/collect/android/instancemanagement/InstancesDataServiceTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/instancemanagement/InstancesDataServiceTest.kt @@ -34,30 +34,26 @@ import java.io.File @RunWith(AndroidJUnit4::class) class InstancesDataServiceTest { - - private val settings = InMemSettings().also { - it.save(ProjectKeys.KEY_SERVER_URL, "http://example.com") - } - - private val changeLocks = ChangeLocks(BooleanChangeLock(), BooleanChangeLock()) - private val formsRepository = InMemFormsRepository() - private val instancesRepository = InMemInstancesRepository() - - private val projectsDependencyModuleFactory = ProjectDependencyFactory { + private val projectsDependencyModuleFactory = CachingProjectDependencyModuleFactory { projectId -> ProjectDependencyModule( - it, - { settings }, - { formsRepository }, - { instancesRepository }, + projectId, + { + InMemSettings().also { + it.save(ProjectKeys.KEY_SERVER_URL, "http://example.com") + } + }, + { InMemFormsRepository() }, + { InMemInstancesRepository() }, mock(), - { changeLocks }, + { ChangeLocks(BooleanChangeLock(), BooleanChangeLock()) }, mock(), mock(), mock() ) } - private val projectDependencyModule = projectsDependencyModuleFactory.create("blah") + private val projectId = "projectId" + private val projectDependencyModule = projectsDependencyModuleFactory.create(projectId) private val httpInterface = mock() private val notifier = mock() @@ -75,25 +71,25 @@ class InstancesDataServiceTest { @Test fun `instances should not be deleted if the instances database is locked`() { projectDependencyModule.instancesLock.lock() - val result = instancesDataService.deleteInstances("projectId", longArrayOf(1)) + val result = instancesDataService.deleteInstances(projectId, longArrayOf(1)) assertThat(result, equalTo(false)) } @Test fun `instances should be deleted if the instances database is not locked`() { - val result = instancesDataService.deleteInstances("projectId", longArrayOf(1)) + val result = instancesDataService.deleteInstances(projectId, longArrayOf(1)) assertThat(result, equalTo(true)) } @Test fun `sendInstances() returns true when there are no instances to send`() { - val result = instancesDataService.sendInstances("projectId") + val result = instancesDataService.sendInstances(projectId) assertThat(result, equalTo(true)) } @Test fun `sendInstances() does not notify when there are no instances to send`() { - instancesDataService.sendInstances("projectId") + instancesDataService.sendInstances(projectId) verifyNoInteractions(notifier) } @@ -108,7 +104,7 @@ class InstancesDataServiceTest { whenever(httpInterface.executeGetRequest(any(), any(), any())) .doReturn(HttpGetResult(null, emptyMap(), "", 500)) - val result = instancesDataService.sendInstances("projectId") + val result = instancesDataService.sendInstances(projectId) assertThat(result, equalTo(false)) } @@ -118,12 +114,48 @@ class InstancesDataServiceTest { val form = formsRepository.save(FormFixtures.form()) val instancesRepository = projectDependencyModule.instancesRepository - instancesRepository.save(InstanceFixtures.instance(form = form, canDeleteBeforeSend = false, status = STATUS_INCOMPLETE)) - instancesRepository.save(InstanceFixtures.instance(form = form, canDeleteBeforeSend = false, status = STATUS_COMPLETE)) - instancesRepository.save(InstanceFixtures.instance(form = form, canDeleteBeforeSend = false, status = STATUS_INVALID)) - instancesRepository.save(InstanceFixtures.instance(form = form, canDeleteBeforeSend = false, status = STATUS_VALID)) - instancesRepository.save(InstanceFixtures.instance(form = form, canDeleteBeforeSend = false, status = STATUS_SUBMITTED)) - instancesRepository.save(InstanceFixtures.instance(form = form, canDeleteBeforeSend = false, status = STATUS_SUBMISSION_FAILED)) + instancesRepository.save( + InstanceFixtures.instance( + form = form, + canDeleteBeforeSend = false, + status = STATUS_INCOMPLETE + ) + ) + instancesRepository.save( + InstanceFixtures.instance( + form = form, + canDeleteBeforeSend = false, + status = STATUS_COMPLETE + ) + ) + instancesRepository.save( + InstanceFixtures.instance( + form = form, + canDeleteBeforeSend = false, + status = STATUS_INVALID + ) + ) + instancesRepository.save( + InstanceFixtures.instance( + form = form, + canDeleteBeforeSend = false, + status = STATUS_VALID + ) + ) + instancesRepository.save( + InstanceFixtures.instance( + form = form, + canDeleteBeforeSend = false, + status = STATUS_SUBMITTED + ) + ) + instancesRepository.save( + InstanceFixtures.instance( + form = form, + canDeleteBeforeSend = false, + status = STATUS_SUBMISSION_FAILED + ) + ) instancesDataService.reset(projectDependencyModule.projectId) val remainingInstances = instancesRepository.all @@ -133,4 +165,37 @@ class InstancesDataServiceTest { assertThat(File(remainingInstances[0].instanceFilePath).parentFile?.exists(), equalTo(true)) assertThat(File(remainingInstances[1].instanceFilePath).parentFile?.exists(), equalTo(true)) } + + @Test + fun `#update updates instances and counts`() { + val instancesRepository = projectDependencyModule.instancesRepository + instancesRepository.save(InstanceFixtures.instance(status = STATUS_COMPLETE)) + instancesRepository.save(InstanceFixtures.instance(status = STATUS_SUBMITTED)) + instancesRepository.save(InstanceFixtures.instance(status = STATUS_INCOMPLETE)) + + instancesDataService.update(projectId) + assertThat( + instancesDataService.getInstances(projectId).value, + equalTo(instancesRepository.all) + ) + assertThat(instancesDataService.getSentCount(projectId).value, equalTo(1)) + assertThat(instancesDataService.getEditableCount(projectId).value, equalTo(1)) + assertThat(instancesDataService.getSendableCount(projectId).value, equalTo(1)) + assertThat(instancesDataService.getInstances("otherProjectId").value, equalTo(emptyList())) + assertThat(instancesDataService.getSentCount("otherProjectId").value, equalTo(0)) + assertThat(instancesDataService.getEditableCount("otherProjectId").value, equalTo(0)) + assertThat(instancesDataService.getSendableCount("otherProjectId").value, equalTo(0)) + } +} + +class CachingProjectDependencyModuleFactory(private val moduleFactory: (String) -> ProjectDependencyModule) : + ProjectDependencyFactory { + + private val modules = mutableMapOf() + + override fun create(projectId: String): ProjectDependencyModule { + return modules.getOrPut(projectId) { + moduleFactory(projectId) + } + } } From 6a5cee2cff05a7c0bb9539bd5793defb0a26d134 Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Thu, 28 Nov 2024 17:25:22 +0000 Subject: [PATCH 03/12] Use Flow for current project --- .../injection/config/AppDependencyModule.java | 4 +- .../mainmenu/CurrentProjectViewModel.kt | 21 +++++----- .../android/mainmenu/MainMenuFragment.kt | 38 +++++++++---------- .../android/mainmenu/MainMenuViewModel.kt | 20 ++++------ .../android/projects/ProjectSettingsDialog.kt | 24 ++++++++---- .../android/projects/ProjectsDataService.kt | 22 +++++++++++ .../org/odk/collect/android/state/DataKeys.kt | 1 + 7 files changed, 78 insertions(+), 52 deletions(-) diff --git a/collect_app/src/main/java/org/odk/collect/android/injection/config/AppDependencyModule.java b/collect_app/src/main/java/org/odk/collect/android/injection/config/AppDependencyModule.java index 34af678eab1..dc4ae97ab5a 100644 --- a/collect_app/src/main/java/org/odk/collect/android/injection/config/AppDependencyModule.java +++ b/collect_app/src/main/java/org/odk/collect/android/injection/config/AppDependencyModule.java @@ -441,8 +441,8 @@ public FastExternalItemsetsRepository providesItemsetsRepository() { } @Provides - public ProjectsDataService providesCurrentProjectProvider(SettingsProvider settingsProvider, ProjectsRepository projectsRepository, AnalyticsInitializer analyticsInitializer, Context context, MapsInitializer mapsInitializer) { - return new ProjectsDataService(settingsProvider, projectsRepository, analyticsInitializer, mapsInitializer); + public ProjectsDataService providesCurrentProjectProvider(Application application, SettingsProvider settingsProvider, ProjectsRepository projectsRepository, AnalyticsInitializer analyticsInitializer, Context context, MapsInitializer mapsInitializer) { + return new ProjectsDataService(getState(application), settingsProvider, projectsRepository, analyticsInitializer, mapsInitializer); } @Provides diff --git a/collect_app/src/main/java/org/odk/collect/android/mainmenu/CurrentProjectViewModel.kt b/collect_app/src/main/java/org/odk/collect/android/mainmenu/CurrentProjectViewModel.kt index 667a1038695..383a93749da 100644 --- a/collect_app/src/main/java/org/odk/collect/android/mainmenu/CurrentProjectViewModel.kt +++ b/collect_app/src/main/java/org/odk/collect/android/mainmenu/CurrentProjectViewModel.kt @@ -1,30 +1,25 @@ package org.odk.collect.android.mainmenu import androidx.lifecycle.ViewModel +import androidx.lifecycle.asLiveData import org.odk.collect.analytics.Analytics import org.odk.collect.android.analytics.AnalyticsEvents import org.odk.collect.android.projects.ProjectsDataService -import org.odk.collect.androidshared.livedata.MutableNonNullLiveData -import org.odk.collect.androidshared.livedata.NonNullLiveData import org.odk.collect.projects.Project class CurrentProjectViewModel( private val projectsDataService: ProjectsDataService ) : ViewModel() { - private val _currentProject by lazy { MutableNonNullLiveData(projectsDataService.getCurrentProject()) } - val currentProject: NonNullLiveData by lazy { _currentProject } + init { + projectsDataService.update() + } + + val currentProject = projectsDataService.getCurrentProjectFlow().asLiveData() fun setCurrentProject(project: Project.Saved) { Analytics.log(AnalyticsEvents.SWITCH_PROJECT) projectsDataService.setCurrentProject(project.uuid) - refresh() - } - - fun refresh() { - if (currentProject.value != projectsDataService.getCurrentProject()) { - _currentProject.value = projectsDataService.getCurrentProject() - } } fun hasCurrentProject(): Boolean { @@ -35,4 +30,8 @@ class CurrentProjectViewModel( false } } + + fun refresh() { + projectsDataService.update() + } } diff --git a/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuFragment.kt b/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuFragment.kt index ba4a4e74516..9ff3b370d37 100644 --- a/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuFragment.kt +++ b/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuFragment.kt @@ -30,7 +30,6 @@ import org.odk.collect.androidshared.data.consume import org.odk.collect.androidshared.ui.DialogFragmentUtils import org.odk.collect.androidshared.ui.SnackbarUtils import org.odk.collect.androidshared.ui.multiclicksafe.MultiClickGuard -import org.odk.collect.projects.Project import org.odk.collect.settings.SettingsProvider import org.odk.collect.strings.R.string import org.odk.collect.webpage.WebViewActivity @@ -69,9 +68,11 @@ class MainMenuFragment( } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - currentProjectViewModel.currentProject.observe(viewLifecycleOwner) { (_, name): Project.Saved -> - requireActivity().invalidateOptionsMenu() - requireActivity().title = name + currentProjectViewModel.currentProject.observe(viewLifecycleOwner) { project -> + if (project != null) { + requireActivity().invalidateOptionsMenu() + requireActivity().title = project.name + } } val binding = MainMenuBinding.bind(view) @@ -104,17 +105,27 @@ class MainMenuFragment( displayDismissButton = true ) } + + currentProjectViewModel.currentProject.observe(viewLifecycleOwner) { + if (it?.isOldGoogleDriveProject == true) { + binding.googleDriveDeprecationBanner.root.visibility = View.VISIBLE + binding.googleDriveDeprecationBanner.learnMoreButton.setOnClickListener { + val intent = Intent(requireContext(), WebViewActivity::class.java) + intent.putExtra("url", "https://forum.getodk.org/t/40097") + startActivity(intent) + } + } else { + binding.googleDriveDeprecationBanner.root.visibility = View.GONE + } + } } override fun onResume() { super.onResume() - - currentProjectViewModel.refresh() mainMenuViewModel.refreshInstances() val binding = MainMenuBinding.bind(requireView()) setButtonsVisibility(binding) - manageGoogleDriveDeprecationBanner(binding) } override fun onPrepareOptionsMenu(menu: Menu) { @@ -249,17 +260,4 @@ class MainMenuFragment( binding.manageForms.visibility = if (mainMenuViewModel.shouldDeleteSavedFormButtonBeVisible()) View.VISIBLE else View.GONE } - - private fun manageGoogleDriveDeprecationBanner(binding: MainMenuBinding) { - if (currentProjectViewModel.currentProject.value.isOldGoogleDriveProject) { - binding.googleDriveDeprecationBanner.root.visibility = View.VISIBLE - binding.googleDriveDeprecationBanner.learnMoreButton.setOnClickListener { - val intent = Intent(requireContext(), WebViewActivity::class.java) - intent.putExtra("url", "https://forum.getodk.org/t/40097") - startActivity(intent) - } - } else { - binding.googleDriveDeprecationBanner.root.visibility = View.GONE - } - } } diff --git a/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt b/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt index c622f93baae..901f34018a2 100644 --- a/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt +++ b/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt @@ -66,8 +66,6 @@ class MainMenuViewModel( } } - private val project = MutableLiveData(projectsDataService.getCurrentProject()) - private val _savedForm = MutableLiveData() val savedForm: LiveData> = _savedForm.map { Consumable(it) } @@ -113,24 +111,22 @@ class MainMenuViewModel( fun refreshInstances() { scheduler.immediate({ InstanceDiskSynchronizer(settingsProvider).doInBackground() - - val currentProject = projectsDataService.getCurrentProject() - instancesDataService.update(currentProject.uuid) - project.postValue(currentProject) + instancesDataService.update(projectsDataService.getCurrentProject().uuid) null }) { } } - val editableInstancesCount: LiveData = project.switchMap { - instancesDataService.getEditableCount(it.uuid).asLiveData() + private val currentProject = projectsDataService.getCurrentProjectFlow().asLiveData() + val editableInstancesCount: LiveData = currentProject.switchMap { + instancesDataService.getEditableCount(it!!.uuid).asLiveData() } - val sendableInstancesCount: LiveData = project.switchMap { - instancesDataService.getSendableCount(it.uuid).asLiveData() + val sendableInstancesCount: LiveData = currentProject.switchMap { + instancesDataService.getSendableCount(it!!.uuid).asLiveData() } - val sentInstancesCount: LiveData = project.switchMap { - instancesDataService.getSentCount(it.uuid).asLiveData() + val sentInstancesCount: LiveData = currentProject.switchMap { + instancesDataService.getSentCount(it!!.uuid).asLiveData() } fun setSavedForm(uri: Uri?) { diff --git a/collect_app/src/main/java/org/odk/collect/android/projects/ProjectSettingsDialog.kt b/collect_app/src/main/java/org/odk/collect/android/projects/ProjectSettingsDialog.kt index 10b8f30f190..5a83c97adbc 100644 --- a/collect_app/src/main/java/org/odk/collect/android/projects/ProjectSettingsDialog.kt +++ b/collect_app/src/main/java/org/odk/collect/android/projects/ProjectSettingsDialog.kt @@ -24,7 +24,8 @@ import org.odk.collect.projects.ProjectsRepository import org.odk.collect.settings.SettingsProvider import javax.inject.Inject -class ProjectSettingsDialog(private val viewModelFactory: ViewModelProvider.Factory) : DialogFragment() { +class ProjectSettingsDialog(private val viewModelFactory: ViewModelProvider.Factory) : + DialogFragment() { @Inject lateinit var projectsRepository: ProjectsRepository @@ -50,10 +51,15 @@ class ProjectSettingsDialog(private val viewModelFactory: ViewModelProvider.Fact override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { binding = ProjectSettingsDialogLayoutBinding.inflate(LayoutInflater.from(context)) - val project = currentProjectViewModel.currentProject.value - binding.currentProject.setupView(project, settingsProvider.getUnprotectedSettings()) - binding.currentProject.contentDescription = getString(org.odk.collect.strings.R.string.using_project, project.name) - inflateListOfInActiveProjects(requireContext(), project) + currentProjectViewModel.currentProject.observe(this) { + if (it != null) { + binding.currentProject.setupView(it, settingsProvider.getUnprotectedSettings()) + binding.currentProject.contentDescription = + getString(org.odk.collect.strings.R.string.using_project, it.name) + + inflateListOfInActiveProjects(requireContext(), it) + } + } binding.closeIcon.setOnClickListener { dismiss() @@ -99,7 +105,8 @@ class ProjectSettingsDialog(private val viewModelFactory: ViewModelProvider.Fact } projectView.setupView(project, settingsProvider.getUnprotectedSettings(project.uuid)) - projectView.contentDescription = getString(org.odk.collect.strings.R.string.switch_to_project, project.name) + projectView.contentDescription = + getString(org.odk.collect.strings.R.string.switch_to_project, project.name) binding.projectList.addView(projectView) } } @@ -107,7 +114,10 @@ class ProjectSettingsDialog(private val viewModelFactory: ViewModelProvider.Fact private fun switchProject(project: Project.Saved) { currentProjectViewModel.setCurrentProject(project) - ActivityUtils.startActivityAndCloseAllOthers(requireActivity(), MainMenuActivity::class.java) + ActivityUtils.startActivityAndCloseAllOthers( + requireActivity(), + MainMenuActivity::class.java + ) ToastUtils.showLongToast( requireContext(), getString(org.odk.collect.strings.R.string.switched_project, project.name) diff --git a/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt b/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt index f0dead95963..ccbbaedd76b 100644 --- a/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt +++ b/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt @@ -1,19 +1,39 @@ package org.odk.collect.android.projects +import kotlinx.coroutines.flow.StateFlow import org.odk.collect.android.application.initialization.AnalyticsInitializer import org.odk.collect.android.application.initialization.MapsInitializer +import org.odk.collect.android.state.DataKeys +import org.odk.collect.androidshared.data.AppState +import org.odk.collect.androidshared.data.getData import org.odk.collect.projects.Project import org.odk.collect.projects.ProjectsRepository import org.odk.collect.settings.SettingsProvider import org.odk.collect.settings.keys.MetaKeys class ProjectsDataService( + appState: AppState, private val settingsProvider: SettingsProvider, private val projectsRepository: ProjectsRepository, private val analyticsInitializer: AnalyticsInitializer, private val mapsInitializer: MapsInitializer ) { + private val currentProject = appState.getData(DataKeys.PROJECT, null) + + fun update() { + val currentProjectId = getCurrentProjectId() + if (currentProjectId != null) { + currentProject.set(projectsRepository.get(currentProjectId)) + } else { + currentProject.set(null) + } + } + + fun getCurrentProjectFlow(): StateFlow { + return currentProject.get() + } + fun getCurrentProject(): Project.Saved { val currentProjectId = getCurrentProjectId() @@ -41,6 +61,8 @@ class ProjectsDataService( analyticsInitializer.initialize() mapsInitializer.initialize() + + update() } private fun getCurrentProjectId(): String? { diff --git a/collect_app/src/main/java/org/odk/collect/android/state/DataKeys.kt b/collect_app/src/main/java/org/odk/collect/android/state/DataKeys.kt index a38f9664a01..5b93a3f3564 100644 --- a/collect_app/src/main/java/org/odk/collect/android/state/DataKeys.kt +++ b/collect_app/src/main/java/org/odk/collect/android/state/DataKeys.kt @@ -1,6 +1,7 @@ package org.odk.collect.android.state object DataKeys { + const val PROJECT = "project" const val INSTANCES_EDITABLE_COUNT = "instancesEditableCount" const val INSTANCES_SENDABLE_COUNT = "instancesSendableCount" const val INSTANCES_SENT_COUNT = "instancesSentCount" From 7fd96ae1b26262bc5d5c88cf6ae09ede1ee3ae8a Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Tue, 3 Dec 2024 11:58:16 +0000 Subject: [PATCH 04/12] Fix test setups --- .../android/external/FormUriActivityTest.kt | 1 + .../mainmenu/CurrentProjectViewModelTest.kt | 16 ++++++++++------ .../android/mainmenu/MainMenuActivityTest.kt | 3 +-- .../android/mainmenu/MainMenuViewModelTest.kt | 12 +++++++++++- .../screens/MapsPreferencesFragmentTest.kt | 2 ++ .../ProjectDisplayPreferencesFragmentTest.kt | 2 ++ .../projects/ManualProjectCreatorDialogTest.kt | 2 ++ .../android/projects/ProjectDeleterTest.kt | 3 ++- .../projects/ProjectSettingsDialogTest.kt | 4 ++-- .../android/projects/ProjectsDataServiceTest.kt | 10 ++++++++-- 10 files changed, 41 insertions(+), 14 deletions(-) diff --git a/collect_app/src/test/java/org/odk/collect/android/external/FormUriActivityTest.kt b/collect_app/src/test/java/org/odk/collect/android/external/FormUriActivityTest.kt index a25b7cc5aa4..fedcc644b15 100644 --- a/collect_app/src/test/java/org/odk/collect/android/external/FormUriActivityTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/external/FormUriActivityTest.kt @@ -106,6 +106,7 @@ class FormUriActivityTest { } override fun providesCurrentProjectProvider( + application: Application, settingsProvider: SettingsProvider, projectsRepository: ProjectsRepository, analyticsInitializer: AnalyticsInitializer, diff --git a/collect_app/src/test/java/org/odk/collect/android/mainmenu/CurrentProjectViewModelTest.kt b/collect_app/src/test/java/org/odk/collect/android/mainmenu/CurrentProjectViewModelTest.kt index 20452a58269..4f3d9960851 100644 --- a/collect_app/src/test/java/org/odk/collect/android/mainmenu/CurrentProjectViewModelTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/mainmenu/CurrentProjectViewModelTest.kt @@ -1,6 +1,7 @@ package org.odk.collect.android.mainmenu import androidx.arch.core.executor.testing.InstantTaskExecutorRule +import kotlinx.coroutines.flow.MutableStateFlow import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.equalTo import org.junit.Rule @@ -9,7 +10,6 @@ import org.mockito.Mockito.verify import org.mockito.kotlin.doReturn import org.mockito.kotlin.mock import org.mockito.kotlin.whenever -import org.odk.collect.android.application.initialization.AnalyticsInitializer import org.odk.collect.android.projects.ProjectsDataService import org.odk.collect.projects.Project @@ -19,13 +19,17 @@ class CurrentProjectViewModelTest { var instantTaskExecutorRule = InstantTaskExecutorRule() private val projectsDataService = mock { - on { getCurrentProject() } doReturn Project.Saved("123", "Project X", "X", "#cccccc") + on { getCurrentProjectFlow() } doReturn MutableStateFlow( + Project.Saved( + "123", + "Project X", + "X", + "#cccccc" + ) + ) } - private val analyticsInitializer = mock() - private val currentProjectViewModel = CurrentProjectViewModel( - projectsDataService - ) + private val currentProjectViewModel by lazy { CurrentProjectViewModel(projectsDataService) } @Test fun `Initial current project should be set`() { diff --git a/collect_app/src/test/java/org/odk/collect/android/mainmenu/MainMenuActivityTest.kt b/collect_app/src/test/java/org/odk/collect/android/mainmenu/MainMenuActivityTest.kt index e1a206b1292..94a5498937d 100644 --- a/collect_app/src/test/java/org/odk/collect/android/mainmenu/MainMenuActivityTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/mainmenu/MainMenuActivityTest.kt @@ -41,7 +41,6 @@ import org.odk.collect.android.utilities.ApplicationConstants import org.odk.collect.android.utilities.FormsRepositoryProvider import org.odk.collect.android.utilities.InstancesRepositoryProvider import org.odk.collect.android.version.VersionInformation -import org.odk.collect.androidshared.livedata.MutableNonNullLiveData import org.odk.collect.androidtest.ActivityScenarioLauncherRule import org.odk.collect.async.Scheduler import org.odk.collect.crashhandler.CrashHandler @@ -66,7 +65,7 @@ class MainMenuActivityTest { private val currentProjectViewModel = mock { on { hasCurrentProject() } doReturn true - on { currentProject } doReturn MutableNonNullLiveData(project) + on { currentProject } doReturn MutableLiveData(project) } private val permissionsViewModel = mock { diff --git a/collect_app/src/test/java/org/odk/collect/android/mainmenu/MainMenuViewModelTest.kt b/collect_app/src/test/java/org/odk/collect/android/mainmenu/MainMenuViewModelTest.kt index 6305a6dc338..33da9ac3e90 100644 --- a/collect_app/src/test/java/org/odk/collect/android/mainmenu/MainMenuViewModelTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/mainmenu/MainMenuViewModelTest.kt @@ -2,15 +2,18 @@ package org.odk.collect.android.mainmenu import androidx.arch.core.executor.testing.InstantTaskExecutorRule import androidx.test.ext.junit.runners.AndroidJUnit4 +import kotlinx.coroutines.flow.MutableStateFlow import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.equalTo import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.mockito.kotlin.any import org.mockito.kotlin.doReturn import org.mockito.kotlin.mock import org.mockito.kotlin.whenever import org.odk.collect.android.external.InstancesContract +import org.odk.collect.android.instancemanagement.InstancesDataService import org.odk.collect.android.instancemanagement.autosend.AutoSendSettingsProvider import org.odk.collect.android.projects.ProjectsDataService import org.odk.collect.android.utilities.FormsRepositoryProvider @@ -43,6 +46,13 @@ class MainMenuViewModelTest { private val projectsDataService = mock { on { getCurrentProject() } doReturn Project.DEMO_PROJECT + on { getCurrentProjectFlow() } doReturn MutableStateFlow(Project.DEMO_PROJECT) + } + + private val instancesDataService = mock { + on { getSendableCount(any()) } doReturn MutableStateFlow(0) + on { getEditableCount(any()) } doReturn MutableStateFlow(0) + on { getSentCount(any()) } doReturn MutableStateFlow(0) } private val scheduler = FakeScheduler() @@ -365,6 +375,6 @@ class MainMenuViewModelTest { } private fun createViewModelWithVersion(version: String): MainMenuViewModel { - return MainMenuViewModel(mock(), VersionInformation { version }, settingsProvider, mock(), scheduler, formsRepositoryProvider, instancesRepositoryProvider, autoSendSettingsProvider, projectsDataService) + return MainMenuViewModel(mock(), VersionInformation { version }, settingsProvider, instancesDataService, scheduler, formsRepositoryProvider, instancesRepositoryProvider, autoSendSettingsProvider, projectsDataService) } } diff --git a/collect_app/src/test/java/org/odk/collect/android/preferences/screens/MapsPreferencesFragmentTest.kt b/collect_app/src/test/java/org/odk/collect/android/preferences/screens/MapsPreferencesFragmentTest.kt index 3a345d4b137..fe2a061d18e 100644 --- a/collect_app/src/test/java/org/odk/collect/android/preferences/screens/MapsPreferencesFragmentTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/preferences/screens/MapsPreferencesFragmentTest.kt @@ -1,5 +1,6 @@ package org.odk.collect.android.preferences.screens +import android.app.Application import android.content.Context import androidx.preference.Preference import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -49,6 +50,7 @@ class MapsPreferencesFragmentTest { fun setup() { CollectHelpers.overrideAppDependencyModule(object : AppDependencyModule() { override fun providesCurrentProjectProvider( + application: Application, settingsProvider: SettingsProvider, projectsRepository: ProjectsRepository, analyticsInitializer: AnalyticsInitializer, diff --git a/collect_app/src/test/java/org/odk/collect/android/preferences/screens/ProjectDisplayPreferencesFragmentTest.kt b/collect_app/src/test/java/org/odk/collect/android/preferences/screens/ProjectDisplayPreferencesFragmentTest.kt index dd7d779d21a..cc5d3913acf 100644 --- a/collect_app/src/test/java/org/odk/collect/android/preferences/screens/ProjectDisplayPreferencesFragmentTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/preferences/screens/ProjectDisplayPreferencesFragmentTest.kt @@ -1,5 +1,6 @@ package org.odk.collect.android.preferences.screens +import android.app.Application import android.content.Context import androidx.preference.EditTextPreference import androidx.preference.Preference @@ -46,6 +47,7 @@ class ProjectDisplayPreferencesFragmentTest { CollectHelpers.overrideAppDependencyModule(object : AppDependencyModule() { override fun providesCurrentProjectProvider( + application: Application, settingsProvider: SettingsProvider, projectsRepository: ProjectsRepository, analyticsInitializer: AnalyticsInitializer, diff --git a/collect_app/src/test/java/org/odk/collect/android/projects/ManualProjectCreatorDialogTest.kt b/collect_app/src/test/java/org/odk/collect/android/projects/ManualProjectCreatorDialogTest.kt index b81730dc029..99ec41a07d1 100644 --- a/collect_app/src/test/java/org/odk/collect/android/projects/ManualProjectCreatorDialogTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/projects/ManualProjectCreatorDialogTest.kt @@ -1,5 +1,6 @@ package org.odk.collect.android.projects +import android.app.Application import android.content.Context import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.click @@ -127,6 +128,7 @@ class ManualProjectCreatorDialogTest { } override fun providesCurrentProjectProvider( + application: Application, settingsProvider: SettingsProvider, projectsRepository: ProjectsRepository, analyticsInitializer: AnalyticsInitializer, diff --git a/collect_app/src/test/java/org/odk/collect/android/projects/ProjectDeleterTest.kt b/collect_app/src/test/java/org/odk/collect/android/projects/ProjectDeleterTest.kt index e2e36796f5a..4675a8b1e4c 100644 --- a/collect_app/src/test/java/org/odk/collect/android/projects/ProjectDeleterTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/projects/ProjectDeleterTest.kt @@ -15,6 +15,7 @@ import org.odk.collect.android.preferences.Defaults import org.odk.collect.android.storage.StoragePathProvider import org.odk.collect.android.utilities.ChangeLockProvider import org.odk.collect.android.utilities.InstancesRepositoryProvider +import org.odk.collect.androidshared.data.AppState import org.odk.collect.forms.instances.Instance import org.odk.collect.formstest.InMemInstancesRepository import org.odk.collect.projects.InMemProjectsRepository @@ -37,7 +38,7 @@ class ProjectDeleterTest { whenever(create(project1.uuid)).thenReturn(instancesRepository) } private val settingsProvider = InMemSettingsProvider() - private val projectsDataService = ProjectsDataService(settingsProvider, projectsRepository, mock(), mock()) + private val projectsDataService = ProjectsDataService(AppState(), settingsProvider, projectsRepository, mock(), mock()) private val formUpdateScheduler = mock() private val instanceSubmitScheduler = mock() private val storagePathProvider = mock().apply { diff --git a/collect_app/src/test/java/org/odk/collect/android/projects/ProjectSettingsDialogTest.kt b/collect_app/src/test/java/org/odk/collect/android/projects/ProjectSettingsDialogTest.kt index 27146a756e2..f6173747b78 100644 --- a/collect_app/src/test/java/org/odk/collect/android/projects/ProjectSettingsDialogTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/projects/ProjectSettingsDialogTest.kt @@ -1,6 +1,7 @@ package org.odk.collect.android.projects import androidx.core.view.children +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewmodel.initializer import androidx.lifecycle.viewmodel.viewModelFactory import androidx.test.espresso.Espresso.onView @@ -26,7 +27,6 @@ import org.odk.collect.android.injection.config.AppDependencyModule import org.odk.collect.android.mainmenu.CurrentProjectViewModel import org.odk.collect.android.preferences.screens.ProjectPreferencesActivity import org.odk.collect.android.support.CollectHelpers -import org.odk.collect.androidshared.livedata.MutableNonNullLiveData import org.odk.collect.androidshared.ui.FragmentFactoryBuilder import org.odk.collect.fragmentstest.FragmentScenarioLauncherRule import org.odk.collect.projects.InMemProjectsRepository @@ -40,7 +40,7 @@ import org.odk.collect.testshared.RobolectricHelpers class ProjectSettingsDialogTest { private val currentProjectViewModel: CurrentProjectViewModel = mock { - on { currentProject } doReturn MutableNonNullLiveData( + on { currentProject } doReturn MutableLiveData( Project.Saved( "x", "Project X", diff --git a/collect_app/src/test/java/org/odk/collect/android/projects/ProjectsDataServiceTest.kt b/collect_app/src/test/java/org/odk/collect/android/projects/ProjectsDataServiceTest.kt index 51b8f1bcd99..164021dee4d 100644 --- a/collect_app/src/test/java/org/odk/collect/android/projects/ProjectsDataServiceTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/projects/ProjectsDataServiceTest.kt @@ -7,6 +7,7 @@ import org.junit.Test import org.mockito.Mockito.verify import org.mockito.kotlin.mock import org.odk.collect.android.application.initialization.AnalyticsInitializer +import org.odk.collect.androidshared.data.AppState import org.odk.collect.projects.InMemProjectsRepository import org.odk.collect.projects.Project import org.odk.collect.settings.InMemSettingsProvider @@ -18,8 +19,13 @@ class ProjectsDataServiceTest { private val settingsProvider = InMemSettingsProvider() private val metaSettings = settingsProvider.getMetaSettings() private val analyticsInitializer = mock() - private val projectsDataService = - ProjectsDataService(settingsProvider, projectsRepository, analyticsInitializer, mock()) + private val projectsDataService = ProjectsDataService( + AppState(), + settingsProvider, + projectsRepository, + analyticsInitializer, + mock() + ) @Test fun `A project should be returned after calling getCurrentProject() if there is a project for given id`() { From 7cb63f33946bbd41d449c1b19acc4d3864db6552 Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Wed, 4 Dec 2024 10:36:03 +0000 Subject: [PATCH 05/12] Introduce generalized abstract DataService --- .../odk/collect/androidshared/data/Data.kt | 33 +++++++++++++++++++ .../android/projects/ProjectsDataService.kt | 12 +++---- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt b/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt index d17c1b3b4b1..4a1fa743bb2 100644 --- a/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt +++ b/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt @@ -1,6 +1,7 @@ package org.odk.collect.androidshared.data import kotlinx.coroutines.flow.StateFlow +import kotlin.reflect.KProperty class Data(private val appState: AppState, private val key: String, private val default: T) { fun get(qualifier: String? = null): StateFlow { @@ -16,6 +17,38 @@ class Data(private val appState: AppState, private val key: String, private v } } +class DataUpdater(private val data: Data, private val updater: (String?) -> T) { + fun update(qualifier: String? = null) { + data.set(qualifier, updater(qualifier)) + } +} + fun AppState.getData(key: String, default: T): Data { return Data(this, key, default) } + +abstract class DataService(private val appState: AppState) { + + private val dataUpdaters = mutableListOf>() + + fun update(qualifier: String? = null) { + dataUpdaters.forEach { it.update(qualifier) } + } + + protected fun data(key: String, default: T, updater: (String?) -> T): DataDelegate { + val data = createData(key, default, updater) + return DataDelegate(data) + } + + private fun createData(key: String, default: T, updater: (String?) -> T): Data { + val data = Data(appState, key, default) + dataUpdaters.add(DataUpdater(data, updater)) + return data + } + + class DataDelegate(private val data: Data) { + operator fun getValue(thisRef: Any?, property: KProperty<*>): Data { + return data + } + } +} diff --git a/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt b/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt index ccbbaedd76b..36380ceaced 100644 --- a/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt +++ b/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt @@ -5,7 +5,7 @@ import org.odk.collect.android.application.initialization.AnalyticsInitializer import org.odk.collect.android.application.initialization.MapsInitializer import org.odk.collect.android.state.DataKeys import org.odk.collect.androidshared.data.AppState -import org.odk.collect.androidshared.data.getData +import org.odk.collect.androidshared.data.DataService import org.odk.collect.projects.Project import org.odk.collect.projects.ProjectsRepository import org.odk.collect.settings.SettingsProvider @@ -17,16 +17,14 @@ class ProjectsDataService( private val projectsRepository: ProjectsRepository, private val analyticsInitializer: AnalyticsInitializer, private val mapsInitializer: MapsInitializer -) { +) : DataService(appState) { - private val currentProject = appState.getData(DataKeys.PROJECT, null) - - fun update() { + private val currentProject by data(DataKeys.PROJECT, null) { val currentProjectId = getCurrentProjectId() if (currentProjectId != null) { - currentProject.set(projectsRepository.get(currentProjectId)) + projectsRepository.get(currentProjectId) } else { - currentProject.set(null) + null } } From d5506967c0939e3a20e7511868c728e3ace1b674 Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Wed, 4 Dec 2024 11:08:23 +0000 Subject: [PATCH 06/12] Convert InstancesDataService to DataService --- .../odk/collect/androidshared/data/Data.kt | 3 +- .../InstancesDataService.kt | 61 ++++++++++--------- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt b/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt index 4a1fa743bb2..0001692c03f 100644 --- a/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt +++ b/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt @@ -27,12 +27,13 @@ fun AppState.getData(key: String, default: T): Data { return Data(this, key, default) } -abstract class DataService(private val appState: AppState) { +abstract class DataService(private val appState: AppState, private val onUpdate: (() -> Unit)? = null) { private val dataUpdaters = mutableListOf>() fun update(qualifier: String? = null) { dataUpdaters.forEach { it.update(qualifier) } + onUpdate?.invoke() } protected fun data(key: String, default: T, updater: (String?) -> T): DataDelegate { diff --git a/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt b/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt index 632c8f5971e..9349534fd44 100644 --- a/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt +++ b/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt @@ -17,7 +17,7 @@ import org.odk.collect.android.state.DataKeys import org.odk.collect.android.utilities.ExternalizableFormDefCache import org.odk.collect.android.utilities.FormsUploadResultInterpreter import org.odk.collect.androidshared.data.AppState -import org.odk.collect.androidshared.data.getData +import org.odk.collect.androidshared.data.DataService import org.odk.collect.forms.Form import org.odk.collect.forms.instances.Instance import org.odk.collect.metadata.PropertyManager @@ -31,46 +31,49 @@ class InstancesDataService( private val notifier: Notifier, private val propertyManager: PropertyManager, private val httpInterface: OpenRosaHttpInterface, - private val onUpdate: () -> Unit -) { + onUpdate: () -> Unit +) : DataService(appState, onUpdate) { - private val editableCount = appState.getData(DataKeys.INSTANCES_EDITABLE_COUNT, 0) - private val sendableCount = appState.getData(DataKeys.INSTANCES_SENDABLE_COUNT, 0) - private val sentCount = appState.getData(DataKeys.INSTANCES_SENT_COUNT, 0) - private val instances = appState.getData>(DataKeys.INSTANCES, emptyList()) - - fun getEditableCount(projectId: String): StateFlow = editableCount.get(projectId) - fun getSendableCount(projectId: String): StateFlow = sendableCount.get(projectId) - fun getSentCount(projectId: String): StateFlow = sentCount.get(projectId) - - fun getInstances(projectId: String): StateFlow> { - return instances.get(projectId) + private val editableCount by data(DataKeys.INSTANCES_EDITABLE_COUNT, 0) { projectId -> + val projectDependencyModule = projectDependencyModuleFactory.create(projectId!!) + val instancesRepository = projectDependencyModule.instancesRepository + instancesRepository.getCountByStatus( + Instance.STATUS_INCOMPLETE, + Instance.STATUS_INVALID, + Instance.STATUS_VALID + ) } - fun update(projectId: String) { - val projectDependencyModule = projectDependencyModuleFactory.create(projectId) + private val sendableCount by data(DataKeys.INSTANCES_SENDABLE_COUNT, 0) { projectId -> + val projectDependencyModule = projectDependencyModuleFactory.create(projectId!!) val instancesRepository = projectDependencyModule.instancesRepository - - val sendableInstances = instancesRepository.getCountByStatus( + instancesRepository.getCountByStatus( Instance.STATUS_COMPLETE, Instance.STATUS_SUBMISSION_FAILED ) - val sentInstances = instancesRepository.getCountByStatus( + } + + private val sentCount by data(DataKeys.INSTANCES_SENT_COUNT, 0) { projectId -> + val projectDependencyModule = projectDependencyModuleFactory.create(projectId!!) + val instancesRepository = projectDependencyModule.instancesRepository + instancesRepository.getCountByStatus( Instance.STATUS_SUBMITTED, Instance.STATUS_SUBMISSION_FAILED ) - val editableInstances = instancesRepository.getCountByStatus( - Instance.STATUS_INCOMPLETE, - Instance.STATUS_INVALID, - Instance.STATUS_VALID - ) + } - editableCount.set(projectId, editableInstances) - sendableCount.set(projectId, sendableInstances) - sentCount.set(projectId, sentInstances) - instances.set(projectId, instancesRepository.all) + private val instances by data(DataKeys.INSTANCES, emptyList()) { projectId -> + val projectDependencyModule = projectDependencyModuleFactory.create(projectId!!) + val instancesRepository = projectDependencyModule.instancesRepository + instancesRepository.all + } - onUpdate() + fun getEditableCount(projectId: String): StateFlow = editableCount.get(projectId) + fun getSendableCount(projectId: String): StateFlow = sendableCount.get(projectId) + fun getSentCount(projectId: String): StateFlow = sentCount.get(projectId) + + fun getInstances(projectId: String): StateFlow> { + return instances.get(projectId) } fun finalizeAllDrafts(projectId: String): FinalizeAllResult { From a9da804803e1baf661e21f135e7df557bda5f876 Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Wed, 4 Dec 2024 14:51:30 +0000 Subject: [PATCH 07/12] Make it easier to create DataService with qualified data --- .../org/odk/collect/androidshared/data/Data.kt | 9 +++++++-- .../instancemanagement/InstancesDataService.kt | 16 ++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt b/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt index 0001692c03f..37fead2efeb 100644 --- a/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt +++ b/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt @@ -36,8 +36,13 @@ abstract class DataService(private val appState: AppState, private val onUpdate: onUpdate?.invoke() } - protected fun data(key: String, default: T, updater: (String?) -> T): DataDelegate { - val data = createData(key, default, updater) + protected fun data(key: String, default: T, updater: () -> T): DataDelegate { + val data = createData(key, default) { updater() } + return DataDelegate(data) + } + + protected fun qualifiedData(key: String, default: T, updater: (String) -> T): DataDelegate { + val data = createData(key, default) { updater(it!!) } return DataDelegate(data) } diff --git a/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt b/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt index 9349534fd44..ffab185a4a5 100644 --- a/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt +++ b/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt @@ -34,8 +34,8 @@ class InstancesDataService( onUpdate: () -> Unit ) : DataService(appState, onUpdate) { - private val editableCount by data(DataKeys.INSTANCES_EDITABLE_COUNT, 0) { projectId -> - val projectDependencyModule = projectDependencyModuleFactory.create(projectId!!) + private val editableCount by qualifiedData(DataKeys.INSTANCES_EDITABLE_COUNT, 0) { projectId -> + val projectDependencyModule = projectDependencyModuleFactory.create(projectId) val instancesRepository = projectDependencyModule.instancesRepository instancesRepository.getCountByStatus( Instance.STATUS_INCOMPLETE, @@ -44,8 +44,8 @@ class InstancesDataService( ) } - private val sendableCount by data(DataKeys.INSTANCES_SENDABLE_COUNT, 0) { projectId -> - val projectDependencyModule = projectDependencyModuleFactory.create(projectId!!) + private val sendableCount by qualifiedData(DataKeys.INSTANCES_SENDABLE_COUNT, 0) { projectId -> + val projectDependencyModule = projectDependencyModuleFactory.create(projectId) val instancesRepository = projectDependencyModule.instancesRepository instancesRepository.getCountByStatus( Instance.STATUS_COMPLETE, @@ -53,8 +53,8 @@ class InstancesDataService( ) } - private val sentCount by data(DataKeys.INSTANCES_SENT_COUNT, 0) { projectId -> - val projectDependencyModule = projectDependencyModuleFactory.create(projectId!!) + private val sentCount by qualifiedData(DataKeys.INSTANCES_SENT_COUNT, 0) { projectId -> + val projectDependencyModule = projectDependencyModuleFactory.create(projectId) val instancesRepository = projectDependencyModule.instancesRepository instancesRepository.getCountByStatus( Instance.STATUS_SUBMITTED, @@ -62,8 +62,8 @@ class InstancesDataService( ) } - private val instances by data(DataKeys.INSTANCES, emptyList()) { projectId -> - val projectDependencyModule = projectDependencyModuleFactory.create(projectId!!) + private val instances by qualifiedData(DataKeys.INSTANCES, emptyList()) { projectId -> + val projectDependencyModule = projectDependencyModuleFactory.create(projectId) val instancesRepository = projectDependencyModule.instancesRepository instancesRepository.all } From 9240cfe0e56e2e84adbf55a4977273703352c18f Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Wed, 4 Dec 2024 15:33:36 +0000 Subject: [PATCH 08/12] Make FormsDataService implement DataService --- .../odk/collect/androidshared/data/Data.kt | 15 +++--- .../blankformlist/BlankFormListViewModel.kt | 6 ++- .../formmanagement/FormsDataService.kt | 50 +++++++++---------- .../android/tasks/DownloadFormListTask.java | 2 +- .../formmanagement/FormsDataServiceTest.kt | 4 +- 5 files changed, 40 insertions(+), 37 deletions(-) diff --git a/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt b/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt index 37fead2efeb..44a6020cd96 100644 --- a/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt +++ b/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt @@ -23,10 +23,6 @@ class DataUpdater(private val data: Data, private val updater: (String?) - } } -fun AppState.getData(key: String, default: T): Data { - return Data(this, key, default) -} - abstract class DataService(private val appState: AppState, private val onUpdate: (() -> Unit)? = null) { private val dataUpdaters = mutableListOf>() @@ -37,16 +33,21 @@ abstract class DataService(private val appState: AppState, private val onUpdate: } protected fun data(key: String, default: T, updater: () -> T): DataDelegate { - val data = createData(key, default) { updater() } + val data = attachData(key, default) { updater() } return DataDelegate(data) } protected fun qualifiedData(key: String, default: T, updater: (String) -> T): DataDelegate { - val data = createData(key, default) { updater(it!!) } + val data = attachData(key, default) { updater(it!!) } + return DataDelegate(data) + } + + protected fun qualifiedData(key: String, default: T): DataDelegate { + val data = Data(appState, key, default) return DataDelegate(data) } - private fun createData(key: String, default: T, updater: (String?) -> T): Data { + private fun attachData(key: String, default: T, updater: (String?) -> T): Data { val data = Data(appState, key, default) dataUpdaters.add(DataUpdater(data, updater)) return data diff --git a/collect_app/src/main/java/org/odk/collect/android/formlists/blankformlist/BlankFormListViewModel.kt b/collect_app/src/main/java/org/odk/collect/android/formlists/blankformlist/BlankFormListViewModel.kt index 8fdebcd7dcf..f800512376f 100644 --- a/collect_app/src/main/java/org/odk/collect/android/formlists/blankformlist/BlankFormListViewModel.kt +++ b/collect_app/src/main/java/org/odk/collect/android/formlists/blankformlist/BlankFormListViewModel.kt @@ -67,7 +67,7 @@ class BlankFormListViewModel( init { scheduler.immediate( background = { - formsDataService.update(projectId) + formsDataService.refresh(projectId) }, foreground = {} ) @@ -76,7 +76,9 @@ class BlankFormListViewModel( fun syncWithServer(): LiveData { val result = MutableLiveData() scheduler.immediate( - { formsDataService.matchFormsWithServer(projectId) }, + { + formsDataService.matchFormsWithServer(projectId) + }, { value: Boolean -> result.value = value } diff --git a/collect_app/src/main/java/org/odk/collect/android/formmanagement/FormsDataService.kt b/collect_app/src/main/java/org/odk/collect/android/formmanagement/FormsDataService.kt index 9675495c188..17bb76240da 100644 --- a/collect_app/src/main/java/org/odk/collect/android/formmanagement/FormsDataService.kt +++ b/collect_app/src/main/java/org/odk/collect/android/formmanagement/FormsDataService.kt @@ -11,7 +11,7 @@ import org.odk.collect.android.notifications.Notifier import org.odk.collect.android.projects.ProjectDependencyModule import org.odk.collect.android.state.DataKeys import org.odk.collect.androidshared.data.AppState -import org.odk.collect.androidshared.data.getData +import org.odk.collect.androidshared.data.DataService import org.odk.collect.forms.Form import org.odk.collect.forms.FormSourceException import org.odk.collect.projects.ProjectDependencyFactory @@ -25,12 +25,16 @@ class FormsDataService( private val notifier: Notifier, private val projectDependencyModuleFactory: ProjectDependencyFactory, private val clock: Supplier -) { +) : DataService(appState) { - private val forms = appState.getData(DataKeys.FORMS, emptyList
()) - private val syncing = appState.getData(DataKeys.SYNC_STATUS_SYNCING, false) - private val serverError = appState.getData(DataKeys.SYNC_STATUS_ERROR, null) - private val diskError = appState.getData(DataKeys.DISK_ERROR, null) + private val forms by qualifiedData(DataKeys.FORMS, emptyList()) { projectId -> + val projectDependencies = projectDependencyModuleFactory.create(projectId) + projectDependencies.formsRepository.all + } + + private val syncing by qualifiedData(DataKeys.SYNC_STATUS_SYNCING, false) + private val serverError by qualifiedData(DataKeys.SYNC_STATUS_ERROR, null) + private val diskError by qualifiedData(DataKeys.DISK_ERROR, null) fun getForms(projectId: String): Flow> { return forms.get(projectId) @@ -52,6 +56,18 @@ class FormsDataService( serverError.set(projectId, null) } + fun refresh(projectId: String) { + val projectDependencies = projectDependencyModuleFactory.create(projectId) + projectDependencies.formsLock.withLock { acquiredLock -> + if (acquiredLock) { + startSync(projectId) + syncWithStorage(projectId) + update(projectId) + finishSyncWithStorage(projectId) + } + } + } + fun downloadForms( projectId: String, forms: List, @@ -109,7 +125,7 @@ class FormsDataService( } } - syncWithDb(projectId) + update(projectId) } catch (_: FormSourceException) { // Ignored } @@ -154,7 +170,7 @@ class FormsDataService( e } - syncWithDb(projectId) + update(projectId) finishSyncWithServer(projectId, exception) exception == null } else { @@ -170,19 +186,8 @@ class FormsDataService( projectDependencies.instancesRepository, formId ) - syncWithDb(projectId) - } - fun update(projectId: String) { - val projectDependencies = projectDependencyModuleFactory.create(projectId) - projectDependencies.formsLock.withLock { acquiredLock -> - if (acquiredLock) { - startSync(projectId) - syncWithStorage(projectId) - syncWithDb(projectId) - finishSyncWithStorage(projectId) - } - } + update(projectId) } private fun syncWithStorage(projectId: String) { @@ -207,11 +212,6 @@ class FormsDataService( private fun finishSyncWithStorage(projectId: String) { syncing.set(projectId, false) } - - private fun syncWithDb(projectId: String) { - val projectDependencies = projectDependencyModuleFactory.create(projectId) - forms.set(projectId, projectDependencies.formsRepository.all) - } } private fun formDownloader( diff --git a/collect_app/src/main/java/org/odk/collect/android/tasks/DownloadFormListTask.java b/collect_app/src/main/java/org/odk/collect/android/tasks/DownloadFormListTask.java index 2e29a21b2fc..80549160f10 100644 --- a/collect_app/src/main/java/org/odk/collect/android/tasks/DownloadFormListTask.java +++ b/collect_app/src/main/java/org/odk/collect/android/tasks/DownloadFormListTask.java @@ -68,7 +68,7 @@ public DownloadFormListTask(ServerFormsDetailsFetcher serverFormsDetailsFetcher) @Override protected Pair, FormSourceException> doInBackground(Void... values) { - formsDataService.update(projectsDataService.getCurrentProject().getUuid()); + formsDataService.refresh(projectsDataService.getCurrentProject().getUuid()); if (webCredentialsUtils != null) { setTemporaryCredentials(); diff --git a/collect_app/src/test/java/org/odk/collect/android/formmanagement/FormsDataServiceTest.kt b/collect_app/src/test/java/org/odk/collect/android/formmanagement/FormsDataServiceTest.kt index 6641425a37c..0eb845255ff 100644 --- a/collect_app/src/test/java/org/odk/collect/android/formmanagement/FormsDataServiceTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/formmanagement/FormsDataServiceTest.kt @@ -193,7 +193,7 @@ class FormsDataServiceTest { formsDataService.matchFormsWithServer(project.uuid) assertThat(formsDataService.getServerError(project.uuid).getOrAwaitValue(), equalTo(error)) - formsDataService.update(project.uuid) + formsDataService.refresh(project.uuid) assertThat(formsDataService.getServerError(project.uuid).getOrAwaitValue(), equalTo(error)) } @@ -239,7 +239,7 @@ class FormsDataServiceTest { changeLock.lock() isSyncing.recordValues { projectValues -> - formsDataService.update(project.uuid) + formsDataService.refresh(project.uuid) assertThat(projectValues, equalTo(listOf(false))) } } From 1f5b8d3a061a30541873bc02cecebed2b11a8168 Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Wed, 4 Dec 2024 16:04:07 +0000 Subject: [PATCH 09/12] Clean up delegate helper signatures --- .../java/org/odk/collect/androidshared/data/Data.kt | 10 +++++----- .../collect/android/formmanagement/FormsDataService.kt | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt b/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt index 44a6020cd96..bb966ace614 100644 --- a/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt +++ b/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt @@ -32,6 +32,11 @@ abstract class DataService(private val appState: AppState, private val onUpdate: onUpdate?.invoke() } + protected fun data(key: String, default: T): DataDelegate { + val data = Data(appState, key, default) + return DataDelegate(data) + } + protected fun data(key: String, default: T, updater: () -> T): DataDelegate { val data = attachData(key, default) { updater() } return DataDelegate(data) @@ -42,11 +47,6 @@ abstract class DataService(private val appState: AppState, private val onUpdate: return DataDelegate(data) } - protected fun qualifiedData(key: String, default: T): DataDelegate { - val data = Data(appState, key, default) - return DataDelegate(data) - } - private fun attachData(key: String, default: T, updater: (String?) -> T): Data { val data = Data(appState, key, default) dataUpdaters.add(DataUpdater(data, updater)) diff --git a/collect_app/src/main/java/org/odk/collect/android/formmanagement/FormsDataService.kt b/collect_app/src/main/java/org/odk/collect/android/formmanagement/FormsDataService.kt index 17bb76240da..19e23b2eb03 100644 --- a/collect_app/src/main/java/org/odk/collect/android/formmanagement/FormsDataService.kt +++ b/collect_app/src/main/java/org/odk/collect/android/formmanagement/FormsDataService.kt @@ -32,9 +32,9 @@ class FormsDataService( projectDependencies.formsRepository.all } - private val syncing by qualifiedData(DataKeys.SYNC_STATUS_SYNCING, false) - private val serverError by qualifiedData(DataKeys.SYNC_STATUS_ERROR, null) - private val diskError by qualifiedData(DataKeys.DISK_ERROR, null) + private val syncing by data(DataKeys.SYNC_STATUS_SYNCING, false) + private val serverError by data(DataKeys.SYNC_STATUS_ERROR, null) + private val diskError by data(DataKeys.DISK_ERROR, null) fun getForms(projectId: String): Flow> { return forms.get(projectId) From fb757cbdbaecc390758c325a9bde7135903b44a4 Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Wed, 4 Dec 2024 16:24:30 +0000 Subject: [PATCH 10/12] Rename method --- .../main/java/org/odk/collect/androidshared/data/Data.kt | 2 +- .../collect/android/formmanagement/FormsDataService.kt | 8 ++++---- .../android/instancemanagement/InstancesDataService.kt | 8 ++++---- .../odk/collect/android/projects/ProjectsDataService.kt | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt b/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt index bb966ace614..465dff344c9 100644 --- a/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt +++ b/androidshared/src/main/java/org/odk/collect/androidshared/data/Data.kt @@ -4,7 +4,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlin.reflect.KProperty class Data(private val appState: AppState, private val key: String, private val default: T) { - fun get(qualifier: String? = null): StateFlow { + fun flow(qualifier: String? = null): StateFlow { return appState.getFlow("$qualifier:$key", default) } diff --git a/collect_app/src/main/java/org/odk/collect/android/formmanagement/FormsDataService.kt b/collect_app/src/main/java/org/odk/collect/android/formmanagement/FormsDataService.kt index 19e23b2eb03..8114da10abe 100644 --- a/collect_app/src/main/java/org/odk/collect/android/formmanagement/FormsDataService.kt +++ b/collect_app/src/main/java/org/odk/collect/android/formmanagement/FormsDataService.kt @@ -37,19 +37,19 @@ class FormsDataService( private val diskError by data(DataKeys.DISK_ERROR, null) fun getForms(projectId: String): Flow> { - return forms.get(projectId) + return forms.flow(projectId) } fun isSyncing(projectId: String): LiveData { - return syncing.get(projectId).asLiveData() + return syncing.flow(projectId).asLiveData() } fun getServerError(projectId: String): LiveData { - return serverError.get(projectId).asLiveData() + return serverError.flow(projectId).asLiveData() } fun getDiskError(projectId: String): LiveData { - return diskError.get(projectId).asLiveData() + return diskError.flow(projectId).asLiveData() } fun clear(projectId: String) { diff --git a/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt b/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt index ffab185a4a5..b8b18d94d17 100644 --- a/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt +++ b/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstancesDataService.kt @@ -68,12 +68,12 @@ class InstancesDataService( instancesRepository.all } - fun getEditableCount(projectId: String): StateFlow = editableCount.get(projectId) - fun getSendableCount(projectId: String): StateFlow = sendableCount.get(projectId) - fun getSentCount(projectId: String): StateFlow = sentCount.get(projectId) + fun getEditableCount(projectId: String): StateFlow = editableCount.flow(projectId) + fun getSendableCount(projectId: String): StateFlow = sendableCount.flow(projectId) + fun getSentCount(projectId: String): StateFlow = sentCount.flow(projectId) fun getInstances(projectId: String): StateFlow> { - return instances.get(projectId) + return instances.flow(projectId) } fun finalizeAllDrafts(projectId: String): FinalizeAllResult { diff --git a/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt b/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt index 36380ceaced..eeaed7af174 100644 --- a/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt +++ b/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt @@ -29,7 +29,7 @@ class ProjectsDataService( } fun getCurrentProjectFlow(): StateFlow { - return currentProject.get() + return currentProject.flow() } fun getCurrentProject(): Project.Saved { From 69a1997e9a8d4651744409b7c7dbd3af5d21e98f Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Thu, 5 Dec 2024 12:21:45 +0000 Subject: [PATCH 11/12] Deprecate non nullable project getter --- .../rules/FormEntryActivityTestRule.kt | 4 +- .../android/activities/DeleteFormsActivity.kt | 2 +- .../activities/FormDownloadListActivity.java | 2 +- .../activities/FormEntryViewModelFactory.kt | 2 +- .../activities/FormFillingActivity.java | 2 +- .../android/activities/FormMapActivity.kt | 4 +- .../activities/InstanceChooserList.java | 4 +- .../collect/android/application/Collect.java | 2 +- .../initialization/JavaRosaInitializer.kt | 2 +- .../configure/qr/AppConfigurationGenerator.kt | 2 +- .../configure/qr/QRCodeScannerFragment.kt | 6 +- .../configure/qr/QRCodeTabsActivity.kt | 2 +- .../android/dao/CursorLoaderFactory.java | 2 +- .../android/external/FormUriActivity.kt | 6 +- .../formentry/saving/FormSaveViewModel.java | 4 +- .../injection/config/AppDependencyModule.java | 10 +-- .../InstanceDiskSynchronizer.java | 2 +- .../send/InstanceUploaderListActivity.java | 4 +- .../mainmenu/CurrentProjectViewModel.kt | 9 +-- .../android/mainmenu/MainMenuViewModel.kt | 4 +- .../screens/BaseAdminPreferencesFragment.java | 2 +- .../BaseProjectPreferencesFragment.java | 2 +- .../FormManagementPreferencesFragment.java | 2 +- .../ProjectDisplayPreferencesFragment.kt | 16 ++-- .../projects/ManualProjectCreatorDialog.kt | 4 +- .../android/projects/ProjectDeleter.kt | 4 +- .../android/projects/ProjectsDataService.kt | 38 +++++----- .../projects/QrCodeProjectCreatorDialog.kt | 4 +- .../android/storage/StoragePathProvider.kt | 2 +- .../android/tasks/DownloadFormListTask.java | 2 +- .../android/tasks/InstanceUploaderTask.java | 2 +- .../utilities/FormsRepositoryProvider.kt | 2 +- .../utilities/InstancesRepositoryProvider.kt | 2 +- .../utilities/SavepointsRepositoryProvider.kt | 2 +- .../android/external/FormUriActivityTest.kt | 74 +++++++++---------- .../audit/FormSaveViewModelTest.java | 2 +- .../mainmenu/CurrentProjectViewModelTest.kt | 4 +- .../android/mainmenu/MainMenuViewModelTest.kt | 4 +- .../AppConfigurationGeneratorTest.kt | 2 +- .../screens/MapsPreferencesFragmentTest.kt | 2 +- .../ProjectDisplayPreferencesFragmentTest.kt | 2 +- .../projects/ExistingProjectMigratorTest.kt | 8 +- .../ManualProjectCreatorDialogTest.kt | 2 +- .../android/projects/ProjectCreatorTest.kt | 2 +- .../android/projects/ProjectDeleterTest.kt | 4 +- .../projects/ProjectsDataServiceTest.kt | 16 ++-- .../storage/StoragePathProviderTest.kt | 2 +- 47 files changed, 139 insertions(+), 144 deletions(-) diff --git a/collect_app/src/androidTest/java/org/odk/collect/android/support/rules/FormEntryActivityTestRule.kt b/collect_app/src/androidTest/java/org/odk/collect/android/support/rules/FormEntryActivityTestRule.kt index 19ab89287d7..c8bf44ca0ac 100644 --- a/collect_app/src/androidTest/java/org/odk/collect/android/support/rules/FormEntryActivityTestRule.kt +++ b/collect_app/src/androidTest/java/org/odk/collect/android/support/rules/FormEntryActivityTestRule.kt @@ -89,7 +89,7 @@ open class FormEntryActivityTestRule : val form = DaggerUtils.getComponent(application).formsRepositoryProvider().create() .getOneByPath(formPath) val projectId = DaggerUtils.getComponent(application).currentProjectProvider() - .getCurrentProject().uuid + .requireCurrentProject().uuid return FormFillingIntentFactory.newInstanceIntent( application, @@ -106,7 +106,7 @@ open class FormEntryActivityTestRule : val instance = DaggerUtils.getComponent(application).instancesRepositoryProvider().create() .getAllByFormId(form!!.formId).first() val projectId = DaggerUtils.getComponent(application).currentProjectProvider() - .getCurrentProject().uuid + .requireCurrentProject().uuid return FormFillingIntentFactory.editInstanceIntent( application, diff --git a/collect_app/src/main/java/org/odk/collect/android/activities/DeleteFormsActivity.kt b/collect_app/src/main/java/org/odk/collect/android/activities/DeleteFormsActivity.kt index 34824f22035..2c8444cbd4b 100644 --- a/collect_app/src/main/java/org/odk/collect/android/activities/DeleteFormsActivity.kt +++ b/collect_app/src/main/java/org/odk/collect/android/activities/DeleteFormsActivity.kt @@ -60,7 +60,7 @@ class DeleteFormsActivity : LocalizedActivity() { override fun onCreate(savedInstanceState: Bundle?) { DaggerUtils.getComponent(this).inject(this) - val projectId = projectsDataService.getCurrentProject().uuid + val projectId = projectsDataService.requireCurrentProject().uuid val projectDependencyModule = projectDependencyModuleFactory.create(projectId) val viewModelFactory = ViewModelFactory( diff --git a/collect_app/src/main/java/org/odk/collect/android/activities/FormDownloadListActivity.java b/collect_app/src/main/java/org/odk/collect/android/activities/FormDownloadListActivity.java index d5faebd28f5..655f4e069ec 100644 --- a/collect_app/src/main/java/org/odk/collect/android/activities/FormDownloadListActivity.java +++ b/collect_app/src/main/java/org/odk/collect/android/activities/FormDownloadListActivity.java @@ -395,7 +395,7 @@ private void startFormsDownload(@NonNull ArrayList filesToDow // show dialog box DialogFragmentUtils.showIfNotShowing(RefreshFormListDialogFragment.class, getSupportFragmentManager()); - downloadFormsTask = new DownloadFormsTask(projectsDataService.getCurrentProject().getUuid(), formsDataService); + downloadFormsTask = new DownloadFormsTask(projectsDataService.requireCurrentProject().getUuid(), formsDataService); downloadFormsTask.setDownloaderListener(this); if (viewModel.getUrl() != null) { diff --git a/collect_app/src/main/java/org/odk/collect/android/activities/FormEntryViewModelFactory.kt b/collect_app/src/main/java/org/odk/collect/android/activities/FormEntryViewModelFactory.kt index 484d0ab7ae2..88f02ebd42e 100644 --- a/collect_app/src/main/java/org/odk/collect/android/activities/FormEntryViewModelFactory.kt +++ b/collect_app/src/main/java/org/odk/collect/android/activities/FormEntryViewModelFactory.kt @@ -67,7 +67,7 @@ class FormEntryViewModelFactory( modelClass: Class, handle: SavedStateHandle ): T { - val projectId = projectsDataService.getCurrentProject().uuid + val projectId = projectsDataService.requireCurrentProject().uuid return when (modelClass) { FormEntryViewModel::class.java -> FormEntryViewModel( diff --git a/collect_app/src/main/java/org/odk/collect/android/activities/FormFillingActivity.java b/collect_app/src/main/java/org/odk/collect/android/activities/FormFillingActivity.java index fbd1d390763..7882ffdfb5c 100644 --- a/collect_app/src/main/java/org/odk/collect/android/activities/FormFillingActivity.java +++ b/collect_app/src/main/java/org/odk/collect/android/activities/FormFillingActivity.java @@ -2102,7 +2102,7 @@ private void finishAndReturnInstance() { String path = getAbsoluteInstancePath(); if (path != null) { if (formSaveViewModel.getInstance() != null) { - uri = InstancesContract.getUri(projectsDataService.getCurrentProject().getUuid(), formSaveViewModel.getInstance().getDbId()); + uri = InstancesContract.getUri(projectsDataService.requireCurrentProject().getUuid(), formSaveViewModel.getInstance().getDbId()); } } diff --git a/collect_app/src/main/java/org/odk/collect/android/activities/FormMapActivity.kt b/collect_app/src/main/java/org/odk/collect/android/activities/FormMapActivity.kt index 7a69362cdad..434a22e613f 100644 --- a/collect_app/src/main/java/org/odk/collect/android/activities/FormMapActivity.kt +++ b/collect_app/src/main/java/org/odk/collect/android/activities/FormMapActivity.kt @@ -88,9 +88,9 @@ class FormMapActivity : LocalizedActivity() { ) { _: String?, result: Bundle -> if (result.containsKey(SelectionMapFragment.RESULT_SELECTED_ITEM)) { val instanceId = result.getLong(SelectionMapFragment.RESULT_SELECTED_ITEM) - startActivity(FormFillingIntentFactory.editInstanceIntent(this, projectsDataService.getCurrentProject().uuid, instanceId)) + startActivity(FormFillingIntentFactory.editInstanceIntent(this, projectsDataService.requireCurrentProject().uuid, instanceId)) } else if (result.containsKey(SelectionMapFragment.RESULT_CREATE_NEW_ITEM)) { - startActivity(FormFillingIntentFactory.newInstanceIntent(this, FormsContract.getUri(projectsDataService.getCurrentProject().uuid, formId))) + startActivity(FormFillingIntentFactory.newInstanceIntent(this, FormsContract.getUri(projectsDataService.requireCurrentProject().uuid, formId))) } } } diff --git a/collect_app/src/main/java/org/odk/collect/android/activities/InstanceChooserList.java b/collect_app/src/main/java/org/odk/collect/android/activities/InstanceChooserList.java index 5415d91590c..53d6603a454 100644 --- a/collect_app/src/main/java/org/odk/collect/android/activities/InstanceChooserList.java +++ b/collect_app/src/main/java/org/odk/collect/android/activities/InstanceChooserList.java @@ -157,7 +157,7 @@ public void onCreate(Bundle savedInstanceState) { init(); BulkFinalizationViewModel bulkFinalizationViewModel = new BulkFinalizationViewModel( - projectsDataService.getCurrentProject().getUuid(), + projectsDataService.requireCurrentProject().getUuid(), scheduler, instancesDataService, settingsProvider @@ -198,7 +198,7 @@ public void onItemClick(AdapterView parent, View view, int position, long id) if (view.isEnabled()) { Cursor c = (Cursor) listView.getAdapter().getItem(position); long instanceId = c.getLong(c.getColumnIndex(DatabaseInstanceColumns._ID)); - Uri instanceUri = InstancesContract.getUri(projectsDataService.getCurrentProject().getUuid(), instanceId); + Uri instanceUri = InstancesContract.getUri(projectsDataService.requireCurrentProject().getUuid(), instanceId); String action = getIntent().getAction(); if (Intent.ACTION_PICK.equals(action)) { diff --git a/collect_app/src/main/java/org/odk/collect/android/application/Collect.java b/collect_app/src/main/java/org/odk/collect/android/application/Collect.java index d064066a8d9..bde0571e098 100644 --- a/collect_app/src/main/java/org/odk/collect/android/application/Collect.java +++ b/collect_app/src/main/java/org/odk/collect/android/application/Collect.java @@ -299,7 +299,7 @@ public EntitiesDependencyComponent getEntitiesDependencyComponent() { @NonNull @Override public EntitiesRepository providesEntitiesRepository() { - String projectId = applicationComponent.currentProjectProvider().getCurrentProject().getUuid(); + String projectId = applicationComponent.currentProjectProvider().requireCurrentProject().getUuid(); return applicationComponent.entitiesRepositoryProvider().create(projectId); } diff --git a/collect_app/src/main/java/org/odk/collect/android/application/initialization/JavaRosaInitializer.kt b/collect_app/src/main/java/org/odk/collect/android/application/initialization/JavaRosaInitializer.kt index 146409785d4..d586c4a8633 100644 --- a/collect_app/src/main/java/org/odk/collect/android/application/initialization/JavaRosaInitializer.kt +++ b/collect_app/src/main/java/org/odk/collect/android/application/initialization/JavaRosaInitializer.kt @@ -53,7 +53,7 @@ class JavaRosaInitializer( XFormUtils.setXFormParserFactory(dynamicPreloadXFormParserFactory) val localEntitiesExternalInstanceParserFactory = LocalEntitiesExternalInstanceParserFactory( - { entitiesRepositoryProvider.create(projectsDataService.getCurrentProject().uuid) }, + { entitiesRepositoryProvider.create(projectsDataService.requireCurrentProject().uuid) }, { settingsProvider.getUnprotectedSettings().getBoolean(ProjectKeys.KEY_LOCAL_ENTITIES) } ) diff --git a/collect_app/src/main/java/org/odk/collect/android/configure/qr/AppConfigurationGenerator.kt b/collect_app/src/main/java/org/odk/collect/android/configure/qr/AppConfigurationGenerator.kt index 91121ab5ce7..6582b951519 100644 --- a/collect_app/src/main/java/org/odk/collect/android/configure/qr/AppConfigurationGenerator.kt +++ b/collect_app/src/main/java/org/odk/collect/android/configure/qr/AppConfigurationGenerator.kt @@ -81,7 +81,7 @@ class AppConfigurationGenerator( } private fun getProjectDetailsAsJson(): JSONObject { - val currentProject = projectsDataService.getCurrentProject() + val currentProject = projectsDataService.requireCurrentProject() return JSONObject().apply { put(AppConfigurationKeys.PROJECT_NAME, currentProject.name) diff --git a/collect_app/src/main/java/org/odk/collect/android/configure/qr/QRCodeScannerFragment.kt b/collect_app/src/main/java/org/odk/collect/android/configure/qr/QRCodeScannerFragment.kt index a5026a1575e..1bb9baf6557 100644 --- a/collect_app/src/main/java/org/odk/collect/android/configure/qr/QRCodeScannerFragment.kt +++ b/collect_app/src/main/java/org/odk/collect/android/configure/qr/QRCodeScannerFragment.kt @@ -38,18 +38,18 @@ class QRCodeScannerFragment : BarCodeScannerFragment() { @Throws(IOException::class, DataFormatException::class) override fun handleScanningResult(result: BarcodeResult) { - val oldProjectName = projectsDataService.getCurrentProject().name + val oldProjectName = projectsDataService.requireCurrentProject().name val settingsImportingResult = settingsImporter.fromJSON( CompressionUtils.decompress(result.text), - projectsDataService.getCurrentProject() + projectsDataService.requireCurrentProject() ) when (settingsImportingResult) { SettingsImportingResult.SUCCESS -> { Analytics.log(AnalyticsEvents.RECONFIGURE_PROJECT) - val newProjectName = projectsDataService.getCurrentProject().name + val newProjectName = projectsDataService.requireCurrentProject().name if (newProjectName != oldProjectName) { File(storagePathProvider.getProjectRootDirPath() + File.separator + oldProjectName).delete() File(storagePathProvider.getProjectRootDirPath() + File.separator + newProjectName).createNewFile() diff --git a/collect_app/src/main/java/org/odk/collect/android/configure/qr/QRCodeTabsActivity.kt b/collect_app/src/main/java/org/odk/collect/android/configure/qr/QRCodeTabsActivity.kt index dbcaf79c589..2278b98207d 100644 --- a/collect_app/src/main/java/org/odk/collect/android/configure/qr/QRCodeTabsActivity.kt +++ b/collect_app/src/main/java/org/odk/collect/android/configure/qr/QRCodeTabsActivity.kt @@ -64,7 +64,7 @@ class QRCodeTabsActivity : LocalizedActivity() { this, settingsImporter, qrCodeDecoder, - projectsDataService.getCurrentProject() + projectsDataService.requireCurrentProject() ) val menuProvider = QRCodeMenuProvider( diff --git a/collect_app/src/main/java/org/odk/collect/android/dao/CursorLoaderFactory.java b/collect_app/src/main/java/org/odk/collect/android/dao/CursorLoaderFactory.java index c19ada34d27..358c6d7d669 100644 --- a/collect_app/src/main/java/org/odk/collect/android/dao/CursorLoaderFactory.java +++ b/collect_app/src/main/java/org/odk/collect/android/dao/CursorLoaderFactory.java @@ -119,7 +119,7 @@ public CursorLoader createCompletedUndeletedInstancesCursorLoader(CharSequence c } private CursorLoader getInstancesCursorLoader(String selection, String[] selectionArgs, String sortOrder) { - Uri uri = InstancesContract.getUri(projectsDataService.getCurrentProject().getUuid()); + Uri uri = InstancesContract.getUri(projectsDataService.requireCurrentProject().getUuid()); return new CursorLoader( Collect.getInstance(), diff --git a/collect_app/src/main/java/org/odk/collect/android/external/FormUriActivity.kt b/collect_app/src/main/java/org/odk/collect/android/external/FormUriActivity.kt index 7e2bd0a6601..0dc92919fe1 100644 --- a/collect_app/src/main/java/org/odk/collect/android/external/FormUriActivity.kt +++ b/collect_app/src/main/java/org/odk/collect/android/external/FormUriActivity.kt @@ -123,7 +123,7 @@ class FormUriActivity : LocalizedActivity() { val uri = intent.data!! val uriMimeType = contentResolver.getType(uri)!! if (uriMimeType == FormsContract.CONTENT_ITEM_TYPE) { - startForm(FormsContract.getUri(projectsDataService.getCurrentProject().uuid, savepoint.formDbId)) + startForm(FormsContract.getUri(projectsDataService.requireCurrentProject().uuid, savepoint.formDbId)) } else { startForm(intent.data!!) } @@ -224,7 +224,7 @@ private class FormUriViewModel( val uriProjectId = uri?.getQueryParameter("projectId") val projectId = uriProjectId ?: firstProject.uuid - return if (projectId != projectsDataService.getCurrentProject().uuid) { + return if (projectId != projectsDataService.requireCurrentProject().uuid) { resources.getString(string.wrong_project_selected_for_form) } else { null @@ -321,7 +321,7 @@ private class FormUriViewModel( private fun assertDoesNotUseEntitiesOrFormsUpdateNotInProgress(): String? { val uriMimeType = contentResolver.getType(uri!!) - val projectId = projectsDataService.getCurrentProject().uuid + val projectId = projectsDataService.requireCurrentProject().uuid if (intent.extras?.getString(ApplicationConstants.BundleKeys.FORM_MODE) == ApplicationConstants.FormModes.VIEW_SENT) { return null diff --git a/collect_app/src/main/java/org/odk/collect/android/formentry/saving/FormSaveViewModel.java b/collect_app/src/main/java/org/odk/collect/android/formentry/saving/FormSaveViewModel.java index 7b698702c6f..e454cd48e88 100644 --- a/collect_app/src/main/java/org/odk/collect/android/formentry/saving/FormSaveViewModel.java +++ b/collect_app/src/main/java/org/odk/collect/android/formentry/saving/FormSaveViewModel.java @@ -249,7 +249,7 @@ public void onComplete(SaveToDiskResult saveToDiskResult) { handleTaskResult(saveToDiskResult, saveRequest); clearMediaFiles(); } - }, new ArrayList<>(originalFiles.values()), projectsDataService.getCurrentProject().getUuid(), entitiesRepository, instancesRepository).execute(); + }, new ArrayList<>(originalFiles.values()), projectsDataService.requireCurrentProject().getUuid(), entitiesRepository, instancesRepository).execute(); } private void handleTaskResult(SaveToDiskResult taskResult, SaveRequest saveRequest) { @@ -273,7 +273,7 @@ private void handleTaskResult(SaveToDiskResult taskResult, SaveRequest saveReque formController.getAuditEventLogger().logEvent(AuditEvent.AuditEventType.FORM_EXIT, false, clock.get()); formController.getAuditEventLogger().logEvent(AuditEvent.AuditEventType.FORM_FINALIZE, true, clock.get()); - instancesDataService.instanceFinalized(projectsDataService.getCurrentProject().getUuid(), form); + instancesDataService.instanceFinalized(projectsDataService.requireCurrentProject().getUuid(), form); } else { formController.getAuditEventLogger().logEvent(AuditEvent.AuditEventType.FORM_EXIT, true, clock.get()); } diff --git a/collect_app/src/main/java/org/odk/collect/android/injection/config/AppDependencyModule.java b/collect_app/src/main/java/org/odk/collect/android/injection/config/AppDependencyModule.java index dc4ae97ab5a..e2dfbf89696 100644 --- a/collect_app/src/main/java/org/odk/collect/android/injection/config/AppDependencyModule.java +++ b/collect_app/src/main/java/org/odk/collect/android/injection/config/AppDependencyModule.java @@ -335,7 +335,7 @@ public QRCodeDecoder providesQRCodeDecoder() { @Provides public ServerFormsDetailsFetcher providesServerFormDetailsFetcher(FormsRepositoryProvider formsRepositoryProvider, FormSourceProvider formSourceProvider, ProjectsDataService projectsDataService) { - Project.Saved currentProject = projectsDataService.getCurrentProject(); + Project.Saved currentProject = projectsDataService.requireCurrentProject(); FormsRepository formsRepository = formsRepositoryProvider.create(currentProject.getUuid()); return new ServerFormsDetailsFetcher(formsRepository, formSourceProvider.create(currentProject.getUuid())); } @@ -425,7 +425,7 @@ public UUIDGenerator providesUUIDGenerator() { public InstancesDataService providesInstancesDataService(Application application, ProjectsDataService projectsDataService, InstanceSubmitScheduler instanceSubmitScheduler, ProjectDependencyModuleFactory projectsDependencyProviderFactory, Notifier notifier, PropertyManager propertyManager, OpenRosaHttpInterface httpInterface) { Function0 onUpdate = () -> { application.getContentResolver().notifyChange( - InstancesContract.getUri(projectsDataService.getCurrentProject().getUuid()), + InstancesContract.getUri(projectsDataService.requireCurrentProject().getUuid()), null ); @@ -551,7 +551,7 @@ public ProjectDeleter providesProjectDeleter(ProjectsRepository projectsReposito @Provides public ProjectResetter providesProjectResetter(StoragePathProvider storagePathProvider, PropertyManager propertyManager, SettingsProvider settingsProvider, FormsRepositoryProvider formsRepositoryProvider, SavepointsRepositoryProvider savepointsRepositoryProvider, InstancesDataService instancesDataService, ProjectsDataService projectsDataService) { - return new ProjectResetter(storagePathProvider, propertyManager, settingsProvider, formsRepositoryProvider, savepointsRepositoryProvider, instancesDataService, projectsDataService.getCurrentProject().getUuid()); + return new ProjectResetter(storagePathProvider, propertyManager, settingsProvider, formsRepositoryProvider, savepointsRepositoryProvider, instancesDataService, projectsDataService.requireCurrentProject().getUuid()); } @Provides @@ -603,7 +603,7 @@ public ImageLoader providesImageLoader() { @Provides public BlankFormListViewModel.Factory providesBlankFormListViewModel(FormsRepositoryProvider formsRepositoryProvider, InstancesRepositoryProvider instancesRepositoryProvider, Application application, FormsDataService formsDataService, Scheduler scheduler, SettingsProvider settingsProvider, ChangeLockProvider changeLockProvider, ProjectsDataService projectsDataService) { - return new BlankFormListViewModel.Factory(instancesRepositoryProvider.create(), application, formsDataService, scheduler, settingsProvider.getUnprotectedSettings(), projectsDataService.getCurrentProject().getUuid()); + return new BlankFormListViewModel.Factory(instancesRepositoryProvider.create(), application, formsDataService, scheduler, settingsProvider.getUnprotectedSettings(), projectsDataService.requireCurrentProject().getUuid()); } @Provides @@ -614,7 +614,7 @@ public ImageCompressionController providesImageCompressorManager() { @Provides public FormLoaderTask.FormEntryControllerFactory formEntryControllerFactory(ProjectsDataService projectsDataService, EntitiesRepositoryProvider entitiesRepositoryProvider, SettingsProvider settingsProvider) { - String projectId = projectsDataService.getCurrentProject().getUuid(); + String projectId = projectsDataService.requireCurrentProject().getUuid(); EntitiesRepository entitiesRepository = entitiesRepositoryProvider.create(projectId); return new CollectFormEntryControllerFactory(entitiesRepository, settingsProvider.getUnprotectedSettings(projectId)); } diff --git a/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstanceDiskSynchronizer.java b/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstanceDiskSynchronizer.java index 912c59e9455..de406e8e7c2 100644 --- a/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstanceDiskSynchronizer.java +++ b/collect_app/src/main/java/org/odk/collect/android/instancemanagement/InstanceDiskSynchronizer.java @@ -194,7 +194,7 @@ private void encryptInstance(Instance instance) throws EncryptionException, IOEx String instancePath = instance.getInstanceFilePath(); File instanceXml = new File(instancePath); if (!new File(instanceXml.getParentFile(), "submission.xml.enc").exists()) { - Uri uri = InstancesContract.getUri(projectsDataService.getCurrentProject().getUuid(), instance.getDbId()); + Uri uri = InstancesContract.getUri(projectsDataService.requireCurrentProject().getUuid(), instance.getDbId()); InstanceMetadata instanceMetadata = new InstanceMetadata(getInstanceIdFromInstance(instancePath), null, null); EncryptionUtils.EncryptedFormInformation formInfo = EncryptionUtils.getEncryptedFormInformation(uri, instanceMetadata); diff --git a/collect_app/src/main/java/org/odk/collect/android/instancemanagement/send/InstanceUploaderListActivity.java b/collect_app/src/main/java/org/odk/collect/android/instancemanagement/send/InstanceUploaderListActivity.java index b7339bb73a7..648c4950955 100644 --- a/collect_app/src/main/java/org/odk/collect/android/instancemanagement/send/InstanceUploaderListActivity.java +++ b/collect_app/src/main/java/org/odk/collect/android/instancemanagement/send/InstanceUploaderListActivity.java @@ -257,7 +257,7 @@ void init() { private void updateAutoSendStatus() { // This shouldn't use WorkManager directly but it's likely this code will be removed when // we eventually move sending forms to a Foreground Service (rather than a blocking AsyncTask) - String tag = ((FormUpdateAndInstanceSubmitScheduler) instanceSubmitScheduler).getAutoSendTag(projectsDataService.getCurrentProject().getUuid()); + String tag = ((FormUpdateAndInstanceSubmitScheduler) instanceSubmitScheduler).getAutoSendTag(projectsDataService.requireCurrentProject().getUuid()); LiveData> statuses = WorkManager.getInstance().getWorkInfosForUniqueWorkLiveData(tag); statuses.observe(this, workStatuses -> { if (workStatuses != null) { @@ -379,7 +379,7 @@ public void onItemClick(AdapterView parent, View view, int position, long row ToastUtils.showLongToast(this, org.odk.collect.strings.R.string.encrypted_form); } else { long instanceId = c.getLong(c.getColumnIndex(DatabaseInstanceColumns._ID)); - Intent intent = FormFillingIntentFactory.editInstanceIntent(this, projectsDataService.getCurrentProject().getUuid(), instanceId); + Intent intent = FormFillingIntentFactory.editInstanceIntent(this, projectsDataService.requireCurrentProject().getUuid(), instanceId); startActivity(intent); } } diff --git a/collect_app/src/main/java/org/odk/collect/android/mainmenu/CurrentProjectViewModel.kt b/collect_app/src/main/java/org/odk/collect/android/mainmenu/CurrentProjectViewModel.kt index 383a93749da..a0aaeff908c 100644 --- a/collect_app/src/main/java/org/odk/collect/android/mainmenu/CurrentProjectViewModel.kt +++ b/collect_app/src/main/java/org/odk/collect/android/mainmenu/CurrentProjectViewModel.kt @@ -15,7 +15,7 @@ class CurrentProjectViewModel( projectsDataService.update() } - val currentProject = projectsDataService.getCurrentProjectFlow().asLiveData() + val currentProject = projectsDataService.getCurrentProject().asLiveData() fun setCurrentProject(project: Project.Saved) { Analytics.log(AnalyticsEvents.SWITCH_PROJECT) @@ -23,12 +23,7 @@ class CurrentProjectViewModel( } fun hasCurrentProject(): Boolean { - return try { - projectsDataService.getCurrentProject() - true - } catch (e: IllegalStateException) { - false - } + return projectsDataService.getCurrentProject().value != null } fun refresh() { diff --git a/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt b/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt index 901f34018a2..322f330237a 100644 --- a/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt +++ b/collect_app/src/main/java/org/odk/collect/android/mainmenu/MainMenuViewModel.kt @@ -111,12 +111,12 @@ class MainMenuViewModel( fun refreshInstances() { scheduler.immediate({ InstanceDiskSynchronizer(settingsProvider).doInBackground() - instancesDataService.update(projectsDataService.getCurrentProject().uuid) + instancesDataService.update(projectsDataService.requireCurrentProject().uuid) null }) { } } - private val currentProject = projectsDataService.getCurrentProjectFlow().asLiveData() + private val currentProject = projectsDataService.getCurrentProject().asLiveData() val editableInstancesCount: LiveData = currentProject.switchMap { instancesDataService.getEditableCount(it!!.uuid).asLiveData() } diff --git a/collect_app/src/main/java/org/odk/collect/android/preferences/screens/BaseAdminPreferencesFragment.java b/collect_app/src/main/java/org/odk/collect/android/preferences/screens/BaseAdminPreferencesFragment.java index 66a3fd832bf..99ca2e6f617 100644 --- a/collect_app/src/main/java/org/odk/collect/android/preferences/screens/BaseAdminPreferencesFragment.java +++ b/collect_app/src/main/java/org/odk/collect/android/preferences/screens/BaseAdminPreferencesFragment.java @@ -17,7 +17,7 @@ public abstract class BaseAdminPreferencesFragment extends BasePreferencesFragme @Override public void onAttach(@NonNull Context context) { super.onAttach(context); - projectId = projectsDataService.getCurrentProject().getUuid(); + projectId = projectsDataService.requireCurrentProject().getUuid(); adminSettings = settingsProvider.getProtectedSettings(projectId); } diff --git a/collect_app/src/main/java/org/odk/collect/android/preferences/screens/BaseProjectPreferencesFragment.java b/collect_app/src/main/java/org/odk/collect/android/preferences/screens/BaseProjectPreferencesFragment.java index 46b03df0d2b..b90ceaaa79c 100644 --- a/collect_app/src/main/java/org/odk/collect/android/preferences/screens/BaseProjectPreferencesFragment.java +++ b/collect_app/src/main/java/org/odk/collect/android/preferences/screens/BaseProjectPreferencesFragment.java @@ -39,7 +39,7 @@ public void onAttach(@NonNull Context context) { DaggerUtils.getComponent(context).inject(this); projectPreferencesViewModel = new ViewModelProvider(requireActivity(), factory).get(ProjectPreferencesViewModel.class); - projectId = projectsDataService.getCurrentProject().getUuid(); + projectId = projectsDataService.requireCurrentProject().getUuid(); settings = settingsProvider.getUnprotectedSettings(projectId); } diff --git a/collect_app/src/main/java/org/odk/collect/android/preferences/screens/FormManagementPreferencesFragment.java b/collect_app/src/main/java/org/odk/collect/android/preferences/screens/FormManagementPreferencesFragment.java index 7828144fba0..a72c67b59e0 100644 --- a/collect_app/src/main/java/org/odk/collect/android/preferences/screens/FormManagementPreferencesFragment.java +++ b/collect_app/src/main/java/org/odk/collect/android/preferences/screens/FormManagementPreferencesFragment.java @@ -83,7 +83,7 @@ public void onSettingChanged(@NotNull String key) { } if (key.equals(KEY_AUTOSEND) && !StringIdEnumUtils.getAutoSend(settingsProvider.getUnprotectedSettings(), requireContext()).equals(AutoSend.OFF)) { - instanceSubmitScheduler.scheduleAutoSend(projectsDataService.getCurrentProject().getUuid()); + instanceSubmitScheduler.scheduleAutoSend(projectsDataService.requireCurrentProject().getUuid()); } } diff --git a/collect_app/src/main/java/org/odk/collect/android/preferences/screens/ProjectDisplayPreferencesFragment.kt b/collect_app/src/main/java/org/odk/collect/android/preferences/screens/ProjectDisplayPreferencesFragment.kt index 79aef1da6a9..0659c07a050 100644 --- a/collect_app/src/main/java/org/odk/collect/android/preferences/screens/ProjectDisplayPreferencesFragment.kt +++ b/collect_app/src/main/java/org/odk/collect/android/preferences/screens/ProjectDisplayPreferencesFragment.kt @@ -49,7 +49,7 @@ class ProjectDisplayPreferencesFragment : { color: String -> Analytics.log(AnalyticsEvents.CHANGE_PROJECT_COLOR) - val (uuid, name, icon) = projectsDataService.getCurrentProject() + val (uuid, name, icon) = projectsDataService.requireCurrentProject() projectsRepository.save(Project.Saved(uuid, name, icon, color)) findPreference(PROJECT_COLOR_KEY)!!.summaryProvider = ProjectDetailsSummaryProvider( @@ -83,9 +83,9 @@ class ProjectDisplayPreferencesFragment : findPreference(PROJECT_NAME_KEY)!!.onPreferenceChangeListener = this findPreference(PROJECT_ICON_KEY)!!.onPreferenceChangeListener = this (findPreference(PROJECT_NAME_KEY) as EditTextPreference).text = - projectsDataService.getCurrentProject().name + projectsDataService.requireCurrentProject().name (findPreference(PROJECT_ICON_KEY) as EditTextPreference).text = - projectsDataService.getCurrentProject().icon + projectsDataService.requireCurrentProject().icon (findPreference(PROJECT_ICON_KEY) as EditTextPreference).setOnBindEditTextListener { editText: EditText -> editText.addTextChangedListener( OneSignTextWatcher(editText) @@ -99,14 +99,14 @@ class ProjectDisplayPreferencesFragment : ) : Preference.SummaryProvider { override fun provideSummary(preference: Preference): CharSequence { return when (key) { - PROJECT_NAME_KEY -> projectsDataService.getCurrentProject().name - PROJECT_ICON_KEY -> projectsDataService.getCurrentProject().icon + PROJECT_NAME_KEY -> projectsDataService.requireCurrentProject().name + PROJECT_ICON_KEY -> projectsDataService.requireCurrentProject().icon PROJECT_COLOR_KEY -> { val summary: Spannable = SpannableString("■") summary.setSpan( ForegroundColorSpan( Color.parseColor( - projectsDataService.getCurrentProject().color + projectsDataService.requireCurrentProject().color ) ), 0, @@ -124,7 +124,7 @@ class ProjectDisplayPreferencesFragment : if (MultiClickGuard.allowClick(javaClass.name)) { when (preference.key) { PROJECT_COLOR_KEY -> { - val (_, _, icon, color) = projectsDataService.getCurrentProject() + val (_, _, icon, color) = projectsDataService.requireCurrentProject() val bundle = Bundle() bundle.putString(ColorPickerDialog.CURRENT_COLOR, color) bundle.putString(ColorPickerDialog.CURRENT_ICON, icon) @@ -141,7 +141,7 @@ class ProjectDisplayPreferencesFragment : } override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean { - val (uuid, name, icon, color) = projectsDataService.getCurrentProject() + val (uuid, name, icon, color) = projectsDataService.requireCurrentProject() when (preference.key) { PROJECT_NAME_KEY -> { Analytics.log(AnalyticsEvents.CHANGE_PROJECT_NAME) diff --git a/collect_app/src/main/java/org/odk/collect/android/projects/ManualProjectCreatorDialog.kt b/collect_app/src/main/java/org/odk/collect/android/projects/ManualProjectCreatorDialog.kt index 9426d973860..1d0a695ea94 100644 --- a/collect_app/src/main/java/org/odk/collect/android/projects/ManualProjectCreatorDialog.kt +++ b/collect_app/src/main/java/org/odk/collect/android/projects/ManualProjectCreatorDialog.kt @@ -133,7 +133,7 @@ class ManualProjectCreatorDialog : ActivityUtils.startActivityAndCloseAllOthers(activity, MainMenuActivity::class.java) ToastUtils.showLongToast( requireContext(), - getString(org.odk.collect.strings.R.string.switched_project, projectsDataService.getCurrentProject().name) + getString(org.odk.collect.strings.R.string.switched_project, projectsDataService.requireCurrentProject().name) ) } @@ -144,7 +144,7 @@ class ManualProjectCreatorDialog : requireContext(), getString( org.odk.collect.strings.R.string.switched_project, - projectsDataService.getCurrentProject().name + projectsDataService.requireCurrentProject().name ) ) } diff --git a/collect_app/src/main/java/org/odk/collect/android/projects/ProjectDeleter.kt b/collect_app/src/main/java/org/odk/collect/android/projects/ProjectDeleter.kt index c99e8760e26..c7660c1151e 100644 --- a/collect_app/src/main/java/org/odk/collect/android/projects/ProjectDeleter.kt +++ b/collect_app/src/main/java/org/odk/collect/android/projects/ProjectDeleter.kt @@ -22,7 +22,7 @@ class ProjectDeleter( private val changeLockProvider: ChangeLockProvider, private val settingsProvider: SettingsProvider ) { - fun deleteProject(projectId: String = projectsDataService.getCurrentProject().uuid): DeleteProjectResult { + fun deleteProject(projectId: String = projectsDataService.requireCurrentProject().uuid): DeleteProjectResult { return when { unsentInstancesDetected(projectId) -> DeleteProjectResult.UnsentInstances runningBackgroundJobsDetected(projectId) -> DeleteProjectResult.RunningBackgroundJobs @@ -65,7 +65,7 @@ class ProjectDeleter( DatabaseConnection.cleanUp() return try { - projectsDataService.getCurrentProject() + projectsDataService.requireCurrentProject() DeleteProjectResult.DeletedSuccessfullyInactiveProject } catch (e: IllegalStateException) { if (projectsRepository.getAll().isEmpty()) { diff --git a/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt b/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt index eeaed7af174..f69e79265e2 100644 --- a/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt +++ b/collect_app/src/main/java/org/odk/collect/android/projects/ProjectsDataService.kt @@ -21,36 +21,36 @@ class ProjectsDataService( private val currentProject by data(DataKeys.PROJECT, null) { val currentProjectId = getCurrentProjectId() + if (currentProjectId != null) { projectsRepository.get(currentProjectId) } else { - null + val projects = projectsRepository.getAll() + + if (projects.isNotEmpty()) { + projects[0] + } else { + null + } } } - fun getCurrentProjectFlow(): StateFlow { + fun getCurrentProject(): StateFlow { return currentProject.flow() } - fun getCurrentProject(): Project.Saved { - val currentProjectId = getCurrentProjectId() - - if (currentProjectId != null) { - val currentProject = projectsRepository.get(currentProjectId) + @Deprecated( + "Most components should be passed project ID/project as a value", + replaceWith = ReplaceWith("getCurrentProject().value!!") + ) + fun requireCurrentProject(): Project.Saved { + update() + val project = getCurrentProject().value - if (currentProject != null) { - return currentProject - } else { - throw IllegalStateException("Current project does not exist!") - } + if (project != null) { + return project } else { - val projects = projectsRepository.getAll() - - if (projects.isNotEmpty()) { - return projects[0] - } else { - throw IllegalStateException("No current project!") - } + throw IllegalStateException("No current project!") } } diff --git a/collect_app/src/main/java/org/odk/collect/android/projects/QrCodeProjectCreatorDialog.kt b/collect_app/src/main/java/org/odk/collect/android/projects/QrCodeProjectCreatorDialog.kt index 51fd7ba724a..835a6230233 100644 --- a/collect_app/src/main/java/org/odk/collect/android/projects/QrCodeProjectCreatorDialog.kt +++ b/collect_app/src/main/java/org/odk/collect/android/projects/QrCodeProjectCreatorDialog.kt @@ -298,7 +298,7 @@ class QrCodeProjectCreatorDialog : requireContext(), getString( org.odk.collect.strings.R.string.switched_project, - projectsDataService.getCurrentProject().name + projectsDataService.requireCurrentProject().name ) ) } @@ -326,7 +326,7 @@ class QrCodeProjectCreatorDialog : requireContext(), getString( org.odk.collect.strings.R.string.switched_project, - projectsDataService.getCurrentProject().name + projectsDataService.requireCurrentProject().name ) ) } diff --git a/collect_app/src/main/java/org/odk/collect/android/storage/StoragePathProvider.kt b/collect_app/src/main/java/org/odk/collect/android/storage/StoragePathProvider.kt index 36f0a1a3751..1f8909e7f0f 100644 --- a/collect_app/src/main/java/org/odk/collect/android/storage/StoragePathProvider.kt +++ b/collect_app/src/main/java/org/odk/collect/android/storage/StoragePathProvider.kt @@ -19,7 +19,7 @@ class StoragePathProvider( @JvmOverloads @Deprecated(message = "Use create() instead") fun getProjectRootDirPath(projectId: String? = null): String { - val uuid = projectId ?: projectsDataService.getCurrentProject().uuid + val uuid = projectId ?: projectsDataService.requireCurrentProject().uuid val path = getOdkDirPath(StorageSubdirectory.PROJECTS) + File.separator + uuid if (!File(path).exists()) { diff --git a/collect_app/src/main/java/org/odk/collect/android/tasks/DownloadFormListTask.java b/collect_app/src/main/java/org/odk/collect/android/tasks/DownloadFormListTask.java index 80549160f10..608ea44d891 100644 --- a/collect_app/src/main/java/org/odk/collect/android/tasks/DownloadFormListTask.java +++ b/collect_app/src/main/java/org/odk/collect/android/tasks/DownloadFormListTask.java @@ -68,7 +68,7 @@ public DownloadFormListTask(ServerFormsDetailsFetcher serverFormsDetailsFetcher) @Override protected Pair, FormSourceException> doInBackground(Void... values) { - formsDataService.refresh(projectsDataService.getCurrentProject().getUuid()); + formsDataService.refresh(projectsDataService.requireCurrentProject().getUuid()); if (webCredentialsUtils != null) { setTemporaryCredentials(); diff --git a/collect_app/src/main/java/org/odk/collect/android/tasks/InstanceUploaderTask.java b/collect_app/src/main/java/org/odk/collect/android/tasks/InstanceUploaderTask.java index b788d041e25..f21a87c94a4 100644 --- a/collect_app/src/main/java/org/odk/collect/android/tasks/InstanceUploaderTask.java +++ b/collect_app/src/main/java/org/odk/collect/android/tasks/InstanceUploaderTask.java @@ -153,7 +153,7 @@ public Outcome doInBackground(Long... instanceIdsToUpload) { InstanceDeleter instanceDeleter = new InstanceDeleter(instancesRepository, formsRepository); instanceDeleter.delete(instancesToDelete.map(Instance::getDbId).toArray(Long[]::new)); - instancesDataService.update(projectsDataService.getCurrentProject().getUuid()); + instancesDataService.update(projectsDataService.requireCurrentProject().getUuid()); return outcome; } diff --git a/collect_app/src/main/java/org/odk/collect/android/utilities/FormsRepositoryProvider.kt b/collect_app/src/main/java/org/odk/collect/android/utilities/FormsRepositoryProvider.kt index f7fd79625a4..d19f0b2bdba 100644 --- a/collect_app/src/main/java/org/odk/collect/android/utilities/FormsRepositoryProvider.kt +++ b/collect_app/src/main/java/org/odk/collect/android/utilities/FormsRepositoryProvider.kt @@ -37,7 +37,7 @@ class FormsRepositoryProvider @JvmOverloads constructor( fun create(): FormsRepository { val currentProject = DaggerUtils.getComponent(Collect.getInstance()).currentProjectProvider() - .getCurrentProject() + .requireCurrentProject() return create(currentProject.uuid) } } diff --git a/collect_app/src/main/java/org/odk/collect/android/utilities/InstancesRepositoryProvider.kt b/collect_app/src/main/java/org/odk/collect/android/utilities/InstancesRepositoryProvider.kt index 04cb531d8f7..89cb951ccc8 100644 --- a/collect_app/src/main/java/org/odk/collect/android/utilities/InstancesRepositoryProvider.kt +++ b/collect_app/src/main/java/org/odk/collect/android/utilities/InstancesRepositoryProvider.kt @@ -28,7 +28,7 @@ class InstancesRepositoryProvider @JvmOverloads constructor( fun create(): InstancesRepository { val currentProject = DaggerUtils.getComponent(Collect.getInstance()).currentProjectProvider() - .getCurrentProject() + .requireCurrentProject() return create(currentProject.uuid) } } diff --git a/collect_app/src/main/java/org/odk/collect/android/utilities/SavepointsRepositoryProvider.kt b/collect_app/src/main/java/org/odk/collect/android/utilities/SavepointsRepositoryProvider.kt index c77a1880e1b..4edea6bbad3 100644 --- a/collect_app/src/main/java/org/odk/collect/android/utilities/SavepointsRepositoryProvider.kt +++ b/collect_app/src/main/java/org/odk/collect/android/utilities/SavepointsRepositoryProvider.kt @@ -27,7 +27,7 @@ class SavepointsRepositoryProvider( fun create(): SavepointsRepository { val currentProject = DaggerUtils.getComponent(Collect.getInstance()).currentProjectProvider() - .getCurrentProject() + .requireCurrentProject() return create(currentProject.uuid) } } diff --git a/collect_app/src/test/java/org/odk/collect/android/external/FormUriActivityTest.kt b/collect_app/src/test/java/org/odk/collect/android/external/FormUriActivityTest.kt index fedcc644b15..9064c407777 100644 --- a/collect_app/src/test/java/org/odk/collect/android/external/FormUriActivityTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/external/FormUriActivityTest.kt @@ -166,7 +166,7 @@ class FormUriActivityTest { val secondProject = Project.Saved("345", "Second project", "A", "#cccccc") projectsRepository.save(firstProject) projectsRepository.save(secondProject) - whenever(projectsDataService.getCurrentProject()).thenReturn(firstProject) + whenever(projectsDataService.requireCurrentProject()).thenReturn(firstProject) val form = formsRepository.save( FormUtils.buildForm( @@ -196,7 +196,7 @@ class FormUriActivityTest { val secondProject = Project.Saved("345", "Second project", "A", "#cccccc") projectsRepository.save(firstProject) projectsRepository.save(secondProject) - whenever(projectsDataService.getCurrentProject()).thenReturn(secondProject) + whenever(projectsDataService.requireCurrentProject()).thenReturn(secondProject) val form = formsRepository.save( FormUtils.buildForm( @@ -220,7 +220,7 @@ class FormUriActivityTest { fun `When uri is null then display alert dialog`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val form = formsRepository.save( FormUtils.buildForm( @@ -247,7 +247,7 @@ class FormUriActivityTest { fun `When uri is invalid then display alert dialog`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val form = formsRepository.save( FormUtils.buildForm( @@ -274,7 +274,7 @@ class FormUriActivityTest { fun `When uri represents a blank form that does not exist then display alert dialog`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val scenario = launcherRule.launchForResult(getBlankFormIntent(project.uuid, 1)) @@ -287,7 +287,7 @@ class FormUriActivityTest { fun `When uri represents a blank form with non existing form file then display alert dialog`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val form = formsRepository.save( FormUtils.buildForm( @@ -313,7 +313,7 @@ class FormUriActivityTest { fun `When uri represents a saved form that does not exist then display alert dialog`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val scenario = launcherRule.launchForResult(getSavedIntent(project.uuid, 1)) @@ -326,7 +326,7 @@ class FormUriActivityTest { fun `When attempting to edit a form with non existing instance file then display alert dialog and remove the instance from the database`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) formsRepository.save( FormUtils.buildForm("1", "1", TempFiles.createTempDir().absolutePath).build() @@ -362,7 +362,7 @@ class FormUriActivityTest { fun `When attempting to edit a form with zero form definitions then display alert dialog with formId if version does not exist`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val instance = instancesRepository.save( Instance.Builder() @@ -392,7 +392,7 @@ class FormUriActivityTest { fun `When attempting to edit a form with zero form definitions then display alert dialog with formId and version if both exist`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val instance = instancesRepository.save( Instance.Builder() @@ -425,7 +425,7 @@ class FormUriActivityTest { fun `When attempting to edit a form with multiple form definitions then display alert dialog`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) formsRepository.save( FormUtils.buildForm( @@ -471,7 +471,7 @@ class FormUriActivityTest { fun `When attempting to edit a form with only one non-deleted form definitions then start form`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val form1 = formsRepository.save( FormUtils.buildForm( @@ -516,7 +516,7 @@ class FormUriActivityTest { fun `When attempting to edit an encrypted form then display alert dialog`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) formsRepository.save( FormUtils.buildForm( @@ -555,7 +555,7 @@ class FormUriActivityTest { fun `When attempting to edit an incomplete form with disabled editing then start form for view only`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) settingsProvider.getProtectedSettings().save(ProtectedProjectKeys.KEY_EDIT_SAVED, false) @@ -582,7 +582,7 @@ class FormUriActivityTest { fun `When attempting to start a new form then there should be no form mode passed with the intent even if editing saved forms is disabled`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) settingsProvider.getProtectedSettings().save(ProtectedProjectKeys.KEY_EDIT_SAVED, false) @@ -604,7 +604,7 @@ class FormUriActivityTest { fun `When attempting to edit a finalized form then start form for view only`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) formsRepository.save( FormUtils.buildForm("1", "1", TempFiles.createTempDir().absolutePath).build() @@ -629,7 +629,7 @@ class FormUriActivityTest { fun `When attempting to edit a submitted form then start form for view only`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) formsRepository.save( FormUtils.buildForm("1", "1", TempFiles.createTempDir().absolutePath).build() @@ -654,7 +654,7 @@ class FormUriActivityTest { fun `When attempting to edit a form that failed to submit then start form for view only`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) formsRepository.save( FormUtils.buildForm("1", "1", TempFiles.createTempDir().absolutePath).build() @@ -679,7 +679,7 @@ class FormUriActivityTest { fun `Form filling should not be started again after recreating the activity`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val form = formsRepository.save( FormUtils.buildForm( @@ -702,7 +702,7 @@ class FormUriActivityTest { fun `Form filling should not be started again after recreating the activity before starting`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val form = formsRepository.save( FormUtils.buildForm( @@ -724,7 +724,7 @@ class FormUriActivityTest { fun `When there is project id specified in uri that represents a blank form and it matches current project id then start form filling`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val form = formsRepository.save( FormUtils.buildForm( @@ -744,7 +744,7 @@ class FormUriActivityTest { fun `When there is project id specified in uri that represents an incomplete form and it matches current project id then start form filling`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) formsRepository.save( FormUtils.buildForm("1", "1", TempFiles.createTempDir().absolutePath).build() @@ -769,7 +769,7 @@ class FormUriActivityTest { fun `When there is project id specified in uri that represents an invalid form and it matches current project id then start form filling`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) formsRepository.save( FormUtils.buildForm("1", "1", TempFiles.createTempDir().absolutePath).build() @@ -794,7 +794,7 @@ class FormUriActivityTest { fun `When there is no project id specified in uri that represents a blank form and first available project id matches current project id then start form filling`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val form = formsRepository.save( FormUtils.buildForm( @@ -814,7 +814,7 @@ class FormUriActivityTest { fun `When there is no project id specified in uri that represents a saved form and first available project id matches current project id then start form filling`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) formsRepository.save( FormUtils.buildForm("1", "1", TempFiles.createTempDir().absolutePath).build() @@ -850,7 +850,7 @@ class FormUriActivityTest { fun `If there is a savepoint, display a recovery dialog before starting a blank form`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val form = formsRepository.save( FormUtils.buildForm( @@ -873,7 +873,7 @@ class FormUriActivityTest { fun `If there is a savepoint, display a recovery dialog before starting a saved form`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val form = formsRepository.save( FormUtils.buildForm( @@ -905,7 +905,7 @@ class FormUriActivityTest { fun `If there is a savepoint for older version of the blank form, display a recovery dialog and start the old version of the blank form if a user accepts`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val formV1 = formsRepository.save( FormUtils.buildForm( @@ -939,7 +939,7 @@ class FormUriActivityTest { fun `If there is a savepoint for older version of the blank form, display a recovery dialog and start the new version of the blank form if a user declines`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val formV1 = formsRepository.save( FormUtils.buildForm( @@ -974,7 +974,7 @@ class FormUriActivityTest { fun `An existing savepoint for a blank form should be removed when a user declines`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val form = formsRepository.save( FormUtils.buildForm( @@ -1004,7 +1004,7 @@ class FormUriActivityTest { fun `An existing savepoint for a saved form should be removed when a user declines`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val form = formsRepository.save( FormUtils.buildForm( @@ -1043,7 +1043,7 @@ class FormUriActivityTest { fun `When attempting to start a new form that does not use entities and the forms database is locked then start form filling`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val form = formsRepository.save( FormUtils.buildForm( @@ -1064,7 +1064,7 @@ class FormUriActivityTest { fun `When attempting to start a new form that uses entities and the forms database is locked then display alert dialog`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) val form = formsRepository.save( FormUtils.buildForm( @@ -1089,7 +1089,7 @@ class FormUriActivityTest { fun `When attempting to edit a form that does not use entities and the forms database is locked then start form filling`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) formsRepository.save( FormUtils.buildForm("1", "1", TempFiles.createTempDir().absolutePath).build() @@ -1115,7 +1115,7 @@ class FormUriActivityTest { fun `When attempting to edit a form that uses entities and the forms database is locked then display alert dialog`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) formsRepository.save( FormUtils.buildForm( @@ -1149,7 +1149,7 @@ class FormUriActivityTest { fun `When attempting to view a non-editable form that uses entities and the forms database is locked then start form for view only`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) formsRepository.save( FormUtils.buildForm( @@ -1180,7 +1180,7 @@ class FormUriActivityTest { fun `When attempting to view a non-editable form that uses entities then do not lock the forms database`() { val project = Project.Saved("123", "First project", "A", "#cccccc") projectsRepository.save(project) - whenever(projectsDataService.getCurrentProject()).thenReturn(project) + whenever(projectsDataService.requireCurrentProject()).thenReturn(project) formsRepository.save( FormUtils.buildForm( diff --git a/collect_app/src/test/java/org/odk/collect/android/formentry/audit/FormSaveViewModelTest.java b/collect_app/src/test/java/org/odk/collect/android/formentry/audit/FormSaveViewModelTest.java index 86c18791d57..6437c5eb0c6 100644 --- a/collect_app/src/test/java/org/odk/collect/android/formentry/audit/FormSaveViewModelTest.java +++ b/collect_app/src/test/java/org/odk/collect/android/formentry/audit/FormSaveViewModelTest.java @@ -98,7 +98,7 @@ public void setup() { audioRecorder = mock(AudioRecorder.class); projectsDataService = mock(ProjectsDataService.class); - when(projectsDataService.getCurrentProject()).thenReturn(Project.Companion.getDEMO_PROJECT()); + when(projectsDataService.requireCurrentProject()).thenReturn(Project.Companion.getDEMO_PROJECT()); formSession = new MutableLiveData<>(new FormSession(formController, form)); viewModel = new FormSaveViewModel(savedStateHandle, () -> CURRENT_TIME, formSaver, mediaUtils, scheduler, audioRecorder, projectsDataService, formSession, entitiesRepository, instancesRepository, savepointsRepository, mock()); diff --git a/collect_app/src/test/java/org/odk/collect/android/mainmenu/CurrentProjectViewModelTest.kt b/collect_app/src/test/java/org/odk/collect/android/mainmenu/CurrentProjectViewModelTest.kt index 4f3d9960851..3c99ae87ba9 100644 --- a/collect_app/src/test/java/org/odk/collect/android/mainmenu/CurrentProjectViewModelTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/mainmenu/CurrentProjectViewModelTest.kt @@ -19,7 +19,7 @@ class CurrentProjectViewModelTest { var instantTaskExecutorRule = InstantTaskExecutorRule() private val projectsDataService = mock { - on { getCurrentProjectFlow() } doReturn MutableStateFlow( + on { getCurrentProject() } doReturn MutableStateFlow( Project.Saved( "123", "Project X", @@ -50,7 +50,7 @@ class CurrentProjectViewModelTest { @Test fun `hasCurrentProject returns false when there is no current project`() { - whenever(projectsDataService.getCurrentProject()).thenThrow(IllegalStateException()) + whenever(projectsDataService.getCurrentProject()).thenReturn(MutableStateFlow(null)) val currentProjectViewModel = CurrentProjectViewModel( projectsDataService ) diff --git a/collect_app/src/test/java/org/odk/collect/android/mainmenu/MainMenuViewModelTest.kt b/collect_app/src/test/java/org/odk/collect/android/mainmenu/MainMenuViewModelTest.kt index 33da9ac3e90..4f9fe11adaf 100644 --- a/collect_app/src/test/java/org/odk/collect/android/mainmenu/MainMenuViewModelTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/mainmenu/MainMenuViewModelTest.kt @@ -45,8 +45,8 @@ class MainMenuViewModelTest { private val settingsProvider = InMemSettingsProvider() private val projectsDataService = mock { - on { getCurrentProject() } doReturn Project.DEMO_PROJECT - on { getCurrentProjectFlow() } doReturn MutableStateFlow(Project.DEMO_PROJECT) + on { requireCurrentProject() } doReturn Project.DEMO_PROJECT + on { getCurrentProject() } doReturn MutableStateFlow(Project.DEMO_PROJECT) } private val instancesDataService = mock { diff --git a/collect_app/src/test/java/org/odk/collect/android/preferences/AppConfigurationGeneratorTest.kt b/collect_app/src/test/java/org/odk/collect/android/preferences/AppConfigurationGeneratorTest.kt index 5eec401e3ad..8925b8f4baf 100644 --- a/collect_app/src/test/java/org/odk/collect/android/preferences/AppConfigurationGeneratorTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/preferences/AppConfigurationGeneratorTest.kt @@ -23,7 +23,7 @@ class AppConfigurationGeneratorTest { private val settingsProvider = InMemSettingsProvider() private val projectsDataService: ProjectsDataService = mock { - on { getCurrentProject() } doReturn Project.Saved("1", "Project X", "X", "#cccccc") + on { requireCurrentProject() } doReturn Project.Saved("1", "Project X", "X", "#cccccc") } val projectDetails = mapOf( diff --git a/collect_app/src/test/java/org/odk/collect/android/preferences/screens/MapsPreferencesFragmentTest.kt b/collect_app/src/test/java/org/odk/collect/android/preferences/screens/MapsPreferencesFragmentTest.kt index fe2a061d18e..965b9bb6be6 100644 --- a/collect_app/src/test/java/org/odk/collect/android/preferences/screens/MapsPreferencesFragmentTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/preferences/screens/MapsPreferencesFragmentTest.kt @@ -38,7 +38,7 @@ class MapsPreferencesFragmentTest { private val project = Project.DEMO_PROJECT private val projectsDataService = mock().apply { - whenever(getCurrentProject()).thenReturn(project) + whenever(requireCurrentProject()).thenReturn(project) } private val projectsRepository = mock().apply { whenever(get(project.uuid)).thenReturn(project) diff --git a/collect_app/src/test/java/org/odk/collect/android/preferences/screens/ProjectDisplayPreferencesFragmentTest.kt b/collect_app/src/test/java/org/odk/collect/android/preferences/screens/ProjectDisplayPreferencesFragmentTest.kt index cc5d3913acf..ef7f701646f 100644 --- a/collect_app/src/test/java/org/odk/collect/android/preferences/screens/ProjectDisplayPreferencesFragmentTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/preferences/screens/ProjectDisplayPreferencesFragmentTest.kt @@ -42,7 +42,7 @@ class ProjectDisplayPreferencesFragmentTest { projectsDataService = mock(ProjectsDataService::class.java) projectsRepository = mock(ProjectsRepository::class.java) - `when`(projectsDataService.getCurrentProject()) + `when`(projectsDataService.requireCurrentProject()) .thenReturn(Project.Saved("123", "Project X", "X", "#cccccc")) CollectHelpers.overrideAppDependencyModule(object : AppDependencyModule() { diff --git a/collect_app/src/test/java/org/odk/collect/android/projects/ExistingProjectMigratorTest.kt b/collect_app/src/test/java/org/odk/collect/android/projects/ExistingProjectMigratorTest.kt index 1381c470f40..bf9c6ef016b 100644 --- a/collect_app/src/test/java/org/odk/collect/android/projects/ExistingProjectMigratorTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/projects/ExistingProjectMigratorTest.kt @@ -69,7 +69,7 @@ class ExistingProjectMigratorTest { } existingProjectMigrator.run() - val existingProject = currentProjectProvider.getCurrentProject() + val existingProject = currentProjectProvider.requireCurrentProject() legacyRootDirs.forEach { assertThat(it.exists(), `is`(false)) @@ -92,7 +92,7 @@ class ExistingProjectMigratorTest { TempFiles.createTempFile(cacheDir, "file", ".temp") existingProjectMigrator.run() - val existingProject = currentProjectProvider.getCurrentProject() + val existingProject = currentProjectProvider.requireCurrentProject() assertThat(cacheDir.exists(), `is`(false)) @@ -119,7 +119,7 @@ class ExistingProjectMigratorTest { } existingProjectMigrator.run() - val existingProject = currentProjectProvider.getCurrentProject() + val existingProject = currentProjectProvider.requireCurrentProject() getProjectDirPaths(existingProject.uuid).forEach { val dir = File(it) assertThat(dir.exists(), `is`(true)) @@ -141,7 +141,7 @@ class ExistingProjectMigratorTest { oldAdminSettings.edit().putString("adminKey", "adminValue").apply() existingProjectMigrator.run() - val existingProject = currentProjectProvider.getCurrentProject() + val existingProject = currentProjectProvider.requireCurrentProject() val generalSettings = settingsProvider.getUnprotectedSettings(existingProject.uuid) assertThat( diff --git a/collect_app/src/test/java/org/odk/collect/android/projects/ManualProjectCreatorDialogTest.kt b/collect_app/src/test/java/org/odk/collect/android/projects/ManualProjectCreatorDialogTest.kt index 99ec41a07d1..dbd2ef8a48e 100644 --- a/collect_app/src/test/java/org/odk/collect/android/projects/ManualProjectCreatorDialogTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/projects/ManualProjectCreatorDialogTest.kt @@ -114,7 +114,7 @@ class ManualProjectCreatorDialogTest { fun `Server project creation should be triggered after clicking on the 'Add' button`() { val projectCreator = mock {} val projectsDataService = mock { - on { getCurrentProject() } doReturn Project.DEMO_PROJECT + on { requireCurrentProject() } doReturn Project.DEMO_PROJECT } CollectHelpers.overrideAppDependencyModule(object : AppDependencyModule() { diff --git a/collect_app/src/test/java/org/odk/collect/android/projects/ProjectCreatorTest.kt b/collect_app/src/test/java/org/odk/collect/android/projects/ProjectCreatorTest.kt index 82ddcf03f28..2eb6cec0a0d 100644 --- a/collect_app/src/test/java/org/odk/collect/android/projects/ProjectCreatorTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/projects/ProjectCreatorTest.kt @@ -26,7 +26,7 @@ class ProjectCreatorTest { } private var projectsDataService = mock { - on { getCurrentProject() } doReturn savedProject + on { requireCurrentProject() } doReturn savedProject } private var settingsImporter = mock {} diff --git a/collect_app/src/test/java/org/odk/collect/android/projects/ProjectDeleterTest.kt b/collect_app/src/test/java/org/odk/collect/android/projects/ProjectDeleterTest.kt index 4675a8b1e4c..e687d1fde01 100644 --- a/collect_app/src/test/java/org/odk/collect/android/projects/ProjectDeleterTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/projects/ProjectDeleterTest.kt @@ -222,7 +222,7 @@ class ProjectDeleterTest { val result = deleter.deleteProject(project1.uuid) - assertThat(projectsDataService.getCurrentProject().uuid, equalTo(project2.uuid)) + assertThat(projectsDataService.requireCurrentProject().uuid, equalTo(project2.uuid)) assertThat((result as DeleteProjectResult.DeletedSuccessfullyCurrentProject).newCurrentProject, equalTo(project2)) } @@ -234,7 +234,7 @@ class ProjectDeleterTest { val result = deleter.deleteProject(project1.uuid) - assertThat(projectsDataService.getCurrentProject().uuid, equalTo(project2.uuid)) + assertThat(projectsDataService.requireCurrentProject().uuid, equalTo(project2.uuid)) assertThat(result, instanceOf(DeleteProjectResult.DeletedSuccessfullyInactiveProject::class.java)) } diff --git a/collect_app/src/test/java/org/odk/collect/android/projects/ProjectsDataServiceTest.kt b/collect_app/src/test/java/org/odk/collect/android/projects/ProjectsDataServiceTest.kt index 164021dee4d..2f7946624cd 100644 --- a/collect_app/src/test/java/org/odk/collect/android/projects/ProjectsDataServiceTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/projects/ProjectsDataServiceTest.kt @@ -28,11 +28,11 @@ class ProjectsDataServiceTest { ) @Test - fun `A project should be returned after calling getCurrentProject() if there is a project for given id`() { + fun `A project should be returned after calling requireCurrentProject if there is a project for given id`() { val project = projectsRepository.save(Project.New("ProjectX", "X", "#00FF00")) metaSettings.save(MetaKeys.CURRENT_PROJECT_ID, project.uuid) - assertThat(projectsDataService.getCurrentProject(), `is`(project)) + assertThat(projectsDataService.requireCurrentProject(), `is`(project)) } @Test @@ -42,21 +42,21 @@ class ProjectsDataServiceTest { } @Test(expected = IllegalStateException::class) - fun `getCurrentProject throws IllegalStateException when there is no current project`() { - projectsDataService.getCurrentProject() + fun `requireCurrentProject throws IllegalStateException when there is no current project`() { + projectsDataService.requireCurrentProject() } @Test - fun `getCurrentProject returns first project when there is no current project but there are projects`() { + fun `requireCurrentProject returns first project when there is no current project but there are projects`() { val firstProject = projectsRepository.save(Project.New("ProjectX", "X", "#00FF00")) projectsRepository.save(Project.New("ProjectY", "Y", "#00FF00")) - assertThat(projectsDataService.getCurrentProject(), `is`(firstProject)) + assertThat(projectsDataService.requireCurrentProject(), `is`(firstProject)) } @Test(expected = IllegalStateException::class) - fun `getCurrentProject throws IllegalStateException when current project does not exist`() { + fun `requireCurrentProject throws IllegalStateException when current project does not exist`() { projectsDataService.setCurrentProject("123e4567") - projectsDataService.getCurrentProject() + projectsDataService.requireCurrentProject() } @Test diff --git a/collect_app/src/test/java/org/odk/collect/android/storage/StoragePathProviderTest.kt b/collect_app/src/test/java/org/odk/collect/android/storage/StoragePathProviderTest.kt index bbf9a54c0f2..b19e61e26d4 100644 --- a/collect_app/src/test/java/org/odk/collect/android/storage/StoragePathProviderTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/storage/StoragePathProviderTest.kt @@ -20,7 +20,7 @@ class StoragePathProviderTest { @Before fun setup() { val projectsDataService = mock(ProjectsDataService::class.java) - `when`(projectsDataService.getCurrentProject()).thenReturn( + `when`(projectsDataService.requireCurrentProject()).thenReturn( Project.Saved( "123", "Project", From d5b2c23807e0db03d86b99f57ffcd624b1a4242c Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Thu, 5 Dec 2024 13:14:27 +0000 Subject: [PATCH 12/12] Update test --- .../formlists/blankformlist/BlankFormListViewModelTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collect_app/src/test/java/org/odk/collect/android/formlists/blankformlist/BlankFormListViewModelTest.kt b/collect_app/src/test/java/org/odk/collect/android/formlists/blankformlist/BlankFormListViewModelTest.kt index 9fca88a6256..a1ee64b2f9d 100644 --- a/collect_app/src/test/java/org/odk/collect/android/formlists/blankformlist/BlankFormListViewModelTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/formlists/blankformlist/BlankFormListViewModelTest.kt @@ -53,7 +53,7 @@ class BlankFormListViewModelTest { @Test fun `updates forms when created`() { createViewModel() - verify(formsDataService).update(projectId) + verify(formsDataService).refresh(projectId) } @Test