diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 50907769f..4e3b89737 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -14,10 +14,10 @@
android:fullBackupContent="@xml/backup_descriptor"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
- android:usesCleartextTraffic="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
- android:theme="@style/AppTheme">
+ android:theme="@style/AppTheme"
+ android:usesCleartextTraffic="true">
@@ -29,14 +29,9 @@
-
-
-
-
-
-
+
@@ -44,7 +39,7 @@
() {
@@ -25,6 +29,14 @@ class RemoteListFragment : MangaListFragment() {
super.onFilterChanged(filter)
}
+ override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+ inflater.inflate(R.menu.opt_remote, menu)
+ menu.findItem(R.id.action_search)?.let { menuItem ->
+ SearchHelper.setupSearchView(menuItem, source)
+ }
+ super.onCreateOptionsMenu(menu, inflater)
+ }
+
companion object {
private const val ARG_SOURCE = "provider"
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/search/MangaSuggestionsProvider.kt b/app/src/main/java/org/koitharu/kotatsu/ui/search/MangaSuggestionsProvider.kt
new file mode 100644
index 000000000..5d1bd3ca9
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/search/MangaSuggestionsProvider.kt
@@ -0,0 +1,91 @@
+package org.koitharu.kotatsu.ui.search
+
+import android.app.SearchManager
+import android.content.ContentResolver
+import android.content.Context
+import android.content.SearchRecentSuggestionsProvider
+import android.database.Cursor
+import android.net.Uri
+import android.provider.SearchRecentSuggestions
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.cursoradapter.widget.CursorAdapter
+import org.koitharu.kotatsu.BuildConfig
+import org.koitharu.kotatsu.R
+
+class MangaSuggestionsProvider : SearchRecentSuggestionsProvider() {
+
+ init {
+ setupSuggestions(
+ AUTHORITY,
+ MODE
+ )
+ }
+
+ private class SearchSuggestionAdapter(context: Context, cursor: Cursor) : CursorAdapter(
+ context, cursor,
+ FLAG_REGISTER_CONTENT_OBSERVER
+ ) {
+
+ override fun newView(context: Context, cursor: Cursor?, parent: ViewGroup?): View {
+ return LayoutInflater.from(context)
+ .inflate(R.layout.item_search_complete, parent, false)
+ }
+
+ override fun bindView(view: View, context: Context, cursor: Cursor) {
+ if (view !is TextView) return
+ view.text = cursor.getString(cursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_QUERY))
+ }
+
+ override fun convertToString(cursor: Cursor?): CharSequence {
+ return cursor?.getString(cursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_QUERY))
+ .orEmpty()
+ }
+ }
+
+ companion object {
+
+ private const val AUTHORITY = "${BuildConfig.APPLICATION_ID}.MangaSuggestionsProvider"
+ private const val MODE = DATABASE_MODE_QUERIES
+
+ private val uri = Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(AUTHORITY)
+ .appendPath(SearchManager.SUGGEST_URI_PATH_QUERY)
+ .build()
+ private val projection = arrayOf("_id", SearchManager.SUGGEST_COLUMN_QUERY)
+
+ fun saveQuery(context: Context, query: String) {
+ SearchRecentSuggestions(
+ context,
+ AUTHORITY,
+ MODE
+ ).saveRecentQuery(query, null)
+ }
+
+ fun clearHistory(context: Context) {
+ SearchRecentSuggestions(
+ context,
+ AUTHORITY,
+ MODE
+ ).clearHistory()
+ }
+
+ private fun getCursor(context: Context): Cursor? {
+ return context.contentResolver?.query(uri, projection, null, arrayOf(""), null)
+ }
+
+ fun getSuggestionAdapter(context: Context): CursorAdapter? = getCursor(
+ context
+ )?.let { cursor ->
+ SearchSuggestionAdapter(context, cursor).also {
+ it.setFilterQueryProvider { q ->
+ context.contentResolver?.query(uri, projection, " ?", arrayOf(q.toString()), null)
+ }
+ }
+ }
+
+ }
+}
\ No newline at end of file
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
index 13ca3dc9d..89035096e 100644
--- a/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchActivity.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchActivity.kt
@@ -1,10 +1,11 @@
package org.koitharu.kotatsu.ui.search
-import android.app.SearchManager
+import android.content.Context
import android.content.Intent
import android.os.Bundle
+import android.os.Parcelable
import org.koitharu.kotatsu.R
-import org.koitharu.kotatsu.domain.search.MangaSuggestionsProvider
+import org.koitharu.kotatsu.core.model.MangaSource
import org.koitharu.kotatsu.ui.common.BaseActivity
class SearchActivity : BaseActivity() {
@@ -12,22 +13,31 @@ 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) {
+ val source = intent.getParcelableExtra(EXTRA_SOURCE)
+ val query = intent.getStringExtra(EXTRA_QUERY)
+
+ if (source == null || query == null) {
finish()
return
}
- MangaSuggestionsProvider.saveQuery(this, query)
+
supportActionBar?.setDisplayHomeAsUpEnabled(true)
title = query
supportActionBar?.setSubtitle(R.string.search_results)
supportFragmentManager
.beginTransaction()
- .replace(R.id.container, SearchFragment.newInstance(query))
+ .replace(R.id.container, SearchFragment.newInstance(source, query))
.commit()
}
+
+ companion object {
+
+ private const val EXTRA_SOURCE = "source"
+ private const val EXTRA_QUERY = "query"
+
+ fun newIntent(context: Context, source: MangaSource, query: String) =
+ Intent(context, SearchActivity::class.java)
+ .putExtra(EXTRA_SOURCE, source as Parcelable)
+ .putExtra(EXTRA_QUERY, query)
+ }
}
\ 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
index fd17b41cd..0cf073fc1 100644
--- a/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchFragment.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchFragment.kt
@@ -1,6 +1,7 @@
package org.koitharu.kotatsu.ui.search
import moxy.ktx.moxyPresenter
+import org.koitharu.kotatsu.core.model.MangaSource
import org.koitharu.kotatsu.ui.main.list.MangaListFragment
import org.koitharu.kotatsu.utils.ext.withArgs
@@ -9,9 +10,10 @@ class SearchFragment : MangaListFragment() {
private val presenter by moxyPresenter(factory = ::SearchPresenter)
private val query by stringArg(ARG_QUERY)
+ private val source by arg(ARG_SOURCE)
override fun onRequestMoreItems(offset: Int) {
- presenter.loadList(query.orEmpty(), offset)
+ presenter.loadList(source, query.orEmpty(), offset)
}
override fun getTitle(): CharSequence? {
@@ -21,8 +23,10 @@ class SearchFragment : MangaListFragment() {
companion object {
private const val ARG_QUERY = "query"
+ private const val ARG_SOURCE = "source"
- fun newInstance(query: String) = SearchFragment().withArgs(1) {
+ fun newInstance(source: MangaSource, query: String) = SearchFragment().withArgs(2) {
+ putParcelable(ARG_SOURCE, source)
putString(ARG_QUERY, query)
}
}
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchHelper.kt b/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchHelper.kt
new file mode 100644
index 000000000..1adbf694b
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchHelper.kt
@@ -0,0 +1,55 @@
+package org.koitharu.kotatsu.ui.search
+
+import android.app.SearchManager
+import android.content.Context
+import android.database.Cursor
+import android.view.MenuItem
+import android.view.inputmethod.EditorInfo
+import androidx.appcompat.widget.SearchView
+import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.core.model.MangaSource
+import org.koitharu.kotatsu.utils.ext.safe
+
+object SearchHelper {
+
+ @JvmStatic
+ fun setupSearchView(menuItem: MenuItem, source: MangaSource) {
+ val view = menuItem.actionView as? SearchView ?: return
+ val context = view.context
+ view.queryHint = context.getString(R.string.search_manga)
+ view.imeOptions = EditorInfo.IME_ACTION_SEARCH
+ view.inputType = EditorInfo.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE
+ view.suggestionsAdapter = MangaSuggestionsProvider.getSuggestionAdapter(context)
+ view.setOnQueryTextListener(QueryListener(context, source))
+ view.setOnSuggestionListener(SuggestionListener(view))
+ }
+
+ private class QueryListener(private val context: Context, private val source: MangaSource) :
+ SearchView.OnQueryTextListener {
+
+ override fun onQueryTextSubmit(query: String?): Boolean {
+ return if (!query.isNullOrBlank()) {
+ context.startActivity(SearchActivity.newIntent(context, source, query.trim()))
+ MangaSuggestionsProvider.saveQuery(context, query)
+ true
+ } else false
+ }
+
+ override fun onQueryTextChange(newText: String?) = false
+ }
+
+ private class SuggestionListener(private val view: SearchView) :
+ SearchView.OnSuggestionListener {
+
+ override fun onSuggestionSelect(position: Int) = false
+
+ override fun onSuggestionClick(position: Int): Boolean {
+ val query = safe {
+ val c = view.suggestionsAdapter.getItem(position) as? Cursor
+ c?.getString(c.getColumnIndex(SearchManager.SUGGEST_COLUMN_QUERY))
+ } ?: return false
+ view.setQuery(query, true)
+ return true
+ }
+ }
+}
\ 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
index b9db5ca6d..84abd7ddb 100644
--- a/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchPresenter.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/search/SearchPresenter.kt
@@ -21,13 +21,12 @@ class SearchPresenter : BasePresenter>() {
super.onFirstViewAttach()
}
- fun loadList(query: String, offset: Int) {
+ fun loadList(source: MangaSource, query: String, offset: Int) {
presenterScope.launch {
viewState.onLoadingChanged(true)
try {
- //TODO select source
val list = withContext(Dispatchers.IO) {
- MangaProviderFactory.create(MangaSource.READMANGA_RU)
+ MangaProviderFactory.create(source)
.getList(offset, query = query)
}
if (offset == 0) {
diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/SearchHelper.kt b/app/src/main/java/org/koitharu/kotatsu/utils/SearchHelper.kt
deleted file mode 100644
index 8d7c928fa..000000000
--- a/app/src/main/java/org/koitharu/kotatsu/utils/SearchHelper.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-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
- 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_details.xml b/app/src/main/res/layout/activity_details.xml
index c76924fe0..caa3f66b1 100644
--- a/app/src/main/res/layout/activity_details.xml
+++ b/app/src/main/res/layout/activity_details.xml
@@ -10,7 +10,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?colorPrimary"
- android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar">
+ android:theme="@style/AppToolbarTheme">
+ android:theme="@style/AppToolbarTheme">
+ app:layout_scrollFlags="scroll|enterAlways" />
diff --git a/app/src/main/res/layout/activity_reader.xml b/app/src/main/res/layout/activity_reader.xml
index 07dcb89ab..16201aeeb 100644
--- a/app/src/main/res/layout/activity_reader.xml
+++ b/app/src/main/res/layout/activity_reader.xml
@@ -28,7 +28,7 @@
android:background="@color/dim"
android:elevation="0dp"
android:fitsSystemWindows="true"
- android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar"
+ android:theme="@style/AppToolbarTheme"
app:elevation="0dp">
+ android:theme="@style/AppToolbarTheme">
+ android:theme="@style/AppToolbarTheme">
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/opt_main.xml b/app/src/main/res/menu/opt_main.xml
index 15f6118e3..b730bac92 100644
--- a/app/src/main/res/menu/opt_main.xml
+++ b/app/src/main/res/menu/opt_main.xml
@@ -3,12 +3,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
-
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/opt_remote.xml b/app/src/main/res/menu/opt_remote.xml
new file mode 100644
index 000000000..82a1adbcc
--- /dev/null
+++ b/app/src/main/res/menu/opt_remote.xml
@@ -0,0 +1,14 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml
index 050fe5805..65256236f 100644
--- a/app/src/main/res/values-night/styles.xml
+++ b/app/src/main/res/values-night/styles.xml
@@ -1,4 +1,8 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 3bd21339b..fa6c6d0a4 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -10,4 +10,13 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/search.xml b/app/src/main/res/xml/search.xml
deleted file mode 100644
index df926a5b3..000000000
--- a/app/src/main/res/xml/search.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-