diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt index 84980d598..57c887b62 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt @@ -60,6 +60,8 @@ class AppSettings private constructor(resources: Resources, private val prefs: S sourcesOrderStr = value.joinToString("|") } + var hiddenSources by StringSetPreferenceDelegate(resources.getString(R.string.key_sources_hidden)) + fun subscribe(listener: SharedPreferences.OnSharedPreferenceChangeListener) { prefs.registerOnSharedPreferenceChangeListener(listener) } 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 e4272cc5f..3c36c00a9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/domain/MangaProviderFactory.kt +++ b/app/src/main/java/org/koitharu/kotatsu/domain/MangaProviderFactory.kt @@ -9,15 +9,23 @@ import org.koitharu.kotatsu.core.prefs.AppSettings object MangaProviderFactory : KoinComponent { - val sources: List - get() { - val list = MangaSource.values().toList() - MangaSource.LOCAL - val order = get().sourcesOrder - return list.sortedBy { x -> - val e = order.indexOf(x.ordinal) - if (e == -1) order.size + x.ordinal else e + fun getSources(includeHidden: Boolean): List { + val settings = get() + val list = MangaSource.values().toList() - MangaSource.LOCAL + val order = settings.sourcesOrder + val hidden = settings.hiddenSources + val sorted = list.sortedBy { x -> + val e = order.indexOf(x.ordinal) + if (e == -1) order.size + x.ordinal else e + } + return if(includeHidden) { + sorted + } else { + sorted.filterNot { x -> + x.name in hidden } } + } fun createLocal() = LocalMangaRepository() diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/common/widgets/CheckableImageView.kt b/app/src/main/java/org/koitharu/kotatsu/ui/common/widgets/CheckableImageView.kt new file mode 100644 index 000000000..f1a2e46a5 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/ui/common/widgets/CheckableImageView.kt @@ -0,0 +1,67 @@ +package org.koitharu.kotatsu.ui.common.widgets + +import android.content.Context +import android.util.AttributeSet +import android.widget.Checkable +import androidx.appcompat.widget.AppCompatImageView + +class CheckableImageView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : AppCompatImageView(context, attrs, defStyleAttr), Checkable { + + private var isCheckedInternal = false + private var isBroadcasting = false + + var onCheckedChangeListener: OnCheckedChangeListener? = null + + init { + setOnClickListener { + toggle() + } + } + + fun setOnCheckedChangeListener(listener: (Boolean) -> Unit) { + onCheckedChangeListener = object : OnCheckedChangeListener { + override fun onCheckedChanged(view: CheckableImageView, isChecked: Boolean) { + listener(isChecked) + } + } + } + + override fun isChecked() = isCheckedInternal + + override fun toggle() { + isChecked = !isCheckedInternal + } + + override fun setChecked(checked: Boolean) { + if (checked != isCheckedInternal) { + isCheckedInternal = checked + refreshDrawableState() + if (!isBroadcasting) { + isBroadcasting = true + onCheckedChangeListener?.onCheckedChanged(this, checked) + isBroadcasting = false + } + } + } + + override fun onCreateDrawableState(extraSpace: Int): IntArray { + val state = super.onCreateDrawableState(extraSpace + 1) + if (isCheckedInternal) { + mergeDrawableStates(state, CHECKED_STATE_SET) + } + return state + } + + interface OnCheckedChangeListener { + + fun onCheckedChanged(view: CheckableImageView, isChecked: Boolean) + } + + private companion object { + + @JvmStatic + private val CHECKED_STATE_SET = intArrayOf(android.R.attr.state_checked) + } +} \ No newline at end of file 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 2b9e13013..9529d739e 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 @@ -28,8 +28,8 @@ import org.koitharu.kotatsu.ui.main.list.local.LocalListFragment import org.koitharu.kotatsu.ui.main.list.remote.RemoteListFragment import org.koitharu.kotatsu.ui.reader.ReaderActivity import org.koitharu.kotatsu.ui.reader.ReaderState -import org.koitharu.kotatsu.ui.settings.SettingsActivity import org.koitharu.kotatsu.ui.settings.AppUpdateService +import org.koitharu.kotatsu.ui.settings.SettingsActivity import org.koitharu.kotatsu.utils.ext.getDisplayMessage import org.koitharu.kotatsu.utils.ext.resolveDp @@ -79,7 +79,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList override fun onPostCreate(savedInstanceState: Bundle?) { super.onPostCreate(savedInstanceState) drawerToggle.syncState() - initSideMenu(MangaProviderFactory.sources) + initSideMenu(MangaProviderFactory.getSources(includeHidden = false)) } override fun onConfigurationChanged(newConfig: Configuration) { @@ -148,7 +148,10 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { when (key) { - getString(R.string.key_sources_order) -> initSideMenu(MangaProviderFactory.sources) + getString(R.string.key_sources_hidden), + getString(R.string.key_sources_order) -> { + initSideMenu(MangaProviderFactory.getSources(includeHidden = false)) + } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/settings/sources/SourceDividerHolder.kt b/app/src/main/java/org/koitharu/kotatsu/ui/settings/sources/SourceDividerHolder.kt deleted file mode 100644 index b7cd0c58b..000000000 --- a/app/src/main/java/org/koitharu/kotatsu/ui/settings/sources/SourceDividerHolder.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.koitharu.kotatsu.ui.settings.sources - -import android.view.ViewGroup -import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.ui.common.list.BaseViewHolder - -class SourceDividerHolder(parent: ViewGroup) : - BaseViewHolder(parent, R.layout.item_sources_pref_divider) { - - override fun onBind(data: Unit, extra: Unit) = Unit -} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/settings/sources/SourceViewHolder.kt b/app/src/main/java/org/koitharu/kotatsu/ui/settings/sources/SourceViewHolder.kt index 3e706f4d3..4440b2aac 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/settings/sources/SourceViewHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/settings/sources/SourceViewHolder.kt @@ -7,9 +7,10 @@ import org.koitharu.kotatsu.core.model.MangaSource import org.koitharu.kotatsu.ui.common.list.BaseViewHolder class SourceViewHolder(parent: ViewGroup) : - BaseViewHolder(parent, R.layout.item_source_config) { + BaseViewHolder(parent, R.layout.item_source_config) { - override fun onBind(data: MangaSource, extra: Unit) { + override fun onBind(data: MangaSource, extra: Boolean) { textView_title.text = data.title + imageView_hidden.isChecked = extra } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/settings/sources/SourcesAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/settings/sources/SourcesAdapter.kt index 4bd0d343f..11cc7097f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/settings/sources/SourcesAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/settings/sources/SourcesAdapter.kt @@ -6,32 +6,46 @@ import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.item_source_config.* 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.prefs.AppSettings import org.koitharu.kotatsu.domain.MangaProviderFactory -import org.koitharu.kotatsu.ui.common.list.BaseViewHolder import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener +import org.koitharu.kotatsu.utils.ext.safe class SourcesAdapter(private val onItemClickListener: OnRecyclerItemClickListener) : - RecyclerView.Adapter>(), KoinComponent { + RecyclerView.Adapter(), KoinComponent { - private val dataSet = MangaProviderFactory.sources.toMutableList() + private val dataSet = MangaProviderFactory.getSources(includeHidden = true).toMutableList() + private val settings by inject() + private val hiddenItems = settings.hiddenSources.mapNotNull { + safe { + MangaSource.valueOf(it) + } + }.toMutableSet() - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = when (viewType) { - ITEM_SOURCE -> SourceViewHolder(parent).also(::onViewHolderCreated) - ITEM_DIVIDER -> SourceDividerHolder(parent) - else -> throw IllegalArgumentException("Unsupported viewType $viewType") - } + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int + ) = SourceViewHolder(parent).also(::onViewHolderCreated) override fun getItemCount() = dataSet.size - override fun onBindViewHolder(holder: BaseViewHolder<*, Unit>, position: Int) { - (holder as? SourceViewHolder)?.bind(dataSet[position], Unit) + override fun onBindViewHolder(holder: SourceViewHolder, position: Int) { + val item = dataSet[position] + holder.bind(item, !hiddenItems.contains(item)) } @SuppressLint("ClickableViewAccessibility") private fun onViewHolderCreated(holder: SourceViewHolder) { + holder.imageView_hidden.setOnCheckedChangeListener { + if (it) { + hiddenItems.remove(holder.requireData()) + } else { + hiddenItems.add(holder.requireData()) + } + settings.hiddenSources = hiddenItems.map { x -> x.name }.toSet() + } holder.imageView_config.setOnClickListener { v -> onItemClickListener.onItemClick(holder.requireData(), holder.adapterPosition, v) } @@ -48,12 +62,6 @@ class SourcesAdapter(private val onItemClickListener: OnRecyclerItemClickListene val item = dataSet.removeAt(oldPos) dataSet.add(newPos, item) notifyItemMoved(oldPos, newPos) - get().sourcesOrder = dataSet.map { it.ordinal } - } - - companion object { - - const val ITEM_SOURCE = 0 - const val ITEM_DIVIDER = 1 + settings.sourcesOrder = dataSet.map { it.ordinal } } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/delegates/prefs/StringSetPreferenceDelegate.kt b/app/src/main/java/org/koitharu/kotatsu/utils/delegates/prefs/StringSetPreferenceDelegate.kt index df4af5aca..79adf259c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/delegates/prefs/StringSetPreferenceDelegate.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/delegates/prefs/StringSetPreferenceDelegate.kt @@ -5,7 +5,7 @@ import androidx.core.content.edit import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty -class StringSetPreferenceDelegate(private val key: String, private val defValue: Set) : +class StringSetPreferenceDelegate(private val key: String, private val defValue: Set = emptySet()) : ReadWriteProperty> { override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): Set { diff --git a/app/src/main/res/drawable/ic_eye.xml b/app/src/main/res/drawable/ic_eye.xml new file mode 100644 index 000000000..52e210215 --- /dev/null +++ b/app/src/main/res/drawable/ic_eye.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_eye_checkable.xml b/app/src/main/res/drawable/ic_eye_checkable.xml new file mode 100644 index 000000000..7f35e1761 --- /dev/null +++ b/app/src/main/res/drawable/ic_eye_checkable.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_eye_off.xml b/app/src/main/res/drawable/ic_eye_off.xml new file mode 100644 index 000000000..e558a36c4 --- /dev/null +++ b/app/src/main/res/drawable/ic_eye_off.xml @@ -0,0 +1,13 @@ + + + + \ 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 8397effaf..c3c7d37bb 100644 --- a/app/src/main/res/layout/item_source_config.xml +++ b/app/src/main/res/layout/item_source_config.xml @@ -28,6 +28,15 @@ android:textColor="?android:attr/textColorPrimary" tools:text="@tools:sample/lorem[1]" /> + + list_mode theme sources_order + sources_hidden traffic_warning pages_cache_clear thumbs_cache_clear