Search manga

This commit is contained in:
Koitharu
2020-02-06 20:48:47 +02:00
parent 1aee900587
commit b69c624442
13 changed files with 175 additions and 17 deletions

View File

@@ -10,8 +10,6 @@ abstract class BaseMangaRepository(protected val loaderContext: MangaLoaderConte
override val sortOrders: Set<SortOrder> get() = emptySet()
override val isSearchAvailable get() = true
override suspend fun getPageFullUrl(page: MangaPage) : String = page.url
override suspend fun getTags(): Set<MangaTag> = emptySet()

View File

@@ -6,8 +6,6 @@ interface MangaRepository {
val sortOrders: Set<SortOrder>
val isSearchAvailable: Boolean
suspend fun getList(offset: Int, query: String? = null, sortOrder: SortOrder? = null, tag: MangaTag? = null): List<Manga>
suspend fun getDetails(manga: Manga) : Manga

View File

@@ -25,13 +25,11 @@ abstract class GroupleRepository(
sortOrder: SortOrder?,
tag: MangaTag?
): List<Manga> {
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 ->

View File

@@ -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<MangaLoaderContext>()
private val loaderContext by inject<MangaLoaderContext>()
fun create(source: MangaSource): MangaRepository {
val constructor = source.cls.getConstructor(MangaLoaderContext::class.java)

View File

@@ -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)
}
}

View File

@@ -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()
}
}

View File

@@ -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)
}
}
}

View File

@@ -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)
}
}
}
}

View File

@@ -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)
}
}