diff --git a/src/main/kotlin/com/looker/droidify/ui/appsList/AppListFragment.kt b/src/main/kotlin/com/looker/droidify/ui/appsList/AppListFragment.kt index 9741ad92..e4572a07 100644 --- a/src/main/kotlin/com/looker/droidify/ui/appsList/AppListFragment.kt +++ b/src/main/kotlin/com/looker/droidify/ui/appsList/AppListFragment.kt @@ -2,7 +2,6 @@ package com.looker.droidify.ui.appsList import android.database.Cursor import android.os.Bundle -import android.os.Parcelable import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -22,7 +21,7 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.disposables.Disposable import io.reactivex.rxjava3.schedulers.Schedulers -import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.first class AppListFragment() : BaseFragment(), CursorOwner.Callback { @@ -30,7 +29,6 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback { companion object { private const val EXTRA_SOURCE = "source" - private const val STATE_LAYOUT_MANAGER = "layoutManager" } enum class Source(val titleResId: Int, val sections: Boolean, val order: Boolean) { @@ -48,51 +46,10 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback { val source: Source get() = requireArguments().getString(EXTRA_SOURCE)!!.let(Source::valueOf) - private val searchQuery: String - get() { - var _searchQuery = "" - lifecycleScope.launchWhenCreated { viewModel.searchQuery.collect { _searchQuery = it } } - return _searchQuery - } - private val section: ProductItem.Section - get() { - var _section: ProductItem.Section = ProductItem.Section.All - lifecycleScope.launchWhenCreated { viewModel.sections.collect { _section = it } } - return _section - } - private val order: ProductItem.Order - get() { - var _order: ProductItem.Order = ProductItem.Order.LAST_UPDATE - lifecycleScope.launchWhenCreated { viewModel.order.collect { _order = it } } - return _order - } - - private var layoutManagerState: Parcelable? = null - private var recyclerView: RecyclerView? = null private var repositoriesDisposable: Disposable? = null - private val request: CursorOwner.Request - get() { - val searchQuery = searchQuery - val section = if (source.sections) section else ProductItem.Section.All - val order = if (source.order) order else ProductItem.Order.NAME - return when (source) { - Source.AVAILABLE -> CursorOwner.Request.ProductsAvailable( - searchQuery, - section, - order - ) - Source.INSTALLED -> CursorOwner.Request.ProductsInstalled( - searchQuery, - section, - order - ) - Source.UPDATES -> CursorOwner.Request.ProductsUpdates(searchQuery, section, order) - } - } - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -114,14 +71,13 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - layoutManagerState = savedInstanceState?.getParcelable(STATE_LAYOUT_MANAGER) - screenActivity.cursorOwner.attach(this, request) + screenActivity.cursorOwner.attach(this, viewModel.request(source)) repositoriesDisposable = Observable.just(Unit) .concatWith(Database.observable(Database.Subject.Repositories)) .observeOn(Schedulers.io()) .flatMapSingle { RxUtils.querySingle { Database.RepositoryAdapter.getAll(it) } } - .map { it.asSequence().map { Pair(it.id, it) }.toMap() } + .map { list -> list.asSequence().map { Pair(it.id, it) }.toMap() } .observeOn(AndroidSchedulers.mainThread()) .subscribe { (recyclerView?.adapter as? ProductsAdapter)?.repositories = it } } @@ -136,35 +92,28 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback { repositoriesDisposable = null } - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - (layoutManagerState ?: recyclerView?.layoutManager?.onSaveInstanceState()) - ?.let { outState.putParcelable(STATE_LAYOUT_MANAGER, it) } - } - override fun onCursorData(request: CursorOwner.Request, cursor: Cursor?) { (recyclerView?.adapter as? ProductsAdapter)?.apply { this.cursor = cursor - emptyText = when { - cursor == null -> "" - searchQuery.isNotEmpty() -> getString(R.string.no_matching_applications_found) - else -> when (source) { - Source.AVAILABLE -> getString(R.string.no_applications_available) - Source.INSTALLED -> getString(R.string.no_applications_installed) - Source.UPDATES -> getString(R.string.all_applications_up_to_date) + viewLifecycleOwner.lifecycleScope.launchWhenCreated { + emptyText = when { + cursor == null -> "" + viewModel.searchQuery.first() + .isNotEmpty() -> getString(R.string.no_matching_applications_found) + else -> when (source) { + Source.AVAILABLE -> getString(R.string.no_applications_available) + Source.INSTALLED -> getString(R.string.no_applications_installed) + Source.UPDATES -> getString(R.string.all_applications_up_to_date) + } } } } - layoutManagerState?.let { - layoutManagerState = null - recyclerView?.layoutManager?.onRestoreInstanceState(it) - } } internal fun setSearchQuery(searchQuery: String) { viewModel.setSearchQuery(searchQuery) { if (view != null) { - screenActivity.cursorOwner.attach(this, request) + screenActivity.cursorOwner.attach(this, viewModel.request(source)) } } } @@ -172,7 +121,7 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback { internal fun setSection(section: ProductItem.Section) { viewModel.setSection(section) { if (view != null) { - screenActivity.cursorOwner.attach(this, request) + screenActivity.cursorOwner.attach(this, viewModel.request(source)) } } } @@ -180,7 +129,7 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback { internal fun setOrder(order: ProductItem.Order) { viewModel.setOrder(order) { if (view != null) { - screenActivity.cursorOwner.attach(this, request) + screenActivity.cursorOwner.attach(this, viewModel.request(source)) } } } diff --git a/src/main/kotlin/com/looker/droidify/ui/appsList/AppListViewModel.kt b/src/main/kotlin/com/looker/droidify/ui/appsList/AppListViewModel.kt index 3f1adb37..53226e7f 100644 --- a/src/main/kotlin/com/looker/droidify/ui/appsList/AppListViewModel.kt +++ b/src/main/kotlin/com/looker/droidify/ui/appsList/AppListViewModel.kt @@ -2,12 +2,10 @@ package com.looker.droidify.ui.appsList import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.looker.droidify.database.CursorOwner import com.looker.droidify.entity.ProductItem import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch class AppListViewModel : ViewModel() { @@ -21,6 +19,7 @@ class AppListViewModel : ViewModel() { scope = viewModelScope, started = SharingStarted.WhileSubscribed(5000) ) + val sections: StateFlow = _sections.stateIn( initialValue = ProductItem.Section.All, scope = viewModelScope, @@ -32,6 +31,32 @@ class AppListViewModel : ViewModel() { started = SharingStarted.WhileSubscribed(5000) ) + fun request(source: AppListFragment.Source): CursorOwner.Request { + var mSearchQuery = "" + var mSections: ProductItem.Section = ProductItem.Section.All + var mOrder: ProductItem.Order = ProductItem.Order.NAME + viewModelScope.launch { searchQuery.collect { if (source.sections) mSearchQuery = it } } + viewModelScope.launch { sections.collect { if (source.sections) mSections = it } } + viewModelScope.launch { order.collect { if (source.order) mOrder = it } } + return when (source) { + AppListFragment.Source.AVAILABLE -> CursorOwner.Request.ProductsAvailable( + mSearchQuery, + mSections, + mOrder + ) + AppListFragment.Source.INSTALLED -> CursorOwner.Request.ProductsInstalled( + mSearchQuery, + mSections, + mOrder + ) + AppListFragment.Source.UPDATES -> CursorOwner.Request.ProductsUpdates( + mSearchQuery, + mSections, + mOrder + ) + } + } + fun setSection(newSection: ProductItem.Section, perform: () -> Unit) { viewModelScope.launch(Dispatchers.Main) { if (newSection != sections.value) {