diff --git a/collect_app/src/main/java/org/odk/collect/android/formlists/blankformlist/BlankFormListMenuDelegate.kt b/collect_app/src/main/java/org/odk/collect/android/formlists/blankformlist/BlankFormListMenuDelegate.kt index d2d72a1f557..3d857bb1965 100644 --- a/collect_app/src/main/java/org/odk/collect/android/formlists/blankformlist/BlankFormListMenuDelegate.kt +++ b/collect_app/src/main/java/org/odk/collect/android/formlists/blankformlist/BlankFormListMenuDelegate.kt @@ -22,8 +22,8 @@ class BlankFormListMenuDelegate( private var syncing = false init { - viewModel.isSyncingWithServer().observe(activity) { syncing: Boolean -> - this.syncing = syncing + viewModel.isLoading.observe(activity) { isLoading: Boolean -> + this.syncing = isLoading activity.invalidateOptionsMenu() } 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 e3c81da7d3c..706dc496c37 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 @@ -4,6 +4,7 @@ import android.app.Application import android.net.Uri import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.Observer import androidx.lifecycle.Transformations import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider @@ -51,13 +52,12 @@ class BlankFormListViewModel( private val isFormLoadingRunning = MutableNonNullLiveData(false) private val isSyncingWithStorageRunning = MutableNonNullLiveData(false) - private val isSyncingWithServerRunning = MutableNonNullLiveData(false) val isLoading: LiveData = Transformations.map( LiveDataUtils.zip3( isFormLoadingRunning, isSyncingWithStorageRunning, - isSyncingWithServerRunning, + syncRepository.isSyncing(projectId), ) ) { (one, two, three) -> one || two || three } @@ -81,9 +81,17 @@ class BlankFormListViewModel( return generalSettings.getBoolean(ProjectKeys.KEY_HIDE_OLD_FORM_VERSIONS) } + private val syncWithServerObserver = Observer { + if (!it) { + loadFromDatabase() + } + } + init { loadFromDatabase() syncWithStorage() + + syncRepository.isSyncing(projectId).observeForever(syncWithServerObserver) } fun getAllForms(): List { @@ -165,15 +173,6 @@ class BlankFormListViewModel( ) == FormUpdateMode.MATCH_EXACTLY } - fun isSyncingWithServer(): LiveData { - return Transformations.map( - syncRepository.isSyncing(projectId) - ) { isSyncing -> - isSyncingWithServerRunning.value = isSyncing - isSyncing - } - } - fun isOutOfSyncWithServer(): LiveData { return Transformations.map( syncRepository.getSyncError(projectId) @@ -244,4 +243,9 @@ class BlankFormListViewModel( ) as T } } + + override fun onCleared() { + super.onCleared() + syncRepository.isSyncing(projectId).removeObserver(syncWithServerObserver) + } } diff --git a/collect_app/src/test/java/org/odk/collect/android/formlists/blankformlist/BlankFormListMenuDelegateTest.kt b/collect_app/src/test/java/org/odk/collect/android/formlists/blankformlist/BlankFormListMenuDelegateTest.kt index 610df86485f..794f4631e10 100644 --- a/collect_app/src/test/java/org/odk/collect/android/formlists/blankformlist/BlankFormListMenuDelegateTest.kt +++ b/collect_app/src/test/java/org/odk/collect/android/formlists/blankformlist/BlankFormListMenuDelegateTest.kt @@ -41,7 +41,7 @@ class BlankFormListMenuDelegateTest { @Before fun setup() { whenever(networkStateProvider.isDeviceOnline).thenReturn(true) - whenever(viewModel.isSyncingWithServer()).thenReturn(MutableLiveData(false)) + whenever(viewModel.isLoading).thenReturn(MutableLiveData(false)) whenever(viewModel.isOutOfSyncWithServer()).thenReturn(MutableLiveData(false)) activity = CollectHelpers.createThemedActivity(FragmentActivity::class.java) @@ -78,8 +78,8 @@ class BlankFormListMenuDelegateTest { } @Test - fun `onPrepareOptionsMenu when syncing disables refresh button`() { - whenever(viewModel.isSyncingWithServer()).thenReturn(MutableLiveData(true)) + fun `onPrepareOptionsMenu when loading disables refresh button`() { + whenever(viewModel.isLoading).thenReturn(MutableLiveData(true)) val menuDelegate = createMenuDelegate() val menu = createdMenu() @@ -91,7 +91,7 @@ class BlankFormListMenuDelegateTest { } @Test - fun `onPrepareOptionsMenu when not syncing enables refresh button`() { + fun `onPrepareOptionsMenu when not loading enables refresh button`() { val menuDelegate = createMenuDelegate() val menu = createdMenu() 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 b13461f951e..a78405795f2 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 @@ -78,6 +78,7 @@ class BlankFormListViewModelTest { doReturn(true).whenever(formsUpdater).matchFormsWithServer(projectId) val result = viewModel.syncWithServer() scheduler.runBackground() + scheduler.runBackground() assertThat(result.value, `is`(true)) } @@ -88,6 +89,7 @@ class BlankFormListViewModelTest { doReturn(false).whenever(formsUpdater).matchFormsWithServer(projectId) val result = viewModel.syncWithServer() scheduler.runBackground() + scheduler.runBackground() assertThat(result.value, `is`(false)) } @@ -107,19 +109,6 @@ class BlankFormListViewModelTest { assertThat(viewModel.isMatchExactlyEnabled(), `is`(true)) } - @Test - fun `isSyncingWithServer follows repository isSyncing`() { - createViewModel() - - val liveData = MutableLiveData(true) - whenever(syncRepository.isSyncing(projectId)).thenReturn(liveData) - - val isSyncing = viewModel.isSyncingWithServer() - assertThat(isSyncing.getOrAwaitValue(), `is`(true)) - liveData.value = false - assertThat(isSyncing.getOrAwaitValue(), `is`(false)) - } - @Test fun `isOutOfSyncWithServer follows repository syncError`() { createViewModel() @@ -188,6 +177,28 @@ class BlankFormListViewModelTest { assertFormItem(viewModel.formsToDisplay.value!![1], form(dbId = 2, formId = "2")) } + @Test + fun `after finished syncing with server forms should be loaded from database`() { + createViewModel(false) + val liveData = MutableLiveData(true) + whenever(syncRepository.isSyncing(projectId)).thenReturn(liveData) + + scheduler.runBackground() // load from database + scheduler.runBackground() // sync with storage + + assertThat(viewModel.formsToDisplay.value!!.size, equalTo(0)) + + saveForms( + form(dbId = 1, formId = "1") + ) + + liveData.value = false + + scheduler.runBackground() // load from database after syncing with server + + assertThat(viewModel.formsToDisplay.value!!.size, equalTo(1)) + } + @Test fun `deleted forms should be ignored`() { saveForms( @@ -494,6 +505,7 @@ class BlankFormListViewModelTest { } private fun createViewModel(runAllBackgroundTasks: Boolean = true, shouldHideOldFormVersions: Boolean = true) { + whenever(syncRepository.isSyncing(projectId)).thenReturn(MutableLiveData(false)) whenever(changeLockProvider.getFormLock(projectId)).thenReturn(changeLock) generalSettings.save(ProjectKeys.KEY_HIDE_OLD_FORM_VERSIONS, shouldHideOldFormVersions)