mirror of
https://github.com/Aviortheking/Neo-Store.git
synced 2025-04-23 19:32:16 +00:00
Reformatted code
This commit is contained in:
parent
b0cec7d768
commit
f79d666219
@ -8,40 +8,43 @@ import com.looker.droidify.utility.extension.android.asSequence
|
|||||||
import com.looker.droidify.utility.extension.text.debug
|
import com.looker.droidify.utility.extension.text.debug
|
||||||
|
|
||||||
class QueryBuilder {
|
class QueryBuilder {
|
||||||
companion object {
|
companion object {
|
||||||
fun trimQuery(query: String): String {
|
fun trimQuery(query: String): String {
|
||||||
return query.lines().map { it.trim() }.filter { it.isNotEmpty() }.joinToString(separator = " ")
|
return query.lines().map { it.trim() }.filter { it.isNotEmpty() }
|
||||||
|
.joinToString(separator = " ")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private val builder = StringBuilder()
|
private val builder = StringBuilder()
|
||||||
private val arguments = mutableListOf<String>()
|
private val arguments = mutableListOf<String>()
|
||||||
|
|
||||||
operator fun plusAssign(query: String) {
|
operator fun plusAssign(query: String) {
|
||||||
if (builder.isNotEmpty()) {
|
if (builder.isNotEmpty()) {
|
||||||
builder.append(" ")
|
builder.append(" ")
|
||||||
|
}
|
||||||
|
builder.append(trimQuery(query))
|
||||||
}
|
}
|
||||||
builder.append(trimQuery(query))
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun remAssign(argument: String) {
|
operator fun remAssign(argument: String) {
|
||||||
this.arguments += argument
|
this.arguments += argument
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun remAssign(arguments: List<String>) {
|
operator fun remAssign(arguments: List<String>) {
|
||||||
this.arguments += arguments
|
this.arguments += arguments
|
||||||
}
|
}
|
||||||
|
|
||||||
fun query(db: SQLiteDatabase, signal: CancellationSignal?): Cursor {
|
fun query(db: SQLiteDatabase, signal: CancellationSignal?): Cursor {
|
||||||
val query = builder.toString()
|
val query = builder.toString()
|
||||||
val arguments = arguments.toTypedArray()
|
val arguments = arguments.toTypedArray()
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
synchronized(QueryBuilder::class.java) {
|
synchronized(QueryBuilder::class.java) {
|
||||||
debug(query)
|
debug(query)
|
||||||
db.rawQuery("EXPLAIN QUERY PLAN $query", arguments).use { it.asSequence()
|
db.rawQuery("EXPLAIN QUERY PLAN $query", arguments).use {
|
||||||
.forEach { debug(":: ${it.getString(it.getColumnIndex("detail"))}") } }
|
it.asSequence()
|
||||||
}
|
.forEach { debug(":: ${it.getString(it.getColumnIndex("detail"))}") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return db.rawQuery(query, arguments, signal)
|
||||||
}
|
}
|
||||||
return db.rawQuery(query, arguments, signal)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -8,172 +8,185 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
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 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.database.Database
|
import com.looker.droidify.database.Database
|
||||||
import com.looker.droidify.entity.ProductItem
|
import com.looker.droidify.entity.ProductItem
|
||||||
import com.looker.droidify.utility.RxUtils
|
import com.looker.droidify.utility.RxUtils
|
||||||
import com.looker.droidify.widget.RecyclerFastScroller
|
import com.looker.droidify.widget.RecyclerFastScroller
|
||||||
|
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
|
||||||
|
|
||||||
class ProductsFragment(): ScreenFragment(), CursorOwner.Callback {
|
class ProductsFragment() : ScreenFragment(), CursorOwner.Callback {
|
||||||
companion object {
|
companion object {
|
||||||
private const val EXTRA_SOURCE = "source"
|
private const val EXTRA_SOURCE = "source"
|
||||||
|
|
||||||
private const val STATE_CURRENT_SEARCH_QUERY = "currentSearchQuery"
|
private const val STATE_CURRENT_SEARCH_QUERY = "currentSearchQuery"
|
||||||
private const val STATE_CURRENT_SECTION = "currentSection"
|
private const val STATE_CURRENT_SECTION = "currentSection"
|
||||||
private const val STATE_CURRENT_ORDER = "currentOrder"
|
private const val STATE_CURRENT_ORDER = "currentOrder"
|
||||||
private const val STATE_LAYOUT_MANAGER = "layoutManager"
|
private const val STATE_LAYOUT_MANAGER = "layoutManager"
|
||||||
}
|
|
||||||
|
|
||||||
enum class Source(val titleResId: Int, val sections: Boolean, val order: Boolean) {
|
|
||||||
AVAILABLE(R.string.available, true, true),
|
|
||||||
INSTALLED(R.string.installed, false, false),
|
|
||||||
UPDATES(R.string.updates, false, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(source: Source): this() {
|
|
||||||
arguments = Bundle().apply {
|
|
||||||
putString(EXTRA_SOURCE, source.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val source: Source
|
|
||||||
get() = requireArguments().getString(EXTRA_SOURCE)!!.let(Source::valueOf)
|
|
||||||
|
|
||||||
private var searchQuery = ""
|
|
||||||
private var section: ProductItem.Section = ProductItem.Section.All
|
|
||||||
private var order = ProductItem.Order.NAME
|
|
||||||
|
|
||||||
private var currentSearchQuery = ""
|
|
||||||
private var currentSection: ProductItem.Section = ProductItem.Section.All
|
|
||||||
private var currentOrder = ProductItem.Order.NAME
|
|
||||||
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?, savedInstanceState: Bundle?): View {
|
enum class Source(val titleResId: Int, val sections: Boolean, val order: Boolean) {
|
||||||
return RecyclerView(requireContext()).apply {
|
AVAILABLE(R.string.available, true, true),
|
||||||
id = android.R.id.list
|
INSTALLED(R.string.installed, false, false),
|
||||||
layoutManager = LinearLayoutManager(context)
|
UPDATES(R.string.updates, false, false)
|
||||||
isMotionEventSplittingEnabled = false
|
|
||||||
isVerticalScrollBarEnabled = false
|
|
||||||
setHasFixedSize(true)
|
|
||||||
recycledViewPool.setMaxRecycledViews(ProductsAdapter.ViewType.PRODUCT.ordinal, 30)
|
|
||||||
val adapter = ProductsAdapter { screenActivity.navigateProduct(it.packageName) }
|
|
||||||
this.adapter = adapter
|
|
||||||
RecyclerFastScroller(this)
|
|
||||||
recyclerView = this
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
constructor(source: Source) : this() {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
arguments = Bundle().apply {
|
||||||
|
putString(EXTRA_SOURCE, source.name)
|
||||||
currentSearchQuery = savedInstanceState?.getString(STATE_CURRENT_SEARCH_QUERY).orEmpty()
|
|
||||||
currentSection = savedInstanceState?.getParcelable(STATE_CURRENT_SECTION) ?: ProductItem.Section.All
|
|
||||||
currentOrder = savedInstanceState?.getString(STATE_CURRENT_ORDER)
|
|
||||||
?.let(ProductItem.Order::valueOf) ?: ProductItem.Order.NAME
|
|
||||||
layoutManagerState = savedInstanceState?.getParcelable(STATE_LAYOUT_MANAGER)
|
|
||||||
|
|
||||||
screenActivity.cursorOwner.attach(this, request)
|
|
||||||
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() }
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe { (recyclerView?.adapter as? ProductsAdapter)?.repositories = it }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
|
||||||
super.onDestroyView()
|
|
||||||
|
|
||||||
recyclerView = null
|
|
||||||
|
|
||||||
screenActivity.cursorOwner.detach(this)
|
|
||||||
repositoriesDisposable?.dispose()
|
|
||||||
repositoriesDisposable = null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
|
||||||
super.onSaveInstanceState(outState)
|
|
||||||
|
|
||||||
outState.putString(STATE_CURRENT_SEARCH_QUERY, currentSearchQuery)
|
|
||||||
outState.putParcelable(STATE_CURRENT_SECTION, currentSection)
|
|
||||||
outState.putString(STATE_CURRENT_ORDER, currentOrder.name)
|
|
||||||
(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)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
layoutManagerState?.let {
|
val source: Source
|
||||||
layoutManagerState = null
|
get() = requireArguments().getString(EXTRA_SOURCE)!!.let(Source::valueOf)
|
||||||
recyclerView?.layoutManager?.onRestoreInstanceState(it)
|
|
||||||
|
private var searchQuery = ""
|
||||||
|
private var section: ProductItem.Section = ProductItem.Section.All
|
||||||
|
private var order = ProductItem.Order.NAME
|
||||||
|
|
||||||
|
private var currentSearchQuery = ""
|
||||||
|
private var currentSection: ProductItem.Section = ProductItem.Section.All
|
||||||
|
private var currentOrder = ProductItem.Order.NAME
|
||||||
|
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?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
return RecyclerView(requireContext()).apply {
|
||||||
|
id = android.R.id.list
|
||||||
|
layoutManager = LinearLayoutManager(context)
|
||||||
|
isMotionEventSplittingEnabled = false
|
||||||
|
isVerticalScrollBarEnabled = false
|
||||||
|
setHasFixedSize(true)
|
||||||
|
recycledViewPool.setMaxRecycledViews(ProductsAdapter.ViewType.PRODUCT.ordinal, 30)
|
||||||
|
val adapter = ProductsAdapter { screenActivity.navigateProduct(it.packageName) }
|
||||||
|
this.adapter = adapter
|
||||||
|
RecyclerFastScroller(this)
|
||||||
|
recyclerView = this
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentSearchQuery != searchQuery || currentSection != section || currentOrder != order) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
currentSearchQuery = searchQuery
|
super.onViewCreated(view, savedInstanceState)
|
||||||
currentSection = section
|
|
||||||
currentOrder = order
|
currentSearchQuery = savedInstanceState?.getString(STATE_CURRENT_SEARCH_QUERY).orEmpty()
|
||||||
recyclerView?.scrollToPosition(0)
|
currentSection =
|
||||||
}
|
savedInstanceState?.getParcelable(STATE_CURRENT_SECTION) ?: ProductItem.Section.All
|
||||||
}
|
currentOrder = savedInstanceState?.getString(STATE_CURRENT_ORDER)
|
||||||
|
?.let(ProductItem.Order::valueOf) ?: ProductItem.Order.NAME
|
||||||
|
layoutManagerState = savedInstanceState?.getParcelable(STATE_LAYOUT_MANAGER)
|
||||||
|
|
||||||
internal fun setSearchQuery(searchQuery: String) {
|
|
||||||
if (this.searchQuery != searchQuery) {
|
|
||||||
this.searchQuery = searchQuery
|
|
||||||
if (view != null) {
|
|
||||||
screenActivity.cursorOwner.attach(this, request)
|
screenActivity.cursorOwner.attach(this, request)
|
||||||
}
|
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() }
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe { (recyclerView?.adapter as? ProductsAdapter)?.repositories = it }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
internal fun setSection(section: ProductItem.Section) {
|
override fun onDestroyView() {
|
||||||
if (this.section != section) {
|
super.onDestroyView()
|
||||||
this.section = section
|
|
||||||
if (view != null) {
|
|
||||||
screenActivity.cursorOwner.attach(this, request)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun setOrder(order: ProductItem.Order) {
|
recyclerView = null
|
||||||
if (this.order != order) {
|
|
||||||
this.order = order
|
screenActivity.cursorOwner.detach(this)
|
||||||
if (view != null) {
|
repositoriesDisposable?.dispose()
|
||||||
screenActivity.cursorOwner.attach(this, request)
|
repositoriesDisposable = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
|
||||||
|
outState.putString(STATE_CURRENT_SEARCH_QUERY, currentSearchQuery)
|
||||||
|
outState.putParcelable(STATE_CURRENT_SECTION, currentSection)
|
||||||
|
outState.putString(STATE_CURRENT_ORDER, currentOrder.name)
|
||||||
|
(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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
layoutManagerState?.let {
|
||||||
|
layoutManagerState = null
|
||||||
|
recyclerView?.layoutManager?.onRestoreInstanceState(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentSearchQuery != searchQuery || currentSection != section || currentOrder != order) {
|
||||||
|
currentSearchQuery = searchQuery
|
||||||
|
currentSection = section
|
||||||
|
currentOrder = order
|
||||||
|
recyclerView?.scrollToPosition(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun setSearchQuery(searchQuery: String) {
|
||||||
|
if (this.searchQuery != searchQuery) {
|
||||||
|
this.searchQuery = searchQuery
|
||||||
|
if (view != null) {
|
||||||
|
screenActivity.cursorOwner.attach(this, request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun setSection(section: ProductItem.Section) {
|
||||||
|
if (this.section != section) {
|
||||||
|
this.section = section
|
||||||
|
if (view != null) {
|
||||||
|
screenActivity.cursorOwner.attach(this, request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun setOrder(order: ProductItem.Order) {
|
||||||
|
if (this.order != order) {
|
||||||
|
this.order = order
|
||||||
|
if (view != null) {
|
||||||
|
screenActivity.cursorOwner.attach(this, request)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user