diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7a9a413d2..1c9bf7da2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,5 +1,6 @@
-
@@ -16,12 +17,22 @@
-
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/BaseMangaRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/BaseMangaRepository.kt
index 9e60de4a4..b2c32b4d0 100644
--- a/app/src/main/java/org/koitharu/kotatsu/core/parser/BaseMangaRepository.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/BaseMangaRepository.kt
@@ -10,8 +10,6 @@ abstract class BaseMangaRepository(protected val loaderContext: MangaLoaderConte
override val sortOrders: Set get() = emptySet()
- override val isSearchAvailable get() = true
-
override suspend fun getPageFullUrl(page: MangaPage) : String = page.url
override suspend fun getTags(): Set = emptySet()
diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepository.kt
index 28ee01e4e..27009db46 100644
--- a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepository.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepository.kt
@@ -6,8 +6,6 @@ interface MangaRepository {
val sortOrders: Set
- val isSearchAvailable: Boolean
-
suspend fun getList(offset: Int, query: String? = null, sortOrder: SortOrder? = null, tag: MangaTag? = null): List
suspend fun getDetails(manga: Manga) : Manga
diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/GroupleRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/GroupleRepository.kt
index 4a1e1f1a4..d3283f024 100644
--- a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/GroupleRepository.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/GroupleRepository.kt
@@ -25,13 +25,11 @@ abstract class GroupleRepository(
sortOrder: SortOrder?,
tag: MangaTag?
): List {
- val url = if (tag == null) {
- "https://$domain/list?sortType=${getSortKey(sortOrder)}&offset=$offset"
- } else {
- "https://$domain/list/genre/${tag.key}?sortType=${getSortKey(sortOrder)}&offset=$offset"
- }
- val doc = loaderContext.get(url)
- .parseHtml()
+ val doc = when {
+ !query.isNullOrEmpty() -> loaderContext.post("https://$domain/search", mapOf("q" to query))
+ tag == null -> loaderContext.get("https://$domain/list?sortType=${getSortKey(sortOrder)}&offset=$offset")
+ else -> loaderContext.get( "https://$domain/list/genre/${tag.key}?sortType=${getSortKey(sortOrder)}&offset=$offset")
+ }.parseHtml()
val root = doc.body().getElementById("mangaBox")
?.selectFirst("div.tiles.row") ?: throw ParseException("Cannot find root")
return root.select("div.tile").mapNotNull { node ->
diff --git a/app/src/main/java/org/koitharu/kotatsu/domain/MangaProviderFactory.kt b/app/src/main/java/org/koitharu/kotatsu/domain/MangaProviderFactory.kt
index e22b11e99..d77243f59 100644
--- a/app/src/main/java/org/koitharu/kotatsu/domain/MangaProviderFactory.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/domain/MangaProviderFactory.kt
@@ -1,13 +1,13 @@
package org.koitharu.kotatsu.domain
import org.koin.core.KoinComponent
-import org.koin.core.get
+import org.koin.core.inject
import org.koitharu.kotatsu.core.model.MangaSource
import org.koitharu.kotatsu.core.parser.MangaRepository
object MangaProviderFactory : KoinComponent {
- private val loaderContext get() = get()
+ private val loaderContext by inject()
fun create(source: MangaSource): MangaRepository {
val constructor = source.cls.getConstructor(MangaLoaderContext::class.java)
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/MainActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/MainActivity.kt
index ceb2b2038..9ef2b5ef5 100644
--- a/app/src/main/java/org/koitharu/kotatsu/ui/main/MainActivity.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/MainActivity.kt
@@ -57,7 +57,6 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return drawerToggle.onOptionsItemSelected(item) || when(item.itemId) {
-
else -> super.onOptionsItemSelected(item)
}
}
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchActivity.kt
new file mode 100644
index 000000000..59b1165b8
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchActivity.kt
@@ -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()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchFragment.kt
new file mode 100644
index 000000000..fd17b41cd
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchFragment.kt
@@ -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() {
+
+ 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)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchPresenter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchPresenter.kt
new file mode 100644
index 000000000..c0b909aff
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchPresenter.kt
@@ -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>() {
+
+ private lateinit var sources: Array
+
+ 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)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/SearchHelper.kt b/app/src/main/java/org/koitharu/kotatsu/utils/SearchHelper.kt
index a101df1db..8d7c928fa 100644
--- a/app/src/main/java/org/koitharu/kotatsu/utils/SearchHelper.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/utils/SearchHelper.kt
@@ -1,13 +1,20 @@
package org.koitharu.kotatsu.utils
+import android.app.SearchManager
+import android.content.ComponentName
+import android.content.Context
import android.view.MenuItem
import androidx.appcompat.widget.SearchView
+import org.koitharu.kotatsu.ui.search.SearchActivity
object SearchHelper {
@JvmStatic
fun setupSearchView(menuItem: MenuItem) {
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)
}
}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_search.xml b/app/src/main/res/layout/activity_search.xml
new file mode 100644
index 000000000..bf6953216
--- /dev/null
+++ b/app/src/main/res/layout/activity_search.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index faba3e7c4..61db1aaf5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -35,4 +35,6 @@
Create shortcut…
Share %s
Search
+ Search manga
+ Search results
\ No newline at end of file
diff --git a/app/src/main/res/xml/search.xml b/app/src/main/res/xml/search.xml
new file mode 100644
index 000000000..161c80dd9
--- /dev/null
+++ b/app/src/main/res/xml/search.xml
@@ -0,0 +1,8 @@
+
+