Global search
parent
0e3aa3f380
commit
9ce43a39c8
@ -1,8 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CompilerConfiguration">
|
<component name="CompilerConfiguration">
|
||||||
<bytecodeTargetLevel>
|
<bytecodeTargetLevel target="1.8" />
|
||||||
<module name="Kotatsu.app" target="1.8" />
|
|
||||||
</bytecodeTargetLevel>
|
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package org.koitharu.kotatsu.domain
|
||||||
|
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import org.koin.core.KoinComponent
|
||||||
|
import org.koitharu.kotatsu.core.model.Manga
|
||||||
|
import org.koitharu.kotatsu.core.model.SortOrder
|
||||||
|
|
||||||
|
class MangaSearchRepository : KoinComponent {
|
||||||
|
|
||||||
|
fun globalSearch(query: String): Flow<List<Manga>> = flow {
|
||||||
|
val sources = MangaProviderFactory.getSources(false)
|
||||||
|
for (source in sources) {
|
||||||
|
val provider = MangaProviderFactory.create(source)
|
||||||
|
val list = provider.getList(0, query, SortOrder.POPULARITY)
|
||||||
|
emit(list.take(4))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package org.koitharu.kotatsu.ui.common.list
|
||||||
|
|
||||||
|
import android.view.ViewGroup
|
||||||
|
|
||||||
|
class ProgressBarAdapter : BaseRecyclerAdapter<Boolean, Unit>() {
|
||||||
|
|
||||||
|
var isVisible: Boolean
|
||||||
|
get() = dataSet.isNotEmpty()
|
||||||
|
set(value) {
|
||||||
|
if (value == dataSet.isEmpty()) {
|
||||||
|
if (value) {
|
||||||
|
appendItem(true)
|
||||||
|
} else {
|
||||||
|
removeItemAt(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getExtra(item: Boolean, position: Int) = Unit
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup) = ProgressBarHolder(parent)
|
||||||
|
|
||||||
|
override fun onGetItemId(item: Boolean) = 1L
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package org.koitharu.kotatsu.ui.common.list
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import kotlinx.android.synthetic.main.item_progress.*
|
||||||
|
import org.koitharu.kotatsu.R
|
||||||
|
|
||||||
|
class ProgressBarHolder(parent: ViewGroup) :
|
||||||
|
BaseViewHolder<Boolean, Unit>(parent, R.layout.item_progress) {
|
||||||
|
|
||||||
|
override fun onBind(data: Boolean, extra: Unit) {
|
||||||
|
progressBar.visibility = if (data) {
|
||||||
|
View.VISIBLE
|
||||||
|
} else {
|
||||||
|
View.INVISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
package org.koitharu.kotatsu.ui.search.global
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.ui.common.BaseActivity
|
||||||
|
|
||||||
|
class GlobalSearchActivity : BaseActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_search)
|
||||||
|
val query = intent.getStringExtra(EXTRA_QUERY)
|
||||||
|
|
||||||
|
if (query == null) {
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
title = query
|
||||||
|
supportActionBar?.subtitle = getString(R.string.search_results)
|
||||||
|
supportFragmentManager
|
||||||
|
.beginTransaction()
|
||||||
|
.replace(R.id.container, GlobalSearchFragment.newInstance(query))
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private const val EXTRA_QUERY = "query"
|
||||||
|
|
||||||
|
fun newIntent(context: Context, query: String) =
|
||||||
|
Intent(context, GlobalSearchActivity::class.java)
|
||||||
|
.putExtra(EXTRA_QUERY, query)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package org.koitharu.kotatsu.ui.search.global
|
||||||
|
|
||||||
|
import moxy.ktx.moxyPresenter
|
||||||
|
import org.koitharu.kotatsu.ui.list.MangaListFragment
|
||||||
|
import org.koitharu.kotatsu.utils.ext.withArgs
|
||||||
|
|
||||||
|
|
||||||
|
class GlobalSearchFragment: MangaListFragment<Unit>() {
|
||||||
|
|
||||||
|
private val presenter by moxyPresenter(factory = ::GlobalSearchPresenter)
|
||||||
|
|
||||||
|
private val query by stringArg(ARG_QUERY)
|
||||||
|
|
||||||
|
override fun onRequestMoreItems(offset: Int) {
|
||||||
|
if (offset == 0) {
|
||||||
|
presenter.startSearch(query.orEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTitle(): CharSequence? {
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private const val ARG_QUERY = "query"
|
||||||
|
|
||||||
|
fun newInstance(query: String) = GlobalSearchFragment().withArgs(1) {
|
||||||
|
putString(ARG_QUERY, query)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
package org.koitharu.kotatsu.ui.search.global
|
||||||
|
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.catch
|
||||||
|
import kotlinx.coroutines.flow.collect
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
import kotlinx.coroutines.flow.onEmpty
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import moxy.presenterScope
|
||||||
|
import org.koitharu.kotatsu.domain.MangaSearchRepository
|
||||||
|
import org.koitharu.kotatsu.ui.common.BasePresenter
|
||||||
|
import org.koitharu.kotatsu.ui.list.MangaListView
|
||||||
|
import org.koitharu.kotatsu.utils.ext.onFirst
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
class GlobalSearchPresenter : BasePresenter<MangaListView<Unit>>() {
|
||||||
|
|
||||||
|
private lateinit var repository: MangaSearchRepository
|
||||||
|
|
||||||
|
override fun onFirstViewAttach() {
|
||||||
|
repository = MangaSearchRepository()
|
||||||
|
super.onFirstViewAttach()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("EXPERIMENTAL_API_USAGE")
|
||||||
|
fun startSearch(query: String) {
|
||||||
|
presenterScope.launch {
|
||||||
|
viewState.onLoadingStateChanged(isLoading = true)
|
||||||
|
repository.globalSearch(query)
|
||||||
|
.flowOn(Dispatchers.IO)
|
||||||
|
.catch { e ->
|
||||||
|
if (e is IOException) {
|
||||||
|
viewState.onError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onFirst {
|
||||||
|
viewState.onLoadingStateChanged(isLoading = false)
|
||||||
|
}
|
||||||
|
.onEmpty {
|
||||||
|
viewState.onListChanged(emptyList())
|
||||||
|
viewState.onLoadingStateChanged(isLoading = false)
|
||||||
|
}
|
||||||
|
.collect {
|
||||||
|
viewState.onListAppended(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="4dp">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
style="@style/Widget.AppCompat.ProgressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@ -1,2 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu />
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_search"
|
||||||
|
android:icon="@drawable/ic_search"
|
||||||
|
android:orderInCategory="0"
|
||||||
|
android:title="@string/search"
|
||||||
|
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
||||||
|
app:showAsAction="always|collapseActionView" />
|
||||||
|
|
||||||
|
</menu>
|
||||||
@ -1,6 +1,6 @@
|
|||||||
#Sat May 16 07:20:00 EEST 2020
|
#Sat May 30 09:45:56 EEST 2020
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-milestone-1-all.zip
|
||||||
|
|||||||
Loading…
Reference in New Issue