diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesSettingsFragment.kt index 443077ce8..dd9c4235a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesSettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesSettingsFragment.kt @@ -1,9 +1,8 @@ package org.koitharu.kotatsu.settings.sources import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup +import android.view.* +import androidx.appcompat.widget.SearchView import androidx.core.graphics.Insets import androidx.core.view.updatePadding import androidx.recyclerview.widget.ItemTouchHelper @@ -20,7 +19,7 @@ import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigListener import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem class SourcesSettingsFragment : BaseFragment(), - SourceConfigListener { + SourceConfigListener, SearchView.OnQueryTextListener, MenuItem.OnActionExpandListener { private var reorderHelper: ItemTouchHelper? = null private val viewModel by viewModel() @@ -61,6 +60,17 @@ class SourcesSettingsFragment : BaseFragment(), super.onDestroyView() } + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + super.onCreateOptionsMenu(menu, inflater) + inflater.inflate(R.menu.opt_sources, menu) + val searchMenuItem = menu.findItem(R.id.action_search) + searchMenuItem.setOnActionExpandListener(this) + val searchView = searchMenuItem.actionView as SearchView + searchView.setOnQueryTextListener(this) + searchView.setIconifiedByDefault(false) + searchView.queryHint = searchMenuItem.title + } + override fun onWindowInsetsChanged(insets: Insets) { binding.recyclerView.updatePadding( bottom = insets.bottom, @@ -85,6 +95,20 @@ class SourcesSettingsFragment : BaseFragment(), viewModel.expandOrCollapse(header.localeId) } + override fun onQueryTextSubmit(query: String?): Boolean = false + + override fun onQueryTextChange(newText: String?): Boolean { + viewModel.performSearch(newText) + return true + } + + override fun onMenuItemActionExpand(item: MenuItem?): Boolean = true + + override fun onMenuItemActionCollapse(item: MenuItem): Boolean { + (item.actionView as SearchView).setQuery("", false) + return true + } + private inner class SourcesReorderCallback : ItemTouchHelper.SimpleCallback( ItemTouchHelper.DOWN or ItemTouchHelper.UP, 0, diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesSettingsViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesSettingsViewModel.kt index 1bff594c9..a908ccf4e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesSettingsViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesSettingsViewModel.kt @@ -21,6 +21,7 @@ class SourcesSettingsViewModel( val items = MutableLiveData>(emptyList()) private val expandedGroups = HashSet() + private var searchQuery: String? = null init { buildList() @@ -63,9 +64,30 @@ class SourcesSettingsViewModel( buildList() } + fun performSearch(query: String?) { + searchQuery = query?.trim() + buildList() + } + private fun buildList() { val sources = MangaProviderFactory.getSources(settings, includeHidden = true) val hiddenSources = settings.hiddenSources + val query = searchQuery + if (!query.isNullOrEmpty()) { + items.value = sources.mapNotNull { + if (!it.title.contains(query, ignoreCase = true)) { + return@mapNotNull null + } + SourceConfigItem.SourceItem( + source = it, + isEnabled = it.name !in hiddenSources, + isDraggable = false, + ) + }.ifEmpty { + listOf(SourceConfigItem.EmptySearchResult) + } + return + } val map = sources.groupByTo(TreeMap(LocaleKeyComparator())) { if (it.name !in hiddenSources) { KEY_ENABLED diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapter.kt index 79cab4f39..d580684be 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapter.kt @@ -15,4 +15,5 @@ class SourceConfigAdapter( sourceConfigGroupDelegate(listener), sourceConfigItemDelegate(listener, coil, lifecycleOwner), sourceConfigDraggableItemDelegate(listener), + sourceConfigEmptySearchDelegate(), ) \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt index df2b734b9..aa8c9fb35 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt @@ -4,12 +4,11 @@ import android.annotation.SuppressLint import android.view.MotionEvent import android.view.View import android.widget.CompoundButton -import androidx.core.view.isVisible -import androidx.core.view.updatePaddingRelative import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import coil.request.Disposable import coil.request.ImageRequest +import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegate import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R import org.koitharu.kotatsu.databinding.ItemExpandableBinding @@ -53,25 +52,15 @@ fun sourceConfigItemDelegate( on = { item, _, _ -> item is SourceConfigItem.SourceItem && !item.isDraggable } ) { - val eventListener = object : View.OnClickListener, CompoundButton.OnCheckedChangeListener { - override fun onClick(v: View?) = listener.onItemSettingsClick(item) - - override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) { - listener.onItemEnabledChanged(item, isChecked) - } - } var imageRequest: Disposable? = null - binding.imageViewConfig.setOnClickListener(eventListener) - binding.switchToggle.setOnCheckedChangeListener(eventListener) + binding.switchToggle.setOnCheckedChangeListener { _, isChecked -> + listener.onItemEnabledChanged(item, isChecked) + } bind { binding.textViewTitle.text = item.source.title binding.switchToggle.isChecked = item.isEnabled - binding.imageViewConfig.isVisible = item.isEnabled - binding.root.updatePaddingRelative( - end = if (item.isEnabled) 0 else binding.imageViewConfig.paddingEnd, - ) imageRequest = ImageRequest.Builder(context) .data(item.faviconUrl) .error(R.drawable.ic_favicon_fallback) @@ -119,9 +108,9 @@ fun sourceConfigDraggableItemDelegate( bind { binding.textViewTitle.text = item.source.title binding.switchToggle.isChecked = item.isEnabled - binding.imageViewConfig.isVisible = item.isEnabled - binding.root.updatePaddingRelative( - end = if (item.isEnabled) 0 else binding.imageViewConfig.paddingEnd, - ) } -} \ No newline at end of file +} + +fun sourceConfigEmptySearchDelegate() = adapterDelegate( + R.layout.item_sources_empty +) { } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigDiffCallback.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigDiffCallback.kt index 370cca88d..8bab50c2a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigDiffCallback.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigDiffCallback.kt @@ -2,21 +2,25 @@ package org.koitharu.kotatsu.settings.sources.adapter import androidx.recyclerview.widget.DiffUtil import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem +import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem.* class SourceConfigDiffCallback : DiffUtil.ItemCallback() { override fun areItemsTheSame(oldItem: SourceConfigItem, newItem: SourceConfigItem): Boolean { return when { oldItem.javaClass != newItem.javaClass -> false - oldItem is SourceConfigItem.LocaleGroup && newItem is SourceConfigItem.LocaleGroup -> { + oldItem is LocaleGroup && newItem is LocaleGroup -> { oldItem.localeId == newItem.localeId } - oldItem is SourceConfigItem.SourceItem && newItem is SourceConfigItem.SourceItem -> { + oldItem is SourceItem && newItem is SourceItem -> { oldItem.source == newItem.source } - oldItem is SourceConfigItem.Header && newItem is SourceConfigItem.Header -> { + oldItem is Header && newItem is Header -> { oldItem.titleResId == newItem.titleResId } + oldItem == EmptySearchResult && newItem == EmptySearchResult -> { + true + } else -> false } } diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/model/SourceConfigItem.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/model/SourceConfigItem.kt index a3e398a03..dd998ddac 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/model/SourceConfigItem.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/model/SourceConfigItem.kt @@ -76,4 +76,6 @@ sealed interface SourceConfigItem { return result } } + + object EmptySearchResult : SourceConfigItem } \ No newline at end of file diff --git a/app/src/main/res/layout/item_source_config.xml b/app/src/main/res/layout/item_source_config.xml index 2d225fea2..a13432590 100644 --- a/app/src/main/res/layout/item_source_config.xml +++ b/app/src/main/res/layout/item_source_config.xml @@ -4,7 +4,6 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="?android:listPreferredItemHeightSmall" - android:background="?android:windowBackground" android:gravity="center_vertical" android:orientation="horizontal"> @@ -14,7 +13,7 @@ android:layout_height="?android:listPreferredItemHeightSmall" android:layout_marginHorizontal="?listPreferredItemPaddingStart" android:labelFor="@id/textView_title" - android:padding="6dp" + android:padding="8dp" android:scaleType="fitCenter" tools:src="@tools:sample/avatars" /> @@ -33,16 +32,7 @@ - - + android:layout_height="wrap_content" + android:layout_marginEnd="?listPreferredItemPaddingEnd" /> \ No newline at end of file diff --git a/app/src/main/res/layout/item_sources_empty.xml b/app/src/main/res/layout/item_sources_empty.xml new file mode 100644 index 000000000..3aad1bbe4 --- /dev/null +++ b/app/src/main/res/layout/item_sources_empty.xml @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/app/src/main/res/menu/opt_sources.xml b/app/src/main/res/menu/opt_sources.xml index 35c7034be..5128fbe66 100644 --- a/app/src/main/res/menu/opt_sources.xml +++ b/app/src/main/res/menu/opt_sources.xml @@ -4,9 +4,10 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> + android:id="@+id/action_search" + android:icon="@drawable/ic_search" + android:title="@string/search" + app:actionViewClass="androidx.appcompat.widget.SearchView" + app:showAsAction="ifRoom|collapseActionView" /> \ No newline at end of file