Option to enable all sources
This commit is contained in:
@@ -2,6 +2,7 @@ package org.koitharu.kotatsu.core.db.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
import org.koitharu.kotatsu.core.db.entity.ChapterEntity
|
||||
@@ -24,6 +25,6 @@ abstract class ChaptersDao {
|
||||
insert(entities)
|
||||
}
|
||||
|
||||
@Insert
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
protected abstract suspend fun insert(entities: Collection<ChapterEntity>)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import androidx.room.Upsert
|
||||
import androidx.sqlite.db.SimpleSQLiteQuery
|
||||
import androidx.sqlite.db.SupportSQLiteQuery
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.intellij.lang.annotations.Language
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaSourceEntity
|
||||
import org.koitharu.kotatsu.explore.data.SourcesSortOrder
|
||||
@@ -61,21 +60,11 @@ abstract class MangaSourcesDao {
|
||||
@Query("SELECT * FROM sources WHERE pinned = 1")
|
||||
abstract suspend fun findAllPinned(): List<MangaSourceEntity>
|
||||
|
||||
fun observeEnabled(order: SourcesSortOrder): Flow<List<MangaSourceEntity>> {
|
||||
val orderBy = getOrderBy(order)
|
||||
fun observeAll(enabledOnly: Boolean, order: SourcesSortOrder): Flow<List<MangaSourceEntity>> =
|
||||
observeImpl(getQuery(enabledOnly, order))
|
||||
|
||||
@Language("RoomSql")
|
||||
val query = SimpleSQLiteQuery("SELECT * FROM sources WHERE enabled = 1 ORDER BY pinned DESC, $orderBy")
|
||||
return observeImpl(query)
|
||||
}
|
||||
|
||||
suspend fun findAllEnabled(order: SourcesSortOrder): List<MangaSourceEntity> {
|
||||
val orderBy = getOrderBy(order)
|
||||
|
||||
@Language("RoomSql")
|
||||
val query = SimpleSQLiteQuery("SELECT * FROM sources WHERE enabled = 1 ORDER BY pinned DESC, $orderBy")
|
||||
return findAllImpl(query)
|
||||
}
|
||||
suspend fun findAll(enabledOnly: Boolean, order: SourcesSortOrder): List<MangaSourceEntity> =
|
||||
findAllImpl(getQuery(enabledOnly, order))
|
||||
|
||||
@Transaction
|
||||
open suspend fun setEnabled(source: String, isEnabled: Boolean) {
|
||||
@@ -101,6 +90,17 @@ abstract class MangaSourcesDao {
|
||||
@RawQuery
|
||||
protected abstract suspend fun findAllImpl(query: SupportSQLiteQuery): List<MangaSourceEntity>
|
||||
|
||||
private fun getQuery(enabledOnly: Boolean, order: SourcesSortOrder) = SimpleSQLiteQuery(
|
||||
buildString {
|
||||
append("SELECT * FROM sources ")
|
||||
if (enabledOnly) {
|
||||
append("WHERE enabled = 1 ")
|
||||
}
|
||||
append("ORDER BY pinned DESC, ")
|
||||
append(getOrderBy(order))
|
||||
},
|
||||
)
|
||||
|
||||
private fun getOrderBy(order: SourcesSortOrder) = when (order) {
|
||||
SourcesSortOrder.ALPHABETIC -> "source ASC"
|
||||
SourcesSortOrder.POPULARITY -> "(SELECT COUNT(*) FROM manga WHERE source = sources.source) DESC"
|
||||
|
||||
@@ -299,6 +299,10 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
||||
get() = prefs.getInt(KEY_SOURCES_VERSION, 0)
|
||||
set(value) = prefs.edit { putInt(KEY_SOURCES_VERSION, value) }
|
||||
|
||||
var isAllSourcesEnabled: Boolean
|
||||
get() = prefs.getBoolean(KEY_SOURCES_ENABLED_ALL, false)
|
||||
set(value) = prefs.edit { putBoolean(KEY_SOURCES_ENABLED_ALL, value) }
|
||||
|
||||
val isPagesNumbersEnabled: Boolean
|
||||
get() = prefs.getBoolean(KEY_PAGES_NUMBERS, false)
|
||||
|
||||
@@ -717,6 +721,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
||||
const val KEY_FEED_HEADER = "feed_header"
|
||||
const val KEY_SEARCH_SUGGESTION_TYPES = "search_suggest_types"
|
||||
const val KEY_SOURCES_VERSION = "sources_version"
|
||||
const val KEY_SOURCES_ENABLED_ALL = "sources_enabled_all"
|
||||
const val KEY_QUICK_FILTER = "quick_filter"
|
||||
const val KEY_BACKUP_TG_ENABLED = "backup_periodic_tg_enabled"
|
||||
const val KEY_BACKUP_TG_CHAT = "backup_periodic_tg_chat_id"
|
||||
|
||||
@@ -14,6 +14,7 @@ import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
@@ -61,13 +62,14 @@ class MangaSourcesRepository @Inject constructor(
|
||||
suspend fun getEnabledSources(): List<MangaSource> {
|
||||
assimilateNewSources()
|
||||
val order = settings.sourcesSortOrder
|
||||
return dao.findAllEnabled(order).toSources(settings.isNsfwContentDisabled, order).let { enabled ->
|
||||
val external = getExternalSources()
|
||||
val list = ArrayList<MangaSourceInfo>(enabled.size + external.size)
|
||||
external.mapTo(list) { MangaSourceInfo(it, isEnabled = true, isPinned = true) }
|
||||
list.addAll(enabled)
|
||||
list
|
||||
}
|
||||
return dao.findAll(!settings.isAllSourcesEnabled, order).toSources(settings.isNsfwContentDisabled, order)
|
||||
.let { enabled ->
|
||||
val external = getExternalSources()
|
||||
val list = ArrayList<MangaSourceInfo>(enabled.size + external.size)
|
||||
external.mapTo(list) { MangaSourceInfo(it, isEnabled = true, isPinned = true) }
|
||||
list.addAll(enabled)
|
||||
list
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getPinnedSources(): Set<MangaSource> {
|
||||
@@ -85,6 +87,9 @@ class MangaSourcesRepository @Inject constructor(
|
||||
|
||||
suspend fun getDisabledSources(): Set<MangaSource> {
|
||||
assimilateNewSources()
|
||||
if (settings.isAllSourcesEnabled) {
|
||||
return emptySet()
|
||||
}
|
||||
val result = EnumSet.copyOf(allMangaSources)
|
||||
val enabled = dao.findAllEnabledNames()
|
||||
for (name in enabled) {
|
||||
@@ -105,7 +110,7 @@ class MangaSourcesRepository @Inject constructor(
|
||||
): List<MangaParserSource> {
|
||||
assimilateNewSources()
|
||||
val entities = dao.findAll().toMutableList()
|
||||
if (isDisabledOnly) {
|
||||
if (isDisabledOnly && !settings.isAllSourcesEnabled) {
|
||||
entities.removeAll { it.isEnabled }
|
||||
}
|
||||
if (isNewOnly) {
|
||||
@@ -141,7 +146,9 @@ class MangaSourcesRepository @Inject constructor(
|
||||
fun observeEnabledSourcesCount(): Flow<Int> {
|
||||
return combine(
|
||||
observeIsNsfwDisabled(),
|
||||
dao.observeEnabled(SourcesSortOrder.MANUAL),
|
||||
observeAllEnabled().flatMapLatest { isAllSourcesEnabled ->
|
||||
dao.observeAll(!isAllSourcesEnabled, SourcesSortOrder.MANUAL)
|
||||
},
|
||||
) { skipNsfw, sources ->
|
||||
sources.count {
|
||||
it.source.toMangaSourceOrNull()?.let { s -> !skipNsfw || !s.isNsfw() } == true
|
||||
@@ -152,7 +159,9 @@ class MangaSourcesRepository @Inject constructor(
|
||||
fun observeAvailableSourcesCount(): Flow<Int> {
|
||||
return combine(
|
||||
observeIsNsfwDisabled(),
|
||||
dao.observeEnabled(SourcesSortOrder.MANUAL),
|
||||
observeAllEnabled().flatMapLatest { isAllSourcesEnabled ->
|
||||
dao.observeAll(!isAllSourcesEnabled, SourcesSortOrder.MANUAL)
|
||||
},
|
||||
) { skipNsfw, enabledSources ->
|
||||
val enabled = enabledSources.mapToSet { it.source }
|
||||
allMangaSources.count { x ->
|
||||
@@ -163,9 +172,10 @@ class MangaSourcesRepository @Inject constructor(
|
||||
|
||||
fun observeEnabledSources(): Flow<List<MangaSourceInfo>> = combine(
|
||||
observeIsNsfwDisabled(),
|
||||
observeAllEnabled(),
|
||||
observeSortOrder(),
|
||||
) { skipNsfw, order ->
|
||||
dao.observeEnabled(order).map {
|
||||
) { skipNsfw, allEnabled, order ->
|
||||
dao.observeAll(!allEnabled, order).map {
|
||||
it.toSources(skipNsfw, order)
|
||||
}
|
||||
}.flattenLatest()
|
||||
@@ -249,10 +259,11 @@ class MangaSourcesRepository @Inject constructor(
|
||||
return false
|
||||
}
|
||||
var maxSortKey = dao.getMaxSortKey()
|
||||
val isAllEnabled = settings.isAllSourcesEnabled
|
||||
val entities = new.map { x ->
|
||||
MangaSourceEntity(
|
||||
source = x.name,
|
||||
isEnabled = false,
|
||||
isEnabled = isAllEnabled,
|
||||
sortKey = ++maxSortKey,
|
||||
addedIn = BuildConfig.VERSION_CODE,
|
||||
lastUsedAt = 0,
|
||||
@@ -355,6 +366,7 @@ class MangaSourcesRepository @Inject constructor(
|
||||
skipNsfwSources: Boolean,
|
||||
sortOrder: SourcesSortOrder?,
|
||||
): MutableList<MangaSourceInfo> {
|
||||
val isAllEnabled = settings.isAllSourcesEnabled
|
||||
val result = ArrayList<MangaSourceInfo>(size)
|
||||
for (entity in this) {
|
||||
val source = entity.source.toMangaSourceOrNull() ?: continue
|
||||
@@ -365,7 +377,7 @@ class MangaSourcesRepository @Inject constructor(
|
||||
result.add(
|
||||
MangaSourceInfo(
|
||||
mangaSource = source,
|
||||
isEnabled = entity.isEnabled,
|
||||
isEnabled = entity.isEnabled || isAllEnabled,
|
||||
isPinned = entity.isPinned,
|
||||
),
|
||||
)
|
||||
@@ -385,5 +397,9 @@ class MangaSourcesRepository @Inject constructor(
|
||||
sourcesSortOrder
|
||||
}
|
||||
|
||||
private fun observeAllEnabled() = settings.observeAsFlow(AppSettings.KEY_SOURCES_ENABLED_ALL) {
|
||||
isAllSourcesEnabled
|
||||
}
|
||||
|
||||
private fun String.toMangaSourceOrNull(): MangaParserSource? = MangaParserSource.entries.find { it.name == this }
|
||||
}
|
||||
|
||||
@@ -112,6 +112,8 @@ class ExploreFragment :
|
||||
override fun onListHeaderClick(item: ListHeader, view: View) {
|
||||
if (item.payload == R.id.nav_suggestions) {
|
||||
router.openSuggestions()
|
||||
} else if (viewModel.isAllSourcesEnabled.value) {
|
||||
router.openManageSources()
|
||||
} else {
|
||||
router.openSourcesCatalog()
|
||||
}
|
||||
@@ -166,7 +168,8 @@ class ExploreFragment :
|
||||
menu.findItem(R.id.action_shortcut).isVisible = isSingleSelection
|
||||
menu.findItem(R.id.action_pin).isVisible = selectedSources.all { !it.isPinned }
|
||||
menu.findItem(R.id.action_unpin).isVisible = selectedSources.all { it.isPinned }
|
||||
menu.findItem(R.id.action_disable)?.isVisible = selectedSources.all { it.mangaSource is MangaParserSource }
|
||||
menu.findItem(R.id.action_disable)?.isVisible = !viewModel.isAllSourcesEnabled.value &&
|
||||
selectedSources.all { it.mangaSource is MangaParserSource }
|
||||
menu.findItem(R.id.action_delete)?.isVisible = selectedSources.all { it.mangaSource is ExternalMangaSource }
|
||||
return super.onPrepareActionMode(controller, mode, menu)
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.mapLatest
|
||||
@@ -23,6 +22,7 @@ import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.ui.util.ReversibleAction
|
||||
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
|
||||
import org.koitharu.kotatsu.core.util.ext.call
|
||||
import org.koitharu.kotatsu.core.util.ext.combine
|
||||
import org.koitharu.kotatsu.explore.data.MangaSourcesRepository
|
||||
import org.koitharu.kotatsu.explore.domain.ExploreRepository
|
||||
import org.koitharu.kotatsu.explore.ui.model.ExploreButtons
|
||||
@@ -54,6 +54,12 @@ class ExploreViewModel @Inject constructor(
|
||||
valueProducer = { isSourcesGridMode },
|
||||
)
|
||||
|
||||
val isAllSourcesEnabled = settings.observeAsStateFlow(
|
||||
scope = viewModelScope + Dispatchers.IO,
|
||||
key = AppSettings.KEY_SOURCES_ENABLED_ALL,
|
||||
valueProducer = { isAllSourcesEnabled },
|
||||
)
|
||||
|
||||
private val isSuggestionsEnabled = settings.observeAsFlow(
|
||||
key = AppSettings.KEY_SUGGESTIONS,
|
||||
valueProducer = { isSuggestionsEnabled },
|
||||
@@ -137,9 +143,10 @@ class ExploreViewModel @Inject constructor(
|
||||
getSuggestionFlow(),
|
||||
isGrid,
|
||||
isRandomLoading,
|
||||
isAllSourcesEnabled,
|
||||
sourcesRepository.observeHasNewSourcesForBadge(),
|
||||
) { content, suggestions, grid, randomLoading, newSources ->
|
||||
buildList(content, suggestions, grid, randomLoading, newSources)
|
||||
) { content, suggestions, grid, randomLoading, allSourcesEnabled, newSources ->
|
||||
buildList(content, suggestions, grid, randomLoading, allSourcesEnabled, newSources)
|
||||
}.withErrorHandling()
|
||||
|
||||
private fun buildList(
|
||||
@@ -147,6 +154,7 @@ class ExploreViewModel @Inject constructor(
|
||||
recommendation: List<Manga>,
|
||||
isGrid: Boolean,
|
||||
randomLoading: Boolean,
|
||||
allSourcesEnabled: Boolean,
|
||||
hasNewSources: Boolean,
|
||||
): List<ListModel> {
|
||||
val result = ArrayList<ListModel>(sources.size + 3)
|
||||
@@ -158,8 +166,8 @@ class ExploreViewModel @Inject constructor(
|
||||
if (sources.isNotEmpty()) {
|
||||
result += ListHeader(
|
||||
textRes = R.string.remote_sources,
|
||||
buttonTextRes = R.string.catalog,
|
||||
badge = if (hasNewSources) "" else null,
|
||||
buttonTextRes = if (allSourcesEnabled) R.string.manage else R.string.catalog,
|
||||
badge = if (!allSourcesEnabled && hasNewSources) "" else null,
|
||||
)
|
||||
sources.mapTo(result) { MangaSourceItem(it, isGrid) }
|
||||
} else {
|
||||
|
||||
@@ -42,7 +42,7 @@ class SourceSettingsFragment : BasePreferenceFragment(0), Preference.OnPreferenc
|
||||
val isValidSource = viewModel.repository !is EmptyMangaRepository
|
||||
|
||||
findPreference<SwitchPreferenceCompat>(KEY_ENABLE)?.run {
|
||||
isVisible = isValidSource
|
||||
isVisible = isValidSource && !settings.isAllSourcesEnabled
|
||||
onPreferenceChangeListener = this@SourceSettingsFragment
|
||||
}
|
||||
findPreference<Preference>(KEY_AUTH)?.run {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.koitharu.kotatsu.settings.sources
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.fragment.app.viewModels
|
||||
@@ -17,7 +18,8 @@ import org.koitharu.kotatsu.explore.data.SourcesSortOrder
|
||||
import org.koitharu.kotatsu.parsers.util.names
|
||||
|
||||
@AndroidEntryPoint
|
||||
class SourcesSettingsFragment : BasePreferenceFragment(R.string.remote_sources) {
|
||||
class SourcesSettingsFragment : BasePreferenceFragment(R.string.remote_sources),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private val viewModel by viewModels<SourcesSettingsViewModel>()
|
||||
|
||||
@@ -43,10 +45,10 @@ class SourcesSettingsFragment : BasePreferenceFragment(R.string.remote_sources)
|
||||
}
|
||||
findPreference<Preference>(AppSettings.KEY_SOURCES_CATALOG)?.let { pref ->
|
||||
viewModel.availableSourcesCount.observe(viewLifecycleOwner) {
|
||||
pref.summary = if (it >= 0) {
|
||||
getString(R.string.available_d, it)
|
||||
} else {
|
||||
null
|
||||
pref.summary = when {
|
||||
it == 0 -> getString(R.string.all_sources_enabled)
|
||||
it > 0 -> getString(R.string.available_d, it)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,6 +57,13 @@ class SourcesSettingsFragment : BasePreferenceFragment(R.string.remote_sources)
|
||||
pref.isChecked = it
|
||||
}
|
||||
}
|
||||
updateEnableAllDependencies()
|
||||
settings.subscribe(this)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
settings.unsubscribe(this)
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onPreferenceTreeClick(preference: Preference): Boolean = when (preference.key) {
|
||||
@@ -70,4 +79,14 @@ class SourcesSettingsFragment : BasePreferenceFragment(R.string.remote_sources)
|
||||
|
||||
else -> super.onPreferenceTreeClick(preference)
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||
when (key) {
|
||||
AppSettings.KEY_SOURCES_ENABLED_ALL -> updateEnableAllDependencies()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateEnableAllDependencies() {
|
||||
findPreference<Preference>(AppSettings.KEY_SOURCES_CATALOG)?.isEnabled = !settings.isAllSourcesEnabled
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ fun sourceConfigItemDelegate2(
|
||||
bind {
|
||||
binding.textViewTitle.text = item.source.getTitle(context)
|
||||
binding.imageViewAdd.isGone = item.isEnabled || !item.isAvailable
|
||||
binding.imageViewRemove.isVisible = item.isEnabled
|
||||
binding.imageViewRemove.isVisible = item.isEnabled && item.isDisableAvailable
|
||||
binding.imageViewMenu.isVisible = item.isEnabled
|
||||
binding.textViewTitle.drawableStart = if (item.isPinned) iconPinned else null
|
||||
binding.textViewDescription.text = item.source.getSummary(context)
|
||||
|
||||
@@ -70,6 +70,7 @@ class SourcesListProducer @Inject constructor(
|
||||
val pinned = repository.getPinnedSources().mapToSet { it.name }
|
||||
val isNsfwDisabled = settings.isNsfwContentDisabled
|
||||
val isReorderAvailable = settings.sourcesSortOrder == SourcesSortOrder.MANUAL
|
||||
val isDisableAvailable = !settings.isAllSourcesEnabled
|
||||
val withTip = isReorderAvailable && settings.isTipEnabled(TIP_REORDER)
|
||||
val enabledSet = enabledSources.toSet()
|
||||
if (query.isNotEmpty()) {
|
||||
@@ -83,6 +84,7 @@ class SourcesListProducer @Inject constructor(
|
||||
isDraggable = false,
|
||||
isAvailable = !isNsfwDisabled || !it.isNsfw(),
|
||||
isPinned = it.name in pinned,
|
||||
isDisableAvailable = isDisableAvailable,
|
||||
)
|
||||
}.ifEmpty {
|
||||
listOf(SourceConfigItem.EmptySearchResult)
|
||||
@@ -104,6 +106,7 @@ class SourcesListProducer @Inject constructor(
|
||||
isDraggable = isReorderAvailable,
|
||||
isAvailable = false,
|
||||
isPinned = it.name in pinned,
|
||||
isDisableAvailable = isDisableAvailable,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,6 +171,8 @@ class SourcesManageFragment :
|
||||
override fun onPrepareMenu(menu: Menu) {
|
||||
super.onPrepareMenu(menu)
|
||||
menu.findItem(R.id.action_no_nsfw).isChecked = settings.isNsfwContentDisabled
|
||||
menu.findItem(R.id.action_disable_all).isVisible = !settings.isAllSourcesEnabled
|
||||
menu.findItem(R.id.action_catalog).isVisible = !settings.isAllSourcesEnabled
|
||||
}
|
||||
|
||||
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
|
||||
|
||||
@@ -14,6 +14,7 @@ sealed interface SourceConfigItem : ListModel {
|
||||
val isDraggable: Boolean,
|
||||
val isAvailable: Boolean,
|
||||
val isPinned: Boolean,
|
||||
val isDisableAvailable: Boolean,
|
||||
) : SourceConfigItem {
|
||||
|
||||
val isNsfw: Boolean
|
||||
|
||||
12
app/src/main/res/drawable/ic_disable.xml
Normal file
12
app/src/main/res/drawable/ic_disable.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="#000000"
|
||||
android:pathData="M22.11 21.46L2.39 1.73L1.11 3L4.06 5.95C2.78 7.63 2 9.72 2 12C2 17.5 6.5 22 12 22C14.28 22 16.37 21.23 18.05 19.94L20.84 22.73L22.11 21.46M12 20C7.58 20 4 16.42 4 12C4 10.27 4.56 8.68 5.5 7.38L16.62 18.5C15.32 19.45 13.73 20 12 20M8.17 4.97L6.72 3.5C8.25 2.56 10.06 2 12 2C17.5 2 22 6.5 22 12C22 13.94 21.44 15.75 20.5 17.28L19.03 15.83C19.65 14.69 20 13.39 20 12C20 7.58 16.42 4 12 4C10.61 4 9.31 4.35 8.17 4.97Z" />
|
||||
</vector>
|
||||
@@ -82,10 +82,10 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/remove"
|
||||
android:contentDescription="@string/disable"
|
||||
android:padding="@dimen/margin_small"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_delete"
|
||||
android:tooltipText="@string/remove" />
|
||||
android:src="@drawable/ic_disable"
|
||||
android:tooltipText="@string/disable" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -789,4 +789,7 @@
|
||||
<string name="open_telegram_bot_summary">Press to open chat with Kotatsu Backup Bot</string>
|
||||
<string name="clear_database">Clear database</string>
|
||||
<string name="clear_database_summary">Delete information about manga that is not used</string>
|
||||
<string name="enable_all_sources">Enable all manga sources</string>
|
||||
<string name="enable_all_sources_summary">All available manga sources will be enabled permanently</string>
|
||||
<string name="all_sources_enabled">All sources are enabled</string>
|
||||
</resources>
|
||||
|
||||
@@ -20,11 +20,17 @@
|
||||
android:persistent="false"
|
||||
android:title="@string/manage_sources" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="sources_enabled_all"
|
||||
android:summary="@string/enable_all_sources_summary"
|
||||
android:title="@string/enable_all_sources"
|
||||
app:allowDividerAbove="true" />
|
||||
|
||||
<Preference
|
||||
android:key="sources_catalog"
|
||||
android:persistent="false"
|
||||
android:title="@string/sources_catalog"
|
||||
app:allowDividerAbove="true" />
|
||||
android:title="@string/sources_catalog" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
|
||||
Reference in New Issue
Block a user