Option to hide manga source
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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 }
|
||||
}
|
||||
}
|
||||
@@ -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> {
|
||||
|
||||
12
app/src/main/res/drawable/ic_eye.xml
Normal file
12
app/src/main/res/drawable/ic_eye.xml
Normal 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>
|
||||
7
app/src/main/res/drawable/ic_eye_checkable.xml
Normal file
7
app/src/main/res/drawable/ic_eye_checkable.xml
Normal 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>
|
||||
13
app/src/main/res/drawable/ic_eye_off.xml
Normal file
13
app/src/main/res/drawable/ic_eye_off.xml
Normal 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>
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user