Update: Extract Sections and Order from ProductItem class

This commit is contained in:
machiav3lli 2022-02-01 00:51:25 +01:00
parent 63c7a65e21
commit b57ff6e85e
12 changed files with 165 additions and 144 deletions

View File

@ -6,7 +6,7 @@ import android.content.res.Configuration
import com.looker.droidify.PREFS_LANGUAGE import com.looker.droidify.PREFS_LANGUAGE
import com.looker.droidify.PREFS_LANGUAGE_DEFAULT import com.looker.droidify.PREFS_LANGUAGE_DEFAULT
import com.looker.droidify.R import com.looker.droidify.R
import com.looker.droidify.entity.ProductItem import com.looker.droidify.entity.Order
import com.looker.droidify.utility.extension.android.Android import com.looker.droidify.utility.extension.android.Android
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -135,6 +135,7 @@ object Preferences {
"auto_sync", "auto_sync",
Value.EnumerationValue(Preferences.AutoSync.Wifi) Value.EnumerationValue(Preferences.AutoSync.Wifi)
) )
object InstallAfterSync : object InstallAfterSync :
Key<Boolean>("auto_sync_install", Value.BooleanValue(Android.sdk(31))) Key<Boolean>("auto_sync_install", Value.BooleanValue(Android.sdk(31)))
@ -192,14 +193,14 @@ object Preferences {
object Socks : ProxyType("socks", Proxy.Type.SOCKS) object Socks : ProxyType("socks", Proxy.Type.SOCKS)
} }
sealed class SortOrder(override val valueString: String, val order: ProductItem.Order) : sealed class SortOrder(override val valueString: String, val order: Order) :
Enumeration<SortOrder> { Enumeration<SortOrder> {
override val values: List<SortOrder> override val values: List<SortOrder>
get() = listOf(Name, Added, Update) get() = listOf(Name, Added, Update)
object Name : SortOrder("name", ProductItem.Order.NAME) object Name : SortOrder("name", Order.NAME)
object Added : SortOrder("added", ProductItem.Order.DATE_ADDED) object Added : SortOrder("added", Order.DATE_ADDED)
object Update : SortOrder("update", ProductItem.Order.LAST_UPDATE) object Update : SortOrder("update", Order.LAST_UPDATE)
} }
sealed class Theme(override val valueString: String) : Enumeration<Theme> { sealed class Theme(override val valueString: String) : Enumeration<Theme> {

View File

@ -5,31 +5,32 @@ import android.os.Bundle
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.loader.app.LoaderManager import androidx.loader.app.LoaderManager
import androidx.loader.content.Loader import androidx.loader.content.Loader
import com.looker.droidify.entity.ProductItem import com.looker.droidify.entity.Order
import com.looker.droidify.entity.Section
class CursorOwner : Fragment(), LoaderManager.LoaderCallbacks<Cursor> { class CursorOwner : Fragment(), LoaderManager.LoaderCallbacks<Cursor> {
sealed class Request { sealed class Request {
internal abstract val id: Int internal abstract val id: Int
data class ProductsAvailable( data class ProductsAvailable(
val searchQuery: String, val section: ProductItem.Section, val searchQuery: String, val section: Section,
val order: ProductItem.Order, val order: Order,
) : Request() { ) : Request() {
override val id: Int override val id: Int
get() = 1 get() = 1
} }
data class ProductsInstalled( data class ProductsInstalled(
val searchQuery: String, val section: ProductItem.Section, val searchQuery: String, val section: Section,
val order: ProductItem.Order, val order: Order,
) : Request() { ) : Request() {
override val id: Int override val id: Int
get() = 2 get() = 2
} }
data class ProductsUpdates( data class ProductsUpdates(
val searchQuery: String, val section: ProductItem.Section, val searchQuery: String, val section: Section,
val order: ProductItem.Order, val order: Order,
) : Request() { ) : Request() {
override val id: Int override val id: Int
get() = 3 get() = 3

View File

@ -9,7 +9,8 @@ import androidx.sqlite.db.SimpleSQLiteQuery
import androidx.sqlite.db.SupportSQLiteQuery import androidx.sqlite.db.SupportSQLiteQuery
import com.looker.droidify.* import com.looker.droidify.*
import com.looker.droidify.database.entity.* import com.looker.droidify.database.entity.*
import com.looker.droidify.entity.ProductItem import com.looker.droidify.entity.Order
import com.looker.droidify.entity.Section
import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.core.Flowable
@ -91,7 +92,7 @@ interface ProductDao : BaseDao<Product> {
@Transaction @Transaction
fun query( fun query(
installed: Boolean, updates: Boolean, searchQuery: String, installed: Boolean, updates: Boolean, searchQuery: String,
section: ProductItem.Section, order: ProductItem.Order, signal: CancellationSignal? section: Section, order: Order, signal: CancellationSignal?
): Cursor { ): Cursor {
val builder = QueryBuilder() val builder = QueryBuilder()
@ -132,17 +133,17 @@ interface ProductDao : BaseDao<Product> {
builder += """JOIN $ROW_INSTALLED_NAME AS installed builder += """JOIN $ROW_INSTALLED_NAME AS installed
ON product.${ROW_PACKAGE_NAME} = installed.${ROW_PACKAGE_NAME}""" ON product.${ROW_PACKAGE_NAME} = installed.${ROW_PACKAGE_NAME}"""
if (section is ProductItem.Section.Category) { if (section is Section.Category) {
builder += """JOIN $ROW_CATEGORY_NAME AS category builder += """JOIN $ROW_CATEGORY_NAME AS category
ON product.${ROW_PACKAGE_NAME} = category.${ROW_PACKAGE_NAME}""" ON product.${ROW_PACKAGE_NAME} = category.${ROW_PACKAGE_NAME}"""
} }
builder += """WHERE repository.${ROW_ENABLED} != 0""" builder += """WHERE repository.${ROW_ENABLED} != 0"""
if (section is ProductItem.Section.Category) { if (section is Section.Category) {
builder += "AND category.${ROW_NAME} = ?" builder += "AND category.${ROW_NAME} = ?"
builder %= section.name builder %= section.name
} else if (section is ProductItem.Section.Repository) { } else if (section is Section.Repository) {
builder += "AND product.${ROW_REPOSITORY_ID} = ?" builder += "AND product.${ROW_REPOSITORY_ID} = ?"
builder %= section.id.toString() builder %= section.id.toString()
} }
@ -163,9 +164,9 @@ interface ProductDao : BaseDao<Product> {
} }
when (order) { when (order) {
ProductItem.Order.NAME -> Unit Order.NAME -> Unit
ProductItem.Order.DATE_ADDED -> builder += "product.${ROW_ADDED} DESC," Order.DATE_ADDED -> builder += "product.${ROW_ADDED} DESC,"
ProductItem.Order.LAST_UPDATE -> builder += "product.${ROW_UPDATED} DESC," Order.LAST_UPDATE -> builder += "product.${ROW_UPDATED} DESC,"
}::class }::class
builder += "product.${ROW_NAME} COLLATE LOCALIZED ASC" builder += "product.${ROW_NAME} COLLATE LOCALIZED ASC"
@ -180,7 +181,7 @@ interface ProductDao : BaseDao<Product> {
// TODO optimize and simplify // TODO optimize and simplify
fun queryList( fun queryList(
installed: Boolean, updates: Boolean, searchQuery: String, installed: Boolean, updates: Boolean, searchQuery: String,
section: ProductItem.Section, order: ProductItem.Order, numberOfItems: Int = 0 section: Section, order: Order, numberOfItems: Int = 0
): DataSource.Factory<Int, Product> { ): DataSource.Factory<Int, Product> {
val builder = QueryBuilder() val builder = QueryBuilder()
@ -221,17 +222,17 @@ interface ProductDao : BaseDao<Product> {
builder += """JOIN $ROW_INSTALLED_NAME AS installed builder += """JOIN $ROW_INSTALLED_NAME AS installed
ON product.${ROW_PACKAGE_NAME} = installed.${ROW_PACKAGE_NAME}""" ON product.${ROW_PACKAGE_NAME} = installed.${ROW_PACKAGE_NAME}"""
if (section is ProductItem.Section.Category) { if (section is Section.Category) {
builder += """JOIN $ROW_CATEGORY_NAME AS category builder += """JOIN $ROW_CATEGORY_NAME AS category
ON product.${ROW_PACKAGE_NAME} = category.${ROW_PACKAGE_NAME}""" ON product.${ROW_PACKAGE_NAME} = category.${ROW_PACKAGE_NAME}"""
} }
builder += """WHERE repository.${ROW_ENABLED} != 0""" builder += """WHERE repository.${ROW_ENABLED} != 0"""
if (section is ProductItem.Section.Category) { if (section is Section.Category) {
builder += "AND category.${ROW_NAME} = ?" builder += "AND category.${ROW_NAME} = ?"
builder %= section.name builder %= section.name
} else if (section is ProductItem.Section.Repository) { } else if (section is Section.Repository) {
builder += "AND product.${ROW_REPOSITORY_ID} = ?" builder += "AND product.${ROW_REPOSITORY_ID} = ?"
builder %= section.id.toString() builder %= section.id.toString()
} }
@ -252,9 +253,9 @@ interface ProductDao : BaseDao<Product> {
} }
when (order) { when (order) {
ProductItem.Order.NAME -> Unit Order.NAME -> Unit
ProductItem.Order.DATE_ADDED -> builder += "product.${ROW_ADDED} DESC," Order.DATE_ADDED -> builder += "product.${ROW_ADDED} DESC,"
ProductItem.Order.LAST_UPDATE -> builder += "product.${ROW_UPDATED} DESC," Order.LAST_UPDATE -> builder += "product.${ROW_UPDATED} DESC,"
}::class }::class
builder += "product.${ROW_NAME} COLLATE LOCALIZED ASC${if (numberOfItems > 0) " LIMIT $numberOfItems" else ""}" builder += "product.${ROW_NAME} COLLATE LOCALIZED ASC${if (numberOfItems > 0) " LIMIT $numberOfItems" else ""}"

View File

@ -0,0 +1,9 @@
package com.looker.droidify.entity
import com.looker.droidify.R
enum class Order(val titleResId: Int) {
NAME(R.string.name),
DATE_ADDED(R.string.whats_new),
LAST_UPDATE(R.string.recently_updated)
}

View File

@ -1,63 +1,22 @@
package com.looker.droidify.entity package com.looker.droidify.entity
import android.os.Parcel
import com.fasterxml.jackson.core.JsonGenerator import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser import com.fasterxml.jackson.core.JsonParser
import com.looker.droidify.R
import com.looker.droidify.utility.KParcelable
import com.looker.droidify.utility.extension.json.forEachKey import com.looker.droidify.utility.extension.json.forEachKey
data class ProductItem( data class ProductItem(
var repositoryId: Long, var packageName: String, var name: String, var summary: String, var repositoryId: Long,
val icon: String, val metadataIcon: String, val version: String, var installedVersion: String, var packageName: String,
var compatible: Boolean, var canUpdate: Boolean, var matchRank: Int, var name: String,
var summary: String,
val icon: String,
val metadataIcon: String,
val version: String,
var installedVersion: String,
var compatible: Boolean,
var canUpdate: Boolean,
var matchRank: Int,
) { ) {
sealed class Section : KParcelable {
object All : Section() {
@Suppress("unused")
@JvmField
val CREATOR = KParcelable.creator { All }
}
data class Category(val name: String) : Section() {
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeString(name)
}
companion object {
@Suppress("unused")
@JvmField
val CREATOR = KParcelable.creator {
val name = it.readString()!!
Category(name)
}
}
}
data class Repository(val id: Long, val name: String) : Section() {
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeLong(id)
dest.writeString(name)
}
companion object {
@Suppress("unused")
@JvmField
val CREATOR = KParcelable.creator {
val id = it.readLong()
val name = it.readString()!!
Repository(id, name)
}
}
}
}
enum class Order(val titleResId: Int) {
NAME(R.string.name),
DATE_ADDED(R.string.whats_new),
LAST_UPDATE(R.string.recently_updated)
}
fun serialize(generator: JsonGenerator) { fun serialize(generator: JsonGenerator) {
generator.writeNumberField("serialVersion", 1) generator.writeNumberField("serialVersion", 1)
generator.writeNumberField("repositoryId", repositoryId) generator.writeNumberField("repositoryId", repositoryId)

View File

@ -0,0 +1,44 @@
package com.looker.droidify.entity
import android.os.Parcel
import com.looker.droidify.utility.KParcelable
sealed class Section : KParcelable {
object All : Section() {
@Suppress("unused")
@JvmField
val CREATOR = KParcelable.creator { All }
}
data class Category(val name: String) : Section() {
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeString(name)
}
companion object {
@Suppress("unused")
@JvmField
val CREATOR = KParcelable.creator {
val name = it.readString()!!
Category(name)
}
}
}
data class Repository(val id: Long, val name: String) : Section() {
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeLong(id)
dest.writeString(name)
}
companion object {
@Suppress("unused")
@JvmField
val CREATOR = KParcelable.creator {
val id = it.readLong()
val name = it.readString()!!
Repository(id, name)
}
}
}
}

View File

@ -23,7 +23,7 @@ import com.google.android.material.textview.MaterialTextView
import com.looker.droidify.R import com.looker.droidify.R
import com.looker.droidify.content.Preferences import com.looker.droidify.content.Preferences
import com.looker.droidify.databinding.TabsToolbarBinding import com.looker.droidify.databinding.TabsToolbarBinding
import com.looker.droidify.entity.ProductItem import com.looker.droidify.entity.Section
import com.looker.droidify.service.Connection import com.looker.droidify.service.Connection
import com.looker.droidify.service.SyncService import com.looker.droidify.service.SyncService
import com.looker.droidify.ui.fragments.AppListFragment import com.looker.droidify.ui.fragments.AppListFragment
@ -89,8 +89,8 @@ class TabsFragment : ScreenFragment() {
} }
private var searchQuery = "" private var searchQuery = ""
private var sections = listOf<ProductItem.Section>(ProductItem.Section.All) private var sections = listOf<Section>(Section.All)
private var section: ProductItem.Section = ProductItem.Section.All private var section: Section = Section.All
private val syncConnection = Connection(SyncService::class.java, onBind = { _, _ -> private val syncConnection = Connection(SyncService::class.java, onBind = { _, _ ->
viewPager?.let { viewPager?.let {
@ -193,12 +193,12 @@ class TabsFragment : ScreenFragment() {
this.layout = layout this.layout = layout
showSections = savedInstanceState?.getByte(STATE_SHOW_SECTIONS)?.toInt() ?: 0 != 0 showSections = savedInstanceState?.getByte(STATE_SHOW_SECTIONS)?.toInt() ?: 0 != 0
sections = savedInstanceState?.getParcelableArrayList<ProductItem.Section>(STATE_SECTIONS) sections = savedInstanceState?.getParcelableArrayList<Section>(STATE_SECTIONS)
.orEmpty() .orEmpty()
section = savedInstanceState?.getParcelable(STATE_SECTION) ?: ProductItem.Section.All section = savedInstanceState?.getParcelable(STATE_SECTION) ?: Section.All
layout.sectionChange.setOnClickListener { layout.sectionChange.setOnClickListener {
showSections = sections showSections = sections
.any { it !is ProductItem.Section.All } && !showSections .any { it !is Section.All } && !showSections
} }
updateOrder() updateOrder()
@ -240,7 +240,7 @@ class TabsFragment : ScreenFragment() {
.subscribe { .subscribe {
setSectionsAndUpdate( setSectionsAndUpdate(
it.asSequence().sorted() it.asSequence().sorted()
.map(ProductItem.Section::Category).toList(), null .map(Section::Category).toList(), null
) )
} }
repositoriesDisposable = Observable.just(Unit) repositoriesDisposable = Observable.just(Unit)
@ -250,7 +250,7 @@ class TabsFragment : ScreenFragment() {
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe { it -> .subscribe { it ->
setSectionsAndUpdate(null, it.asSequence().filter { it.enabled } setSectionsAndUpdate(null, it.asSequence().filter { it.enabled }
.map { ProductItem.Section.Repository(it.id, it.name) }.toList()) .map { Section.Repository(it.id, it.name) }.toList())
} }
updateSection() updateSection()
@ -383,19 +383,19 @@ class TabsFragment : ScreenFragment() {
productFragments.forEach { it.setOrder(order) } productFragments.forEach { it.setOrder(order) }
} }
private inline fun <reified T : ProductItem.Section> collectOldSections(list: List<T>?): List<T>? { private inline fun <reified T : Section> collectOldSections(list: List<T>?): List<T>? {
val oldList = sections.mapNotNull { it as? T } val oldList = sections.mapNotNull { it as? T }
return if (list == null || oldList == list) oldList else null return if (list == null || oldList == list) oldList else null
} }
private fun setSectionsAndUpdate( private fun setSectionsAndUpdate(
categories: List<ProductItem.Section.Category>?, categories: List<Section.Category>?,
repositories: List<ProductItem.Section.Repository>?, repositories: List<Section.Repository>?,
) { ) {
val oldCategories = collectOldSections(categories) val oldCategories = collectOldSections(categories)
val oldRepositories = collectOldSections(repositories) val oldRepositories = collectOldSections(repositories)
if (oldCategories == null || oldRepositories == null) { if (oldCategories == null || oldRepositories == null) {
sections = listOf(ProductItem.Section.All) + sections = listOf(Section.All) +
(categories ?: oldCategories).orEmpty() + (categories ?: oldCategories).orEmpty() +
(repositories ?: oldRepositories).orEmpty() (repositories ?: oldRepositories).orEmpty()
updateSection() updateSection()
@ -404,15 +404,15 @@ class TabsFragment : ScreenFragment() {
private fun updateSection() { private fun updateSection() {
if (section !in sections) { if (section !in sections) {
section = ProductItem.Section.All section = Section.All
} }
layout?.sectionName?.text = when (val section = section) { layout?.sectionName?.text = when (val section = section) {
is ProductItem.Section.All -> getString(R.string.all_applications) is Section.All -> getString(R.string.all_applications)
is ProductItem.Section.Category -> section.name is Section.Category -> section.name
is ProductItem.Section.Repository -> section.name is Section.Repository -> section.name
} }
layout?.sectionIcon?.visibility = layout?.sectionIcon?.visibility =
if (sections.any { it !is ProductItem.Section.All }) View.VISIBLE else View.GONE if (sections.any { it !is Section.All }) View.VISIBLE else View.GONE
productFragments.forEach { it.setSection(section) } productFragments.forEach { it.setSection(section) }
sectionsList?.adapter?.notifyDataSetChanged() sectionsList?.adapter?.notifyDataSetChanged()
} }
@ -507,8 +507,8 @@ class TabsFragment : ScreenFragment() {
} }
private class SectionsAdapter( private class SectionsAdapter(
private val sections: () -> List<ProductItem.Section>, private val sections: () -> List<Section>,
private val onClick: (ProductItem.Section) -> Unit, private val onClick: (Section) -> Unit,
) : StableRecyclerAdapter<SectionsAdapter.ViewType, ) : StableRecyclerAdapter<SectionsAdapter.ViewType,
RecyclerView.ViewHolder>() { RecyclerView.ViewHolder>() {
enum class ViewType { SECTION } enum class ViewType { SECTION }
@ -589,9 +589,9 @@ class TabsFragment : ScreenFragment() {
section.javaClass != nextSection.javaClass section.javaClass != nextSection.javaClass
) margin else 0 ) margin else 0
holder.title.text = when (section) { holder.title.text = when (section) {
is ProductItem.Section.All -> holder.itemView.resources.getString(R.string.all_applications) is Section.All -> holder.itemView.resources.getString(R.string.all_applications)
is ProductItem.Section.Category -> section.name is Section.Category -> section.name
is ProductItem.Section.Repository -> section.name is Section.Repository -> section.name
} }
} }
} }

View File

@ -16,7 +16,9 @@ import com.looker.droidify.*
import com.looker.droidify.content.Preferences import com.looker.droidify.content.Preferences
import com.looker.droidify.database.DatabaseX import com.looker.droidify.database.DatabaseX
import com.looker.droidify.database.entity.Repository import com.looker.droidify.database.entity.Repository
import com.looker.droidify.entity.Order
import com.looker.droidify.entity.ProductItem import com.looker.droidify.entity.ProductItem
import com.looker.droidify.entity.Section
import com.looker.droidify.index.RepositoryUpdater import com.looker.droidify.index.RepositoryUpdater
import com.looker.droidify.utility.RxUtils import com.looker.droidify.utility.RxUtils
import com.looker.droidify.utility.Utils import com.looker.droidify.utility.Utils
@ -391,8 +393,8 @@ class SyncService : ConnectionService<SyncService.Binder>() {
installed = true, installed = true,
updates = true, updates = true,
searchQuery = "", searchQuery = "",
section = ProductItem.Section.All, section = Section.All,
order = ProductItem.Order.NAME, order = Order.NAME,
signal = it signal = it
) )
.use { .use {

View File

@ -13,7 +13,8 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.looker.droidify.R import com.looker.droidify.R
import com.looker.droidify.database.CursorOwner import com.looker.droidify.database.CursorOwner
import com.looker.droidify.entity.ProductItem import com.looker.droidify.entity.Order
import com.looker.droidify.entity.Section
import com.looker.droidify.screen.BaseFragment import com.looker.droidify.screen.BaseFragment
import com.looker.droidify.ui.adapters.AppListAdapter import com.looker.droidify.ui.adapters.AppListAdapter
import com.looker.droidify.ui.viewmodels.AppListViewModel import com.looker.droidify.ui.viewmodels.AppListViewModel
@ -127,7 +128,7 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback {
} }
} }
internal fun setSection(section: ProductItem.Section) { internal fun setSection(section: Section) {
viewModel.setSection(section) { viewModel.setSection(section) {
if (view != null) { if (view != null) {
screenActivity.cursorOwner.attach(this, viewModel.request(source)) screenActivity.cursorOwner.attach(this, viewModel.request(source))
@ -135,7 +136,7 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback {
} }
} }
internal fun setOrder(order: ProductItem.Order) { internal fun setOrder(order: Order) {
viewModel.setOrder(order) { viewModel.setOrder(order) {
if (view != null) { if (view != null) {
screenActivity.cursorOwner.attach(this, viewModel.request(source)) screenActivity.cursorOwner.attach(this, viewModel.request(source))

View File

@ -3,7 +3,8 @@ package com.looker.droidify.ui.fragments
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import com.looker.droidify.R import com.looker.droidify.R
import com.looker.droidify.entity.ProductItem import com.looker.droidify.entity.Order
import com.looker.droidify.entity.Section
import com.looker.droidify.ui.activities.MainActivityX import com.looker.droidify.ui.activities.MainActivityX
import com.looker.droidify.ui.viewmodels.MainNavFragmentViewModelX import com.looker.droidify.ui.viewmodels.MainNavFragmentViewModelX
@ -26,7 +27,7 @@ abstract class MainNavFragmentX : BaseNavFragment() {
} }
} }
internal fun setSection(section: ProductItem.Section) { internal fun setSection(section: Section) {
viewModel.setSection(section) { viewModel.setSection(section) {
if (view != null) { if (view != null) {
//viewModel.fillList(source) //viewModel.fillList(source)
@ -34,7 +35,7 @@ abstract class MainNavFragmentX : BaseNavFragment() {
} }
} }
internal fun setOrder(order: ProductItem.Order) { internal fun setOrder(order: Order) {
viewModel.setOrder(order) { viewModel.setOrder(order) {
if (view != null) { if (view != null) {
//viewModel.fillList(source) //viewModel.fillList(source)
@ -65,13 +66,13 @@ sealed class Request {
internal abstract val installed: Boolean internal abstract val installed: Boolean
internal abstract val updates: Boolean internal abstract val updates: Boolean
internal abstract val searchQuery: String internal abstract val searchQuery: String
internal abstract val section: ProductItem.Section internal abstract val section: Section
internal abstract val order: ProductItem.Order internal abstract val order: Order
internal open val numberOfItems: Int = 0 internal open val numberOfItems: Int = 0
data class ProductsAll( data class ProductsAll(
override val searchQuery: String, override val section: ProductItem.Section, override val searchQuery: String, override val section: Section,
override val order: ProductItem.Order, override val order: Order,
) : Request() { ) : Request() {
override val id: Int override val id: Int
get() = 1 get() = 1
@ -82,8 +83,8 @@ sealed class Request {
} }
data class ProductsInstalled( data class ProductsInstalled(
override val searchQuery: String, override val section: ProductItem.Section, override val searchQuery: String, override val section: Section,
override val order: ProductItem.Order, override val order: Order,
) : Request() { ) : Request() {
override val id: Int override val id: Int
get() = 2 get() = 2
@ -94,8 +95,8 @@ sealed class Request {
} }
data class ProductsUpdates( data class ProductsUpdates(
override val searchQuery: String, override val section: ProductItem.Section, override val searchQuery: String, override val section: Section,
override val order: ProductItem.Order, override val order: Order,
) : Request() { ) : Request() {
override val id: Int override val id: Int
get() = 3 get() = 3
@ -106,8 +107,8 @@ sealed class Request {
} }
data class ProductsUpdated( data class ProductsUpdated(
override val searchQuery: String, override val section: ProductItem.Section, override val searchQuery: String, override val section: Section,
override val order: ProductItem.Order, override val numberOfItems: Int, override val order: Order, override val numberOfItems: Int,
) : Request() { ) : Request() {
override val id: Int override val id: Int
get() = 4 get() = 4
@ -118,8 +119,8 @@ sealed class Request {
} }
data class ProductsNew( data class ProductsNew(
override val searchQuery: String, override val section: ProductItem.Section, override val searchQuery: String, override val section: Section,
override val order: ProductItem.Order, override val numberOfItems: Int, override val order: Order, override val numberOfItems: Int,
) : Request() { ) : Request() {
override val id: Int override val id: Int
get() = 5 get() = 5

View File

@ -4,7 +4,8 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.looker.droidify.content.Preferences import com.looker.droidify.content.Preferences
import com.looker.droidify.database.CursorOwner import com.looker.droidify.database.CursorOwner
import com.looker.droidify.entity.ProductItem import com.looker.droidify.entity.Order
import com.looker.droidify.entity.Section
import com.looker.droidify.ui.fragments.AppListFragment import com.looker.droidify.ui.fragments.AppListFragment
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -16,17 +17,17 @@ import kotlinx.coroutines.launch
class AppListViewModel : ViewModel() { class AppListViewModel : ViewModel() {
private val _order = MutableStateFlow(Preferences[Preferences.Key.SortOrder].order) private val _order = MutableStateFlow(Preferences[Preferences.Key.SortOrder].order)
private val _sections = MutableStateFlow<ProductItem.Section>(ProductItem.Section.All) private val _sections = MutableStateFlow<Section>(Section.All)
private val _searchQuery = MutableStateFlow("") private val _searchQuery = MutableStateFlow("")
val order: StateFlow<ProductItem.Order> = _order.stateIn( val order: StateFlow<Order> = _order.stateIn(
initialValue = ProductItem.Order.LAST_UPDATE, initialValue = Order.LAST_UPDATE,
scope = viewModelScope, scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000) started = SharingStarted.WhileSubscribed(5000)
) )
val sections: StateFlow<ProductItem.Section> = _sections.stateIn( val sections: StateFlow<Section> = _sections.stateIn(
initialValue = ProductItem.Section.All, initialValue = Section.All,
scope = viewModelScope, scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000) started = SharingStarted.WhileSubscribed(5000)
) )
@ -38,8 +39,8 @@ class AppListViewModel : ViewModel() {
fun request(source: AppListFragment.Source): CursorOwner.Request { fun request(source: AppListFragment.Source): CursorOwner.Request {
var mSearchQuery = "" var mSearchQuery = ""
var mSections: ProductItem.Section = ProductItem.Section.All var mSections: Section = Section.All
var mOrder: ProductItem.Order = ProductItem.Order.NAME var mOrder: Order = Order.NAME
viewModelScope.launch { viewModelScope.launch {
launch { searchQuery.collect { if (source.sections) mSearchQuery = it } } launch { searchQuery.collect { if (source.sections) mSearchQuery = it } }
launch { sections.collect { if (source.sections) mSections = it } } launch { sections.collect { if (source.sections) mSections = it } }
@ -64,7 +65,7 @@ class AppListViewModel : ViewModel() {
} }
} }
fun setSection(newSection: ProductItem.Section, perform: () -> Unit) { fun setSection(newSection: Section, perform: () -> Unit) {
viewModelScope.launch { viewModelScope.launch {
if (newSection != sections.value) { if (newSection != sections.value) {
_sections.emit(newSection) _sections.emit(newSection)
@ -73,7 +74,7 @@ class AppListViewModel : ViewModel() {
} }
} }
fun setOrder(newOrder: ProductItem.Order, perform: () -> Unit) { fun setOrder(newOrder: Order, perform: () -> Unit) {
viewModelScope.launch { viewModelScope.launch {
if (newOrder != order.value) { if (newOrder != order.value) {
_order.emit(newOrder) _order.emit(newOrder)

View File

@ -10,7 +10,8 @@ import androidx.paging.PagedList
import com.looker.droidify.content.Preferences import com.looker.droidify.content.Preferences
import com.looker.droidify.database.DatabaseX import com.looker.droidify.database.DatabaseX
import com.looker.droidify.database.entity.Product import com.looker.droidify.database.entity.Product
import com.looker.droidify.entity.ProductItem import com.looker.droidify.entity.Order
import com.looker.droidify.entity.Section
import com.looker.droidify.ui.fragments.Request import com.looker.droidify.ui.fragments.Request
import com.looker.droidify.ui.fragments.Source import com.looker.droidify.ui.fragments.Source
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -24,18 +25,18 @@ import kotlinx.coroutines.withContext
class MainNavFragmentViewModelX(val db: DatabaseX, primarySource: Source, secondarySource: Source) : class MainNavFragmentViewModelX(val db: DatabaseX, primarySource: Source, secondarySource: Source) :
ViewModel() { ViewModel() {
private val _order = MutableStateFlow(ProductItem.Order.LAST_UPDATE) private val _order = MutableStateFlow(Order.LAST_UPDATE)
private val _sections = MutableStateFlow<ProductItem.Section>(ProductItem.Section.All) private val _sections = MutableStateFlow<Section>(Section.All)
private val _searchQuery = MutableStateFlow("") private val _searchQuery = MutableStateFlow("")
val order: StateFlow<ProductItem.Order> = _order.stateIn( val order: StateFlow<Order> = _order.stateIn(
initialValue = ProductItem.Order.LAST_UPDATE, initialValue = Order.LAST_UPDATE,
scope = viewModelScope, scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000) started = SharingStarted.WhileSubscribed(5000)
) )
val sections: StateFlow<ProductItem.Section> = _sections.stateIn( val sections: StateFlow<Section> = _sections.stateIn(
initialValue = ProductItem.Section.All, initialValue = Section.All,
scope = viewModelScope, scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000) started = SharingStarted.WhileSubscribed(5000)
) )
@ -47,8 +48,8 @@ class MainNavFragmentViewModelX(val db: DatabaseX, primarySource: Source, second
fun request(source: Source): Request { fun request(source: Source): Request {
var mSearchQuery = "" var mSearchQuery = ""
var mSections: ProductItem.Section = ProductItem.Section.All var mSections: Section = Section.All
var mOrder: ProductItem.Order = ProductItem.Order.NAME var mOrder: Order = Order.NAME
viewModelScope.launch { viewModelScope.launch {
launch { searchQuery.collect { if (source.sections) mSearchQuery = it } } launch { searchQuery.collect { if (source.sections) mSearchQuery = it } }
launch { sections.collect { if (source.sections) mSections = it } } launch { sections.collect { if (source.sections) mSections = it } }
@ -74,13 +75,13 @@ class MainNavFragmentViewModelX(val db: DatabaseX, primarySource: Source, second
Source.UPDATED -> Request.ProductsUpdated( Source.UPDATED -> Request.ProductsUpdated(
mSearchQuery, mSearchQuery,
mSections, mSections,
ProductItem.Order.LAST_UPDATE, Order.LAST_UPDATE,
Preferences[Preferences.Key.UpdatedApps] Preferences[Preferences.Key.UpdatedApps]
) )
Source.NEW -> Request.ProductsNew( Source.NEW -> Request.ProductsNew(
mSearchQuery, mSearchQuery,
mSections, mSections,
ProductItem.Order.LAST_UPDATE, Order.LAST_UPDATE,
Preferences[Preferences.Key.NewApps] Preferences[Preferences.Key.NewApps]
) )
} }
@ -140,7 +141,7 @@ class MainNavFragmentViewModelX(val db: DatabaseX, primarySource: Source, second
} }
} }
fun setSection(newSection: ProductItem.Section, perform: () -> Unit) { fun setSection(newSection: Section, perform: () -> Unit) {
viewModelScope.launch { viewModelScope.launch {
if (newSection != sections.value) { if (newSection != sections.value) {
_sections.emit(newSection) _sections.emit(newSection)
@ -149,7 +150,7 @@ class MainNavFragmentViewModelX(val db: DatabaseX, primarySource: Source, second
} }
} }
fun setOrder(newOrder: ProductItem.Order, perform: () -> Unit) { fun setOrder(newOrder: Order, perform: () -> Unit) {
viewModelScope.launch { viewModelScope.launch {
if (newOrder != order.value) { if (newOrder != order.value) {
_order.emit(newOrder) _order.emit(newOrder)