Search manga
parent
1aee900587
commit
b69c624442
@ -0,0 +1,31 @@
|
|||||||
|
package org.koitharu.kotatsu.ui.search
|
||||||
|
|
||||||
|
import android.app.SearchManager
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.ui.common.BaseActivity
|
||||||
|
|
||||||
|
class SearchActivity : BaseActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_search)
|
||||||
|
val query = if (Intent.ACTION_SEARCH == intent.action) {
|
||||||
|
intent.getStringExtra(SearchManager.QUERY)?.trim()
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
if (query == null) {
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
title = query
|
||||||
|
supportActionBar?.setSubtitle(R.string.search_results)
|
||||||
|
supportFragmentManager
|
||||||
|
.beginTransaction()
|
||||||
|
.replace(R.id.container, SearchFragment.newInstance(query))
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package org.koitharu.kotatsu.ui.search
|
||||||
|
|
||||||
|
import moxy.ktx.moxyPresenter
|
||||||
|
import org.koitharu.kotatsu.ui.main.list.MangaListFragment
|
||||||
|
import org.koitharu.kotatsu.utils.ext.withArgs
|
||||||
|
|
||||||
|
class SearchFragment : MangaListFragment<Unit>() {
|
||||||
|
|
||||||
|
private val presenter by moxyPresenter(factory = ::SearchPresenter)
|
||||||
|
|
||||||
|
private val query by stringArg(ARG_QUERY)
|
||||||
|
|
||||||
|
override fun onRequestMoreItems(offset: Int) {
|
||||||
|
presenter.loadList(query.orEmpty(), offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTitle(): CharSequence? {
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private const val ARG_QUERY = "query"
|
||||||
|
|
||||||
|
fun newInstance(query: String) = SearchFragment().withArgs(1) {
|
||||||
|
putString(ARG_QUERY, query)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
package org.koitharu.kotatsu.ui.search
|
||||||
|
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import moxy.InjectViewState
|
||||||
|
import org.koitharu.kotatsu.BuildConfig
|
||||||
|
import org.koitharu.kotatsu.core.model.MangaSource
|
||||||
|
import org.koitharu.kotatsu.domain.MangaProviderFactory
|
||||||
|
import org.koitharu.kotatsu.ui.common.BasePresenter
|
||||||
|
import org.koitharu.kotatsu.ui.main.list.MangaListView
|
||||||
|
|
||||||
|
@InjectViewState
|
||||||
|
class SearchPresenter : BasePresenter<MangaListView<Unit>>() {
|
||||||
|
|
||||||
|
private lateinit var sources: Array<MangaSource>
|
||||||
|
|
||||||
|
override fun onFirstViewAttach() {
|
||||||
|
sources = MangaSource.values()
|
||||||
|
super.onFirstViewAttach()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadList(query: String, offset: Int) {
|
||||||
|
launch {
|
||||||
|
viewState.onLoadingChanged(true)
|
||||||
|
try {
|
||||||
|
//TODO select source
|
||||||
|
val list = withContext(Dispatchers.IO) {
|
||||||
|
MangaProviderFactory.create(MangaSource.READMANGA_RU)
|
||||||
|
.getList(offset, query = query)
|
||||||
|
}
|
||||||
|
if (offset == 0) {
|
||||||
|
viewState.onListChanged(list)
|
||||||
|
} else {
|
||||||
|
viewState.onListAppended(list)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
viewState.onError(e)
|
||||||
|
} finally {
|
||||||
|
viewState.onLoadingChanged(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,13 +1,20 @@
|
|||||||
package org.koitharu.kotatsu.utils
|
package org.koitharu.kotatsu.utils
|
||||||
|
|
||||||
|
import android.app.SearchManager
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
|
import org.koitharu.kotatsu.ui.search.SearchActivity
|
||||||
|
|
||||||
object SearchHelper {
|
object SearchHelper {
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun setupSearchView(menuItem: MenuItem) {
|
fun setupSearchView(menuItem: MenuItem) {
|
||||||
val view = menuItem.actionView as? SearchView ?: return
|
val view = menuItem.actionView as? SearchView ?: return
|
||||||
//TODO
|
val context = view.context
|
||||||
|
val searchManager = context.applicationContext.getSystemService(Context.SEARCH_SERVICE) as SearchManager
|
||||||
|
val info = searchManager.getSearchableInfo(ComponentName(context, SearchActivity::class.java))
|
||||||
|
view.setSearchableInfo(info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/appbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?android:actionBarSize"
|
||||||
|
app:layout_scrollFlags="scroll|enterAlways"
|
||||||
|
app:popupTheme="@style/ThemeOverlay.MaterialComponents.Light" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@id/container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<searchable
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:hint="@string/search_manga"
|
||||||
|
android:inputType="textPersonName"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:voiceLanguageModel="web_search"
|
||||||
|
android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" />
|
||||||
Loading…
Reference in New Issue