diff --git a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepository.java b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepository.java index a1dc2103a4..cf5675ecd5 100644 --- a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepository.java +++ b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepository.java @@ -4,6 +4,7 @@ import androidx.annotation.Nullable; import androidx.lifecycle.LiveData; import androidx.paging.PagedList; +import androidx.paging.PagingData; import org.dhis2.commons.data.EventViewModel; import org.dhis2.commons.data.SearchTeiModel; @@ -15,6 +16,8 @@ import org.hisp.dhis.android.core.program.Program; import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualizationsGroup; import org.hisp.dhis.android.core.trackedentity.TrackedEntityType; +import org.hisp.dhis.android.core.trackedentity.search.TrackedEntitySearchCollectionRepository; +import org.hisp.dhis.android.core.trackedentity.search.TrackedEntitySearchItem; import org.jetbrains.annotations.NotNull; import java.util.Date; @@ -29,9 +32,6 @@ public interface SearchRepository { Observable> programsWithRegistration(String programTypeId); - @NonNull - LiveData> searchTrackedEntities(SearchParametersModel searchParametersModel, boolean isOnline); - void clearFetchedList(); @NonNull @@ -58,6 +58,10 @@ public interface SearchRepository { TeiDownloadResult download(String teiUid, @Nullable String enrollmentUid, String reason); + SearchTeiModel transform(TrackedEntitySearchItem searchItem, @Nullable Program selectedProgram, boolean offlineOnly, SortingItem sortingItem); + + TrackedEntitySearchCollectionRepository getFilteredRepository(SearchParametersModel searchParametersModel); + void setCurrentProgram(@Nullable String currentProgram); boolean programStagesHaveCoordinates(String programUid); boolean teTypeAttributesHaveCoordinates(String typeId); diff --git a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepositoryImpl.java b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepositoryImpl.java index fe74b6c659..2c89d5d569 100644 --- a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepositoryImpl.java +++ b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepositoryImpl.java @@ -5,9 +5,14 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.lifecycle.LiveData; +import androidx.lifecycle.Transformations; import androidx.paging.DataSource; import androidx.paging.LivePagedListBuilder; import androidx.paging.PagedList; +import androidx.paging.Pager; +import androidx.paging.PagingData; +import androidx.paging.PagingDataTransforms; +import androidx.paging.PagingLiveData; import org.dhis2.R; import org.dhis2.bindings.ExtensionsKt; @@ -97,6 +102,11 @@ import io.reactivex.Flowable; import io.reactivex.Observable; import io.reactivex.Single; +import kotlin.Unit; +import kotlin.coroutines.Continuation; +import kotlinx.coroutines.ExecutorsKt; +import kotlinx.coroutines.flow.Flow; +import kotlinx.coroutines.flow.FlowCollector; public class SearchRepositoryImpl implements SearchRepository { @@ -105,7 +115,7 @@ public class SearchRepositoryImpl implements SearchRepository { private final D2 d2; private final SearchSortingValueSetter sortingValueSetter; private TrackedEntitySearchCollectionRepository trackedEntityInstanceQuery; - private SearchParametersModel savedSearchParameters; + public SearchParametersModel savedSearchParameters; private FilterManager savedFilters; private FilterPresenter filterPresenter; private DhisPeriodUtils periodUtils; @@ -168,40 +178,6 @@ public void clearFetchedList() { fetchedTeiUids.clear(); } - @NonNull - @Override - public LiveData> searchTrackedEntities(SearchParametersModel searchParametersModel, boolean isOnline) { - boolean allowCache = false; - if (!searchParametersModel.equals(savedSearchParameters) || !FilterManager.getInstance().sameFilters(savedFilters)) { - trackedEntityInstanceQuery = getFilteredRepository(searchParametersModel); - } else { - getFilteredRepository(searchParametersModel); - allowCache = true; - } - - if (!fetchedTeiUids.isEmpty() && searchParametersModel.getSelectedProgram() == null) { - trackedEntityInstanceQuery = trackedEntityInstanceQuery.excludeUids().in(new ArrayList<>(fetchedTeiUids)); - } - - DataSource dataSource; - - if (isOnline && FilterManager.getInstance().getStateFilters().isEmpty()) { - dataSource = trackedEntityInstanceQuery.allowOnlineCache().eq(allowCache).offlineFirst().getResultDataSource() - .map(result -> transformResult(result, searchParametersModel.getSelectedProgram(), false, FilterManager.getInstance().getSortingItem())); - } else { - dataSource = trackedEntityInstanceQuery.allowOnlineCache().eq(allowCache).offlineOnly().getResultDataSource() - .map(result -> transformResult(result, searchParametersModel.getSelectedProgram(), true, FilterManager.getInstance().getSortingItem())); - } - - return new LivePagedListBuilder<>(new DataSource.Factory() { - @NonNull - @Override - public DataSource create() { - return dataSource; - } - }, 10).build(); - } - @NonNull @Override public Flowable> searchTeiForMap(SearchParametersModel searchParametersModel, boolean isOnline) { @@ -225,7 +201,8 @@ public Flowable> searchTeiForMap(SearchParametersModel sear .toList().toFlowable(); } - private TrackedEntitySearchCollectionRepository getFilteredRepository(SearchParametersModel searchParametersModel) { + @Override + public TrackedEntitySearchCollectionRepository getFilteredRepository(SearchParametersModel searchParametersModel) { this.savedSearchParameters = searchParametersModel.copy(); this.savedFilters = FilterManager.getInstance().copy(); @@ -247,12 +224,12 @@ private TrackedEntitySearchCollectionRepository getFilteredRepository(SearchPara boolean isUnique = d2.trackedEntityModule().trackedEntityAttributes().uid(dataId).blockingGet().unique(); if (isUnique) { - trackedEntityInstanceQuery = trackedEntityInstanceQuery.byAttribute(dataId).eq(dataValue); + trackedEntityInstanceQuery = trackedEntityInstanceQuery.byFilter(dataId).eq(dataValue); } else if (dataValue.contains("_os_")) { dataValue = dataValue.split("_os_")[1]; - trackedEntityInstanceQuery = trackedEntityInstanceQuery.byAttribute(dataId).eq(dataValue); + trackedEntityInstanceQuery = trackedEntityInstanceQuery.byFilter(dataId).eq(dataValue); } else - trackedEntityInstanceQuery = trackedEntityInstanceQuery.byAttribute(dataId).like(dataValue); + trackedEntityInstanceQuery = trackedEntityInstanceQuery.byFilter(dataId).like(dataValue); } } @@ -725,7 +702,7 @@ public TeiDownloadResult download(String teiUid, @Nullable String enrollmentUid, return teiDownloader.download(teiUid, enrollmentUid, reason); } - private SearchTeiModel transformResult(Result result, @Nullable Program selectedProgram, boolean offlineOnly, SortingItem sortingItem) { + public SearchTeiModel transformResult(Result result, @Nullable Program selectedProgram, boolean offlineOnly, SortingItem sortingItem) { try { return transform(result.getOrThrow(), selectedProgram, offlineOnly, sortingItem); } catch (Exception e) { @@ -736,7 +713,8 @@ private SearchTeiModel transformResult(Result } } - private SearchTeiModel transform(TrackedEntitySearchItem searchItem, @Nullable Program selectedProgram, boolean offlineOnly, SortingItem sortingItem) { + @Override + public SearchTeiModel transform(TrackedEntitySearchItem searchItem, @Nullable Program selectedProgram, boolean offlineOnly, SortingItem sortingItem) { if (!fetchedTeiUids.contains(searchItem.uid())) { fetchedTeiUids.add(searchItem.uid()); } diff --git a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepositoryImplKt.kt b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepositoryImplKt.kt new file mode 100644 index 0000000000..57987f08d5 --- /dev/null +++ b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepositoryImplKt.kt @@ -0,0 +1,50 @@ +package org.dhis2.usescases.searchTrackEntity + +import androidx.paging.PagingData +import kotlinx.coroutines.flow.Flow +import org.dhis2.commons.filters.FilterManager +import org.dhis2.data.search.SearchParametersModel +import org.hisp.dhis.android.core.trackedentity.search.TrackedEntitySearchCollectionRepository +import org.hisp.dhis.android.core.trackedentity.search.TrackedEntitySearchItem + +class SearchRepositoryImplKt( + private val searchRepositoryJava: SearchRepository, +) : SearchRepositoryKt { + + private lateinit var savedSearchParamenters: SearchParametersModel + + private lateinit var savedFilters: FilterManager + + private lateinit var trackedEntityInstanceQuery: TrackedEntitySearchCollectionRepository + + private val fetchedTeiUids = HashSet() + + override fun searchTrackedEntities( + searchParametersModel: SearchParametersModel, + isOnline: Boolean, + ): Flow> { + var allowCache = false + savedSearchParamenters = searchParametersModel.copy() + savedFilters = FilterManager.getInstance().copy() + + if (searchParametersModel != savedSearchParamenters || !FilterManager.getInstance().sameFilters(savedFilters)) { + trackedEntityInstanceQuery = searchRepositoryJava.getFilteredRepository(searchParametersModel) + } else { + trackedEntityInstanceQuery = searchRepositoryJava.getFilteredRepository(searchParametersModel) + allowCache = true + } + + if (fetchedTeiUids.isNotEmpty() && searchParametersModel.selectedProgram == null) { + trackedEntityInstanceQuery = + trackedEntityInstanceQuery.excludeUids().`in`(fetchedTeiUids.toList()) + } + + val pagerFlow = if (isOnline && FilterManager.getInstance().stateFilters.isNotEmpty()) { + trackedEntityInstanceQuery.allowOnlineCache().eq(allowCache).offlineFirst().getPagingData(10) + } else { + trackedEntityInstanceQuery.allowOnlineCache().eq(allowCache).offlineOnly().getPagingData(10) + } + + return pagerFlow + } +} diff --git a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepositoryKt.kt b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepositoryKt.kt new file mode 100644 index 0000000000..382bc6c6a0 --- /dev/null +++ b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepositoryKt.kt @@ -0,0 +1,14 @@ +package org.dhis2.usescases.searchTrackEntity + +import androidx.paging.PagingData +import kotlinx.coroutines.flow.Flow +import org.dhis2.data.search.SearchParametersModel +import org.hisp.dhis.android.core.trackedentity.search.TrackedEntitySearchItem + +interface SearchRepositoryKt { + + fun searchTrackedEntities( + searchParametersModel: SearchParametersModel, + isOnline: Boolean, + ): Flow> +} diff --git a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModel.kt b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModel.kt index fe62d5a57d..c9889afc9e 100644 --- a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModel.kt +++ b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModel.kt @@ -4,11 +4,16 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import androidx.paging.PagedList +import androidx.paging.PagingData +import androidx.paging.cachedIn +import androidx.paging.map import kotlinx.coroutines.async +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.dhis2.commons.data.SearchTeiModel +import org.dhis2.commons.filters.FilterManager import org.dhis2.commons.idlingresource.SearchIdlingResourceSingleton import org.dhis2.commons.network.NetworkUtils import org.dhis2.commons.viewmodel.DispatcherProvider @@ -29,6 +34,7 @@ class SearchTEIViewModel( private val initialProgramUid: String?, initialQuery: MutableMap?, private val searchRepository: SearchRepository, + private val searchRepositoryKt: SearchRepositoryKt, private val searchNavPageConfigurator: SearchPageConfigurator, private val mapDataRepository: MapDataRepository, private val networkUtils: NetworkUtils, @@ -226,11 +232,11 @@ class SearchTEIViewModel( } } - fun fetchListResults(onPagedListReady: (LiveData>?) -> Unit) { + fun fetchListResults(onPagedListReady: (Flow>?) -> Unit) { viewModelScope.launch { val resultPagedList = when { - searching -> loadSearchResults() - displayFrontPageList() -> loadDisplayInListResults() + searching -> loadSearchResults().cachedIn(viewModelScope) + displayFrontPageList() -> loadDisplayInListResults().cachedIn(viewModelScope) else -> null } onPagedListReady(resultPagedList) @@ -238,34 +244,94 @@ class SearchTEIViewModel( } private suspend fun loadSearchResults() = withContext(dispatchers.io()) { - return@withContext searchRepository.searchTrackedEntities( - SearchParametersModel( - selectedProgram = searchRepository.getProgram(initialProgramUid), - queryData = queryData, - ), + val searchParametersModel = SearchParametersModel( + selectedProgram = searchRepository.getProgram(initialProgramUid), + queryData = queryData, + ) + val getPagingData = searchRepositoryKt.searchTrackedEntities( + searchParametersModel, searching && networkUtils.isOnline(), ) + + return@withContext getPagingData.map { pagingData -> + pagingData.map { item -> + if ( + searching && networkUtils.isOnline() && + FilterManager.getInstance().stateFilters.isEmpty() + ) { + searchRepository.transform( + item, + searchParametersModel.selectedProgram, + false, + FilterManager.getInstance().sortingItem, + ) + } else { + searchRepository.transform( + item, + searchParametersModel.selectedProgram, + true, + FilterManager.getInstance().sortingItem, + ) + } + } + } } private suspend fun loadDisplayInListResults() = withContext(dispatchers.io()) { - return@withContext searchRepository.searchTrackedEntities( - SearchParametersModel( - selectedProgram = searchRepository.getProgram(initialProgramUid), - queryData = queryData, - ), + val searchParametersModel = SearchParametersModel( + selectedProgram = searchRepository.getProgram(initialProgramUid), + queryData = queryData, + ) + val getPagingData = searchRepositoryKt.searchTrackedEntities( + searchParametersModel, false, ) + + return@withContext getPagingData.map { pagingData -> + pagingData.map { item -> + searchRepository.transform( + item, + searchParametersModel.selectedProgram, + true, + FilterManager.getInstance().sortingItem, + ) + } + } } - fun fetchGlobalResults(): LiveData>? { - return if (searching) { - searchRepository.searchTrackedEntities( - SearchParametersModel( - selectedProgram = null, - queryData = queryData, - ), - searching && networkUtils.isOnline(), - ) + suspend fun fetchGlobalResults() = withContext(dispatchers.io()) { + val searchParametersModel = SearchParametersModel( + selectedProgram = searchRepository.getProgram(initialProgramUid), + queryData = queryData, + ) + val getPagingData = searchRepositoryKt.searchTrackedEntities( + searchParametersModel, + searching && networkUtils.isOnline(), + ) + + return@withContext if (searching) { + getPagingData.map { pagingData -> + pagingData.map { item -> + if ( + searching && networkUtils.isOnline() && + FilterManager.getInstance().stateFilters.isEmpty() + ) { + searchRepository.transform( + item, + searchParametersModel.selectedProgram, + false, + FilterManager.getInstance().sortingItem, + ) + } else { + searchRepository.transform( + item, + searchParametersModel.selectedProgram, + true, + FilterManager.getInstance().sortingItem, + ) + } + } + } } else { null } diff --git a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTEModule.java b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTEModule.java index 55d1cab699..a6850bd3ab 100644 --- a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTEModule.java +++ b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTEModule.java @@ -156,6 +156,14 @@ SearchRepository searchRepository(@NonNull D2 d2, FilterPresenter filterPresente themeManager); } + @Provides + @PerActivity + SearchRepositoryKt searchRepositoryKt( + SearchRepository searchRepository + ) { + return new SearchRepositoryImplKt(searchRepository); + } + @Provides @PerActivity SearchTEIRepository searchTEIRepository(D2 d2) { @@ -248,6 +256,7 @@ FiltersAdapter provideNewFiltersAdapter() { @PerActivity SearchTeiViewModelFactory providesViewModelFactory( SearchRepository searchRepository, + SearchRepositoryKt searchRepositoryKt, MapDataRepository mapDataRepository, NetworkUtils networkUtils, D2 d2, @@ -255,6 +264,7 @@ SearchTeiViewModelFactory providesViewModelFactory( ) { return new SearchTeiViewModelFactory( searchRepository, + searchRepositoryKt, new SearchPageConfigurator(searchRepository), initialProgram, initialQuery, diff --git a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTeiViewModelFactory.kt b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTeiViewModelFactory.kt index c8bb624e4e..46ff618035 100644 --- a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTeiViewModelFactory.kt +++ b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTeiViewModelFactory.kt @@ -9,6 +9,7 @@ import org.dhis2.maps.usecases.MapStyleConfiguration @Suppress("UNCHECKED_CAST") class SearchTeiViewModelFactory( val searchRepository: SearchRepository, + private val searchRepositoryKt: SearchRepositoryKt, private val searchNavPageConfigurator: SearchPageConfigurator, private val initialProgramUid: String?, private val initialQuery: MutableMap?, @@ -22,6 +23,7 @@ class SearchTeiViewModelFactory( initialProgramUid, initialQuery, searchRepository, + searchRepositoryKt, searchNavPageConfigurator, mapDataRepository, networkUtils, diff --git a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/adapters/SearchAdapterDiffCallback.kt b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/adapters/SearchAdapterDiffCallback.kt index 32ba275c1b..10bb606d35 100644 --- a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/adapters/SearchAdapterDiffCallback.kt +++ b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/adapters/SearchAdapterDiffCallback.kt @@ -19,4 +19,12 @@ class SearchAdapterDiffCallback() : DiffUtil.ItemCallback() { oldItem.sortingValue == newItem.sortingValue && oldItem.enrolledOrgUnit == newItem.enrolledOrgUnit } + + override fun getChangePayload(oldItem: SearchTeiModel, newItem: SearchTeiModel): Any? { + return if (oldItem != newItem) { + newItem + } else { + super.getChangePayload(oldItem, newItem) + } + } } diff --git a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/adapters/SearchTeiLiveAdapter.kt b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/adapters/SearchTeiLiveAdapter.kt index 29e5b86bb3..3769edd2cf 100644 --- a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/adapters/SearchTeiLiveAdapter.kt +++ b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/adapters/SearchTeiLiveAdapter.kt @@ -4,7 +4,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.compose.ui.platform.ComposeView -import androidx.paging.PagedListAdapter +import androidx.paging.PagingDataAdapter import androidx.recyclerview.widget.RecyclerView import com.google.android.material.card.MaterialCardView import org.dhis2.R @@ -28,7 +28,7 @@ class SearchTeiLiveAdapter( private val onDownloadTei: (teiUid: String, enrollmentUid: String?) -> Unit, private val onTeiClick: (teiUid: String, enrollmentUid: String?, isOnline: Boolean) -> Unit, private val onImageClick: (imagePath: String) -> Unit, -) : PagedListAdapter(SearchAdapterDiffCallback()) { +) : PagingDataAdapter(SearchAdapterDiffCallback()) { private enum class SearchItem { TEI, @@ -134,8 +134,4 @@ class SearchTeiLiveAdapter( is SearchErrorViewHolder -> holder.bind(getItem(position)!!) } } - - fun clearList() { - submitList(null) - } } diff --git a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/listView/SearchTEList.kt b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/listView/SearchTEList.kt index 58d186a0e6..ed3c749044 100644 --- a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/listView/SearchTEList.kt +++ b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/listView/SearchTEList.kt @@ -17,9 +17,11 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.updateLayoutParams import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels -import androidx.paging.PagedList +import androidx.lifecycle.viewModelScope import androidx.recyclerview.widget.ConcatAdapter import androidx.recyclerview.widget.RecyclerView +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch import org.dhis2.bindings.dp import org.dhis2.commons.dialogs.imagedetail.ImageDetailActivity import org.dhis2.commons.filters.workingLists.WorkingListViewModel @@ -249,17 +251,14 @@ class SearchTEList : FragmentGlobalAbstract() { initLoading(emptyList()) it.firstOrNull()?.let { searchResult -> if (searchResult.shouldClearProgramData()) { - liveAdapter.clearList() + liveAdapter.refresh() } if (searchResult.shouldClearGlobalData()) { - globalAdapter.clearList() + globalAdapter.refresh() } } displayResult(it) updateRecycler() - recycler.post { - recycler.smoothScrollToPosition(0) - } } } @@ -283,51 +282,26 @@ class SearchTEList : FragmentGlobalAbstract() { private fun restoreAdapters() { initLoading(null) - liveAdapter.clearList() + liveAdapter.refresh() if (!viewModel.filtersApplyOnGlobalSearch()) { - globalAdapter.clearList() + globalAdapter.refresh() } else if (globalAdapter.itemCount > 0) { initGlobalData() } displayResult(null) } - private val initResultCallback = object : PagedList.Callback() { - override fun onChanged(position: Int, count: Int) { - } - - override fun onInserted(position: Int, count: Int) { - onInitDataLoaded() - } - - override fun onRemoved(position: Int, count: Int) { - } - } - - private val globalResultCallback = object : PagedList.Callback() { - override fun onChanged(position: Int, count: Int) { - } - - override fun onInserted(position: Int, count: Int) { - onGlobalDataLoaded() - } - - override fun onRemoved(position: Int, count: Int) { - } - } - private fun initData() { displayLoadingData() viewModel.fetchListResults { - it?.takeIf { view != null }?.apply { - removeObservers(viewLifecycleOwner) - observe(viewLifecycleOwner) { results -> - liveAdapter.submitList(results) { + viewModel.viewModelScope.launch { + it?.takeIf { view != null }?.collectLatest { + liveAdapter.addOnPagesUpdatedListener { onInitDataLoaded() } - results.addWeakCallback(results.snapshot(), initResultCallback) - } - } ?: onInitDataLoaded() + liveAdapter.submitData(it) + } ?: onInitDataLoaded() + } } } @@ -340,7 +314,7 @@ class SearchTEList : FragmentGlobalAbstract() { null }, isLandscape = isLandscape(), - onlineErrorCode = liveAdapter.currentList?.lastOrNull()?.onlineErrorCode, + onlineErrorCode = liveAdapter.snapshot().items.lastOrNull()?.onlineErrorCode, ) } @@ -354,13 +328,12 @@ class SearchTEList : FragmentGlobalAbstract() { private fun initGlobalData() { displayLoadingData() - viewModel.fetchGlobalResults()?.let { - it.removeObservers(viewLifecycleOwner) - it.observe(viewLifecycleOwner) { results -> - globalAdapter.submitList(results) { + viewModel.viewModelScope.launch { + viewModel.fetchGlobalResults()?.collectLatest { + globalAdapter.addOnPagesUpdatedListener { onGlobalDataLoaded() } - results.addWeakCallback(results.snapshot(), globalResultCallback) + globalAdapter.submitData(it) } } } diff --git a/app/src/test/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModelTest.kt b/app/src/test/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModelTest.kt index e058268330..be5250af38 100644 --- a/app/src/test/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModelTest.kt +++ b/app/src/test/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModelTest.kt @@ -38,6 +38,7 @@ class SearchTEIViewModelTest { private val initialProgram = "programUid" private val initialQuery = mutableMapOf() private val repository: SearchRepository = mock() + private val repositoryKt: SearchRepositoryKt = mock() private val pageConfigurator: SearchPageConfigurator = mock() private val mapDataRepository: MapDataRepository = mock() private val networkUtils: NetworkUtils = mock() @@ -59,6 +60,7 @@ class SearchTEIViewModelTest { initialProgram, initialQuery, repository, + repositoryKt, pageConfigurator, mapDataRepository, networkUtils, @@ -187,7 +189,7 @@ class SearchTEIViewModelTest { setCurrentProgram(testingProgram) viewModel.fetchListResults {} testingDispatcher.scheduler.advanceUntilIdle() - verify(repository).searchTrackedEntities( + verify(repositoryKt).searchTrackedEntities( SearchParametersModel( selectedProgram = testingProgram, queryData = mutableMapOf(), @@ -202,7 +204,7 @@ class SearchTEIViewModelTest { setCurrentProgram(testingProgram) viewModel.fetchListResults {} - verify(repository, times(0)).searchTrackedEntities( + verify(repositoryKt, times(0)).searchTrackedEntities( SearchParametersModel( selectedProgram = testingProgram, queryData = mutableMapOf(), @@ -210,7 +212,7 @@ class SearchTEIViewModelTest { true, ) - verify(repository, times(0)).searchTrackedEntities( + verify(repositoryKt, times(0)).searchTrackedEntities( SearchParametersModel( selectedProgram = testingProgram, queryData = mutableMapOf(), diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 42b7f52c80..5f98712634 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ hilt = '2.47' hiltCompiler = '1.0.0' jacoco = '0.8.10' designSystem = "0.2-20240206.071329-16" -dhis2sdk = "1.10.0-20240119.100209-6" +dhis2sdk = "1.10.0-20240129.132841-8" ruleEngine = "2.1.9" appcompat = "1.6.1" annotation = "1.6.0"