Option to hide manga source

This commit is contained in:
Koitharu
2020-03-19 16:52:16 +02:00
parent db0ee268f9
commit 418d0247f5
13 changed files with 162 additions and 42 deletions

View File

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

View File

@@ -9,15 +9,23 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
object MangaProviderFactory : KoinComponent {
val sources: List<MangaSource>
get() {
val list = MangaSource.values().toList() - MangaSource.LOCAL
val order = get<AppSettings>().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<MangaSource> {
val settings = get<AppSettings>()
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()

View File

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

View File

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

View File

@@ -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<Unit, Unit>(parent, R.layout.item_sources_pref_divider) {
override fun onBind(data: Unit, extra: Unit) = Unit
}

View File

@@ -7,9 +7,10 @@ import org.koitharu.kotatsu.core.model.MangaSource
import org.koitharu.kotatsu.ui.common.list.BaseViewHolder
class SourceViewHolder(parent: ViewGroup) :
BaseViewHolder<MangaSource, Unit>(parent, R.layout.item_source_config) {
BaseViewHolder<MangaSource, Boolean>(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
}
}

View File

@@ -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<MangaSource>) :
RecyclerView.Adapter<BaseViewHolder<*, Unit>>(), KoinComponent {
RecyclerView.Adapter<SourceViewHolder>(), KoinComponent {
private val dataSet = MangaProviderFactory.sources.toMutableList()
private val dataSet = MangaProviderFactory.getSources(includeHidden = true).toMutableList()
private val settings by inject<AppSettings>()
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<AppSettings>().sourcesOrder = dataSet.map { it.ordinal }
}
companion object {
const val ITEM_SOURCE = 0
const val ITEM_DIVIDER = 1
settings.sourcesOrder = dataSet.map { it.ordinal }
}
}

View File

@@ -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<String>) :
class StringSetPreferenceDelegate(private val key: String, private val defValue: Set<String> = emptySet()) :
ReadWriteProperty<SharedPreferences, Set<String>> {
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): Set<String> {

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000"
android:pathData="M12,9A3,3 0 0,1 15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9M12,4.5C17,4.5 21.27,7.61 23,12C21.27,16.39 17,19.5 12,19.5C7,19.5 2.73,16.39 1,12C2.73,7.61 7,4.5 12,4.5M3.18,12C4.83,15.36 8.24,17.5 12,17.5C15.76,17.5 19.17,15.36 20.82,12C19.17,8.64 15.76,6.5 12,6.5C8.24,6.5 4.83,8.64 3.18,12Z" />
</vector>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:enterFadeDuration="@android:integer/config_mediumAnimTime"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:drawable="@drawable/ic_eye" android:state_checked="true" />
<item android:drawable="@drawable/ic_eye_off" android:state_checked="false" />
</selector>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000"
android:fillAlpha="0.3"
android:pathData="M2,5.27L3.28,4L20,20.72L18.73,22L15.65,18.92C14.5,19.3 13.28,19.5 12,19.5C7,19.5 2.73,16.39 1,12C1.69,10.24 2.79,8.69 4.19,7.46L2,5.27M12,9A3,3 0 0,1 15,12C15,12.35 14.94,12.69 14.83,13L11,9.17C11.31,9.06 11.65,9 12,9M12,4.5C17,4.5 21.27,7.61 23,12C22.18,14.08 20.79,15.88 19,17.19L17.58,15.76C18.94,14.82 20.06,13.54 20.82,12C19.17,8.64 15.76,6.5 12,6.5C10.91,6.5 9.84,6.68 8.84,7L7.3,5.47C8.74,4.85 10.33,4.5 12,4.5M3.18,12C4.83,15.36 8.24,17.5 12,17.5C12.69,17.5 13.37,17.43 14,17.29L11.72,15C10.29,14.85 9.15,13.71 9,12.28L5.6,8.87C4.61,9.72 3.78,10.78 3.18,12Z" />
</vector>

View File

@@ -28,6 +28,15 @@
android:textColor="?android:attr/textColorPrimary"
tools:text="@tools:sample/lorem[1]" />
<org.koitharu.kotatsu.ui.common.widgets.CheckableImageView
android:id="@+id/imageView_hidden"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:padding="?listPreferredItemPaddingEnd"
android:scaleType="center"
android:src="@drawable/ic_eye_checkable" />
<ImageView
android:id="@+id/imageView_config"
android:layout_width="wrap_content"

View File

@@ -3,6 +3,7 @@
<string name="key_list_mode">list_mode</string>
<string name="key_theme">theme</string>
<string name="key_sources_order">sources_order</string>
<string name="key_sources_hidden">sources_hidden</string>
<string name="key_traffic_warning">traffic_warning</string>
<string name="key_pages_cache_clear">pages_cache_clear</string>
<string name="key_thumbs_cache_clear">thumbs_cache_clear</string>