Sources settings screen
This commit is contained in:
@@ -4,10 +4,15 @@ import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.RawQuery
|
||||
import androidx.room.Transaction
|
||||
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.core.db.entity.MangaSourceEntity
|
||||
import org.koitharu.kotatsu.explore.data.SourcesSortOrder
|
||||
|
||||
@Dao
|
||||
abstract class MangaSourcesDao {
|
||||
@@ -15,14 +20,11 @@ abstract class MangaSourcesDao {
|
||||
@Query("SELECT * FROM sources ORDER BY sort_key")
|
||||
abstract suspend fun findAll(): List<MangaSourceEntity>
|
||||
|
||||
@Query("SELECT * FROM sources WHERE enabled = 1 ORDER BY sort_key")
|
||||
abstract suspend fun findAllEnabled(): List<MangaSourceEntity>
|
||||
|
||||
@Query("SELECT * FROM sources WHERE enabled = 0 ORDER BY sort_key")
|
||||
abstract suspend fun findAllDisabled(): List<MangaSourceEntity>
|
||||
|
||||
@Query("SELECT * FROM sources WHERE enabled = 1 ORDER BY sort_key")
|
||||
abstract fun observeEnabled(): Flow<List<MangaSourceEntity>>
|
||||
@Query("SELECT * FROM sources WHERE enabled = 0")
|
||||
abstract fun observeDisabled(): Flow<List<MangaSourceEntity>>
|
||||
|
||||
@Query("SELECT * FROM sources ORDER BY sort_key")
|
||||
abstract fun observeAll(): Flow<List<MangaSourceEntity>>
|
||||
@@ -43,6 +45,22 @@ abstract class MangaSourcesDao {
|
||||
@Upsert
|
||||
abstract suspend fun upsert(entry: MangaSourceEntity)
|
||||
|
||||
fun observeEnabled(order: SourcesSortOrder): Flow<List<MangaSourceEntity>> {
|
||||
val orderBy = getOrderBy(order)
|
||||
|
||||
@Language("RoomSql")
|
||||
val query = SimpleSQLiteQuery("SELECT * FROM sources WHERE enabled = 1 ORDER BY $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 $orderBy")
|
||||
return findAllImpl(query)
|
||||
}
|
||||
|
||||
@Transaction
|
||||
open suspend fun setEnabled(source: String, isEnabled: Boolean) {
|
||||
if (updateIsEnabled(source, isEnabled) == 0) {
|
||||
@@ -57,4 +75,16 @@ abstract class MangaSourcesDao {
|
||||
|
||||
@Query("UPDATE sources SET enabled = :isEnabled WHERE source = :source")
|
||||
protected abstract suspend fun updateIsEnabled(source: String, isEnabled: Boolean): Int
|
||||
|
||||
@RawQuery(observedEntities = [MangaSourceEntity::class])
|
||||
protected abstract fun observeImpl(query: SupportSQLiteQuery): Flow<List<MangaSourceEntity>>
|
||||
|
||||
@RawQuery
|
||||
protected abstract suspend fun findAllImpl(query: SupportSQLiteQuery): List<MangaSourceEntity>
|
||||
|
||||
private fun getOrderBy(order: SourcesSortOrder) = when (order) {
|
||||
SourcesSortOrder.ALPHABETIC -> "source ASC"
|
||||
SourcesSortOrder.POPULARITY -> "(SELECT COUNT(*) FROM manga WHERE source = sources.source) DESC"
|
||||
SourcesSortOrder.MANUAL -> "sort_key ASC"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.koitharu.kotatsu.core.util.ext.observe
|
||||
import org.koitharu.kotatsu.core.util.ext.putEnumValue
|
||||
import org.koitharu.kotatsu.core.util.ext.takeIfReadable
|
||||
import org.koitharu.kotatsu.core.util.ext.toUriOrNull
|
||||
import org.koitharu.kotatsu.explore.data.SourcesSortOrder
|
||||
import org.koitharu.kotatsu.list.domain.ListSortOrder
|
||||
import org.koitharu.kotatsu.parsers.model.SortOrder
|
||||
import org.koitharu.kotatsu.parsers.util.find
|
||||
@@ -209,6 +210,10 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
||||
return policy.isNetworkAllowed(connectivityManager)
|
||||
}
|
||||
|
||||
var sourcesSortOrder: SourcesSortOrder
|
||||
get() = prefs.getEnumValue(KEY_SOURCES_ORDER, SourcesSortOrder.MANUAL)
|
||||
set(value) = prefs.edit { putEnumValue(KEY_SOURCES_ORDER, value) }
|
||||
|
||||
var isSourcesGridMode: Boolean
|
||||
get() = prefs.getBoolean(KEY_SOURCES_GRID, false)
|
||||
set(value) = prefs.edit { putBoolean(KEY_SOURCES_GRID, value) }
|
||||
@@ -528,6 +533,8 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
||||
const val KEY_RELATED_MANGA = "related_manga"
|
||||
const val KEY_NAV_MAIN = "nav_main"
|
||||
const val KEY_32BIT_COLOR = "enhanced_colors"
|
||||
const val KEY_SOURCES_ORDER = "sources_sort_order"
|
||||
const val KEY_SOURCES_CATALOG = "sources_catalog"
|
||||
|
||||
// About
|
||||
const val KEY_APP_UPDATE = "app_update"
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.koitharu.kotatsu.core.prefs.observeAsFlow
|
||||
import org.koitharu.kotatsu.core.ui.util.ReversibleHandle
|
||||
import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import java.util.Collections
|
||||
import java.util.EnumSet
|
||||
import javax.inject.Inject
|
||||
@@ -43,19 +44,44 @@ class MangaSourcesRepository @Inject constructor(
|
||||
get() = Collections.unmodifiableSet(remoteSources)
|
||||
|
||||
suspend fun getEnabledSources(): List<MangaSource> {
|
||||
return dao.findAllEnabled().toSources(settings.isNsfwContentDisabled)
|
||||
val order = settings.sourcesSortOrder
|
||||
return dao.findAllEnabled(order).toSources(settings.isNsfwContentDisabled, order)
|
||||
}
|
||||
|
||||
suspend fun getDisabledSources(): List<MangaSource> {
|
||||
return dao.findAllDisabled().toSources(settings.isNsfwContentDisabled)
|
||||
return dao.findAllDisabled().toSources(settings.isNsfwContentDisabled, null)
|
||||
}
|
||||
|
||||
fun observeEnabledSources(): Flow<List<MangaSource>> = observeIsNsfwDisabled().flatMapLatest { skipNsfw ->
|
||||
dao.observeEnabled().map {
|
||||
it.toSources(skipNsfw)
|
||||
}
|
||||
fun observeEnabledSourcesCount(): Flow<Int> {
|
||||
return combine(
|
||||
observeIsNsfwDisabled(),
|
||||
dao.observeEnabled(SourcesSortOrder.MANUAL),
|
||||
) { skipNsfw, sources ->
|
||||
sources.count { skipNsfw || !MangaSource(it.source).isNsfw() }
|
||||
}.distinctUntilChanged()
|
||||
}
|
||||
|
||||
fun observeAvailableSourcesCount(): Flow<Int> {
|
||||
return combine(
|
||||
observeIsNsfwDisabled(),
|
||||
dao.observeEnabled(SourcesSortOrder.MANUAL),
|
||||
) { skipNsfw, enabledSources ->
|
||||
val enabled = enabledSources.mapToSet { it.source }
|
||||
allMangaSources.count { x ->
|
||||
x.name !in enabled && (!skipNsfw || !x.isNsfw())
|
||||
}
|
||||
}.distinctUntilChanged()
|
||||
}
|
||||
|
||||
fun observeEnabledSources(): Flow<List<MangaSource>> = combine(
|
||||
observeIsNsfwDisabled(),
|
||||
observeSortOrder(),
|
||||
) { skipNsfw, order ->
|
||||
dao.observeEnabled(order).map {
|
||||
it.toSources(skipNsfw, order)
|
||||
}
|
||||
}.flatMapLatest { it }
|
||||
|
||||
fun observeAll(): Flow<List<Pair<MangaSource, Boolean>>> = dao.observeAll().map { entities ->
|
||||
val result = ArrayList<Pair<MangaSource, Boolean>>(entities.size)
|
||||
for (entity in entities) {
|
||||
@@ -150,7 +176,10 @@ class MangaSourcesRepository @Inject constructor(
|
||||
return result
|
||||
}
|
||||
|
||||
private fun List<MangaSourceEntity>.toSources(skipNsfwSources: Boolean): List<MangaSource> {
|
||||
private fun List<MangaSourceEntity>.toSources(
|
||||
skipNsfwSources: Boolean,
|
||||
sortOrder: SourcesSortOrder?,
|
||||
): List<MangaSource> {
|
||||
val result = ArrayList<MangaSource>(size)
|
||||
for (entity in this) {
|
||||
val source = MangaSource(entity.source)
|
||||
@@ -161,6 +190,9 @@ class MangaSourcesRepository @Inject constructor(
|
||||
result.add(source)
|
||||
}
|
||||
}
|
||||
if (sortOrder == SourcesSortOrder.ALPHABETIC) {
|
||||
result.sortBy { it.title }
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -171,4 +203,8 @@ class MangaSourcesRepository @Inject constructor(
|
||||
private fun observeIsNewSourcesEnabled() = settings.observeAsFlow(AppSettings.KEY_SOURCES_NEW) {
|
||||
isNewSourcesTipEnabled
|
||||
}
|
||||
|
||||
private fun observeSortOrder() = settings.observeAsFlow(AppSettings.KEY_SOURCES_ORDER) {
|
||||
sourcesSortOrder
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.koitharu.kotatsu.explore.data
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import org.koitharu.kotatsu.R
|
||||
|
||||
enum class SourcesSortOrder(
|
||||
@StringRes val titleResId: Int,
|
||||
) {
|
||||
ALPHABETIC(R.string.by_name),
|
||||
POPULARITY(R.string.popular),
|
||||
MANUAL(R.string.manual),
|
||||
}
|
||||
@@ -85,7 +85,7 @@ class ExploreFragment :
|
||||
SpanSizeResolver(this, resources.getDimensionPixelSize(R.dimen.explore_grid_width)).attach()
|
||||
addItemDecoration(TypedListSpacingDecoration(context, false))
|
||||
}
|
||||
addMenuProvider(ExploreMenuProvider(binding.root.context, viewModel))
|
||||
addMenuProvider(ExploreMenuProvider(binding.root.context))
|
||||
viewModel.content.observe(viewLifecycleOwner) {
|
||||
exploreAdapter?.items = it
|
||||
}
|
||||
@@ -176,7 +176,6 @@ class ExploreFragment :
|
||||
} else {
|
||||
LinearLayoutManager(requireContext())
|
||||
}
|
||||
activity?.invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
private fun showSuggestionsTip() {
|
||||
|
||||
@@ -10,7 +10,6 @@ import org.koitharu.kotatsu.settings.SettingsActivity
|
||||
|
||||
class ExploreMenuProvider(
|
||||
private val context: Context,
|
||||
private val viewModel: ExploreViewModel,
|
||||
) : MenuProvider {
|
||||
|
||||
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
||||
@@ -19,22 +18,12 @@ class ExploreMenuProvider(
|
||||
|
||||
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
|
||||
return when (menuItem.itemId) {
|
||||
R.id.action_grid -> {
|
||||
viewModel.setGridMode(!menuItem.isChecked)
|
||||
true
|
||||
}
|
||||
|
||||
R.id.action_manage -> {
|
||||
context.startActivity(SettingsActivity.newManageSourcesIntent(context))
|
||||
context.startActivity(SettingsActivity.newSourcesSettingsIntent(context))
|
||||
true
|
||||
}
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPrepareMenu(menu: Menu) {
|
||||
super.onPrepareMenu(menu)
|
||||
menu.findItem(R.id.action_grid)?.isChecked = viewModel.isGrid.value == true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ 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.explore.data.MangaSourcesRepository
|
||||
import org.koitharu.kotatsu.explore.data.SourcesSortOrder
|
||||
import org.koitharu.kotatsu.explore.domain.ExploreRepository
|
||||
import org.koitharu.kotatsu.explore.ui.model.ExploreButtons
|
||||
import org.koitharu.kotatsu.explore.ui.model.MangaSourceItem
|
||||
@@ -50,11 +51,13 @@ class ExploreViewModel @Inject constructor(
|
||||
valueProducer = { isSourcesGridMode },
|
||||
)
|
||||
|
||||
val isSuggestionsEnabled = settings.observeAsFlow(
|
||||
private val isSuggestionsEnabled = settings.observeAsFlow(
|
||||
key = AppSettings.KEY_SUGGESTIONS,
|
||||
valueProducer = { isSuggestionsEnabled },
|
||||
)
|
||||
|
||||
val sortOrder = MutableStateFlow(SourcesSortOrder.MANUAL) // TODO
|
||||
|
||||
val onOpenManga = MutableEventFlow<Manga>()
|
||||
val onActionDone = MutableEventFlow<ReversibleAction>()
|
||||
val onShowSuggestionsTip = MutableEventFlow<Unit>()
|
||||
@@ -104,10 +107,6 @@ class ExploreViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun setGridMode(value: Boolean) {
|
||||
settings.isSourcesGridMode = value
|
||||
}
|
||||
|
||||
fun respondSuggestionTip(isAccepted: Boolean) {
|
||||
settings.isSuggestionsEnabled = isAccepted
|
||||
settings.closeTip(TIP_SUGGESTIONS)
|
||||
|
||||
@@ -4,7 +4,6 @@ import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.plus
|
||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||
@@ -18,7 +17,6 @@ class RootSettingsViewModel @Inject constructor(
|
||||
|
||||
val totalSourcesCount = sourcesRepository.allMangaSources.size
|
||||
|
||||
val enabledSourcesCount = sourcesRepository.observeEnabledSources()
|
||||
.map { it.size }
|
||||
val enabledSourcesCount = sourcesRepository.observeEnabledSourcesCount()
|
||||
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, -1)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,8 @@ import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.settings.about.AboutSettingsFragment
|
||||
import org.koitharu.kotatsu.settings.about.AppUpdateDialog
|
||||
import org.koitharu.kotatsu.settings.sources.SourceSettingsFragment
|
||||
import org.koitharu.kotatsu.settings.sources.SourcesManageFragment
|
||||
import org.koitharu.kotatsu.settings.sources.SourcesSettingsFragment
|
||||
import org.koitharu.kotatsu.settings.sources.manage.SourcesManageFragment
|
||||
import org.koitharu.kotatsu.settings.tracker.TrackerSettingsFragment
|
||||
import org.koitharu.kotatsu.settings.userdata.UserDataSettingsFragment
|
||||
|
||||
@@ -153,6 +154,7 @@ class SettingsActivity :
|
||||
ACTION_SUGGESTIONS -> SuggestionsSettingsFragment()
|
||||
ACTION_HISTORY -> UserDataSettingsFragment()
|
||||
ACTION_TRACKER -> TrackerSettingsFragment()
|
||||
ACTION_SOURCES -> SourcesSettingsFragment()
|
||||
ACTION_MANAGE_DOWNLOADS -> DownloadsSettingsFragment()
|
||||
ACTION_SOURCE -> SourceSettingsFragment.newInstance(
|
||||
intent.getSerializableExtraCompat(EXTRA_SOURCE) as? MangaSource ?: MangaSource.LOCAL,
|
||||
@@ -182,6 +184,7 @@ class SettingsActivity :
|
||||
private const val ACTION_TRACKER = "${BuildConfig.APPLICATION_ID}.action.MANAGE_TRACKER"
|
||||
private const val ACTION_HISTORY = "${BuildConfig.APPLICATION_ID}.action.MANAGE_HISTORY"
|
||||
private const val ACTION_SOURCE = "${BuildConfig.APPLICATION_ID}.action.MANAGE_SOURCE_SETTINGS"
|
||||
private const val ACTION_SOURCES = "${BuildConfig.APPLICATION_ID}.action.MANAGE_SOURCES"
|
||||
private const val ACTION_MANAGE_SOURCES = "${BuildConfig.APPLICATION_ID}.action.MANAGE_SOURCES_LIST"
|
||||
private const val ACTION_MANAGE_DOWNLOADS = "${BuildConfig.APPLICATION_ID}.action.MANAGE_DOWNLOADS"
|
||||
private const val EXTRA_SOURCE = "source"
|
||||
@@ -206,6 +209,10 @@ class SettingsActivity :
|
||||
Intent(context, SettingsActivity::class.java)
|
||||
.setAction(ACTION_HISTORY)
|
||||
|
||||
fun newSourcesSettingsIntent(context: Context) =
|
||||
Intent(context, SettingsActivity::class.java)
|
||||
.setAction(ACTION_SOURCES)
|
||||
|
||||
fun newManageSourcesIntent(context: Context) =
|
||||
Intent(context, SettingsActivity::class.java)
|
||||
.setAction(ACTION_MANAGE_SOURCES)
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.koitharu.kotatsu.settings.sources
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.ui.BasePreferenceFragment
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
import org.koitharu.kotatsu.core.util.ext.setDefaultValueCompat
|
||||
import org.koitharu.kotatsu.explore.data.SourcesSortOrder
|
||||
import org.koitharu.kotatsu.parsers.util.names
|
||||
import org.koitharu.kotatsu.settings.sources.catalog.SourcesCatalogActivity
|
||||
|
||||
@AndroidEntryPoint
|
||||
class SourcesSettingsFragment : BasePreferenceFragment(R.string.remote_sources) {
|
||||
|
||||
private val viewModel by viewModels<SourcesSettingsViewModel>()
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_sources)
|
||||
findPreference<ListPreference>(AppSettings.KEY_SOURCES_ORDER)?.run {
|
||||
entryValues = SourcesSortOrder.entries.names()
|
||||
entries = SourcesSortOrder.entries.map { context.getString(it.titleResId) }.toTypedArray()
|
||||
setDefaultValueCompat(SourcesSortOrder.MANUAL.name)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
findPreference<Preference>(AppSettings.KEY_REMOTE_SOURCES)?.let { pref ->
|
||||
viewModel.enabledSourcesCount.observe(viewLifecycleOwner) {
|
||||
pref.summary = if (it >= 0) {
|
||||
resources.getQuantityString(R.plurals.items, it, it)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPreferenceTreeClick(preference: Preference): Boolean = when (preference.key) {
|
||||
AppSettings.KEY_SOURCES_CATALOG -> {
|
||||
startActivity(Intent(preference.context, SourcesCatalogActivity::class.java))
|
||||
true
|
||||
}
|
||||
|
||||
else -> super.onPreferenceTreeClick(preference)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.koitharu.kotatsu.settings.sources
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.plus
|
||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.explore.data.MangaSourcesRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class SourcesSettingsViewModel @Inject constructor(
|
||||
private val sourcesRepository: MangaSourcesRepository,
|
||||
) : BaseViewModel() {
|
||||
|
||||
val totalSourcesCount = sourcesRepository.allMangaSources.size
|
||||
|
||||
val enabledSourcesCount = sourcesRepository.observeEnabledSourcesCount()
|
||||
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, -1)
|
||||
|
||||
val availableSourcesCount = sourcesRepository.observeAvailableSourcesCount()
|
||||
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, -1)
|
||||
}
|
||||
@@ -169,6 +169,7 @@ private fun showSourceMenu(
|
||||
menu.inflate(R.menu.popup_source_config)
|
||||
menu.menu.findItem(R.id.action_shortcut)
|
||||
?.isVisible = ShortcutManagerCompat.isRequestPinShortcutSupported(anchor.context)
|
||||
menu.menu.findItem(R.id.action_lift)?.isVisible = item.isDraggable
|
||||
menu.setOnMenuItemClickListener {
|
||||
when (it.itemId) {
|
||||
R.id.action_settings -> listener.onItemSettingsClick(item)
|
||||
|
||||
@@ -74,7 +74,7 @@ class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
|
||||
}
|
||||
|
||||
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||
viewModel.setContentType(ContentType.entries[tab.position])
|
||||
viewModel.setContentType(tab.tag as ContentType)
|
||||
}
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab) = Unit
|
||||
@@ -86,8 +86,12 @@ class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
|
||||
private fun initTabs() {
|
||||
val tabs = viewBinding.tabs
|
||||
for (type in ContentType.entries) {
|
||||
if (viewModel.isNsfwDisabled && type == ContentType.HENTAI) {
|
||||
continue
|
||||
}
|
||||
val tab = tabs.newTab()
|
||||
tab.setText(type.titleResId)
|
||||
tab.tag = type
|
||||
tabs.addTab(tab)
|
||||
}
|
||||
tabs.addOnTabSelectedListener(this)
|
||||
|
||||
@@ -12,6 +12,7 @@ import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.ui.util.ReversibleAction
|
||||
import org.koitharu.kotatsu.core.util.LocaleComparator
|
||||
@@ -28,6 +29,7 @@ import javax.inject.Inject
|
||||
class SourcesCatalogViewModel @Inject constructor(
|
||||
private val repository: MangaSourcesRepository,
|
||||
private val listProducerFactory: SourcesCatalogListProducer.Factory,
|
||||
private val settings: AppSettings,
|
||||
) : BaseViewModel() {
|
||||
|
||||
private val lifecycle = RetainedLifecycleImpl()
|
||||
@@ -37,6 +39,8 @@ class SourcesCatalogViewModel @Inject constructor(
|
||||
val locales = getLocalesImpl()
|
||||
val locale = MutableStateFlow(locales.firstOrNull()?.language)
|
||||
|
||||
val isNsfwDisabled = settings.isNsfwContentDisabled
|
||||
|
||||
private val listProducer: StateFlow<SourcesCatalogListProducer?> = combine(
|
||||
locale,
|
||||
contentType,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.settings.sources
|
||||
package org.koitharu.kotatsu.settings.sources.manage
|
||||
|
||||
import androidx.room.InvalidationTracker
|
||||
import dagger.hilt.android.ViewModelLifecycle
|
||||
@@ -19,6 +19,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.util.ext.lifecycleScope
|
||||
import org.koitharu.kotatsu.core.util.ext.toEnumSet
|
||||
import org.koitharu.kotatsu.explore.data.MangaSourcesRepository
|
||||
import org.koitharu.kotatsu.explore.data.SourcesSortOrder
|
||||
import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -61,7 +62,8 @@ class SourcesListProducer @Inject constructor(
|
||||
private suspend fun buildList(): List<SourceConfigItem> {
|
||||
val enabledSources = repository.getEnabledSources()
|
||||
val isNsfwDisabled = settings.isNsfwContentDisabled
|
||||
val withTip = settings.isTipEnabled(TIP_REORDER)
|
||||
val isReorderAvailable = settings.sourcesSortOrder == SourcesSortOrder.MANUAL
|
||||
val withTip = isReorderAvailable && settings.isTipEnabled(TIP_REORDER)
|
||||
val enabledSet = enabledSources.toEnumSet()
|
||||
if (query.isNotEmpty()) {
|
||||
return enabledSources.mapNotNull {
|
||||
@@ -91,7 +93,7 @@ class SourcesListProducer @Inject constructor(
|
||||
SourceConfigItem.SourceItem(
|
||||
source = it,
|
||||
isEnabled = true,
|
||||
isDraggable = true,
|
||||
isDraggable = isReorderAvailable,
|
||||
isAvailable = false,
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.settings.sources
|
||||
package org.koitharu.kotatsu.settings.sources.manage
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
@@ -31,6 +31,7 @@ import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope
|
||||
import org.koitharu.kotatsu.databinding.FragmentSettingsSourcesBinding
|
||||
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
|
||||
import org.koitharu.kotatsu.settings.SettingsActivity
|
||||
import org.koitharu.kotatsu.settings.sources.SourceSettingsFragment
|
||||
import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigAdapter
|
||||
import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigListener
|
||||
import org.koitharu.kotatsu.settings.sources.catalog.SourcesCatalogActivity
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.settings.sources
|
||||
package org.koitharu.kotatsu.settings.sources.manage
|
||||
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -2,12 +2,6 @@
|
||||
<menu
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_grid"
|
||||
android:checkable="true"
|
||||
android:title="@string/show_in_grid_view"
|
||||
android:titleCondensed="@string/grid" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_manage"
|
||||
android:title="@string/manage_sources"
|
||||
|
||||
@@ -523,4 +523,7 @@
|
||||
<string name="no_manga_sources_found">No available manga sources found by your query</string>
|
||||
<string name="catalog">Catalog</string>
|
||||
<string name="manage_sources">Manage sources</string>
|
||||
<string name="manual">Manual</string>
|
||||
<string name="available_d">Available: %1$d</string>
|
||||
<string name="disable_nsfw_summary">Disable NSFW sources and hide adult manga from list if possible</string>
|
||||
</resources>
|
||||
|
||||
@@ -46,21 +46,6 @@
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/remote_sources">
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="sources_grid"
|
||||
android:title="@string/show_in_grid_view" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="sources_new"
|
||||
android:summary="@string/suggest_new_sources_summary"
|
||||
android:title="@string/suggest_new_sources" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceScreen
|
||||
android:fragment="org.koitharu.kotatsu.settings.nav.NavConfigFragment"
|
||||
android:key="nav_main"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
android:title="@string/appearance" />
|
||||
|
||||
<PreferenceScreen
|
||||
android:fragment="org.koitharu.kotatsu.settings.sources.SourcesManageFragment"
|
||||
android:fragment="org.koitharu.kotatsu.settings.sources.SourcesSettingsFragment"
|
||||
android:icon="@drawable/ic_manga_source"
|
||||
android:key="remote_sources"
|
||||
android:title="@string/remote_sources" />
|
||||
|
||||
40
app/src/main/res/xml/pref_sources.xml
Normal file
40
app/src/main/res/xml/pref_sources.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<ListPreference
|
||||
android:key="sources_sort_order"
|
||||
android:title="@string/sort_order"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="sources_grid"
|
||||
android:title="@string/show_in_grid_view" />
|
||||
|
||||
<PreferenceScreen
|
||||
android:fragment="org.koitharu.kotatsu.settings.sources.manage.SourcesManageFragment"
|
||||
android:key="remote_sources"
|
||||
android:persistent="false"
|
||||
android:title="@string/manage_sources" />
|
||||
|
||||
<Preference
|
||||
android:key="sources_catalog"
|
||||
android:persistent="false"
|
||||
android:title="@string/sources_catalog"
|
||||
app:allowDividerAbove="true" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="no_nsfw"
|
||||
android:summary="@string/disable_nsfw_summary"
|
||||
android:title="@string/disable_nsfw" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="sources_new"
|
||||
android:summary="@string/suggest_new_sources_summary"
|
||||
android:title="@string/suggest_new_sources" />
|
||||
|
||||
</androidx.preference.PreferenceScreen>
|
||||
Reference in New Issue
Block a user