Fix settings issues
This commit is contained in:
@@ -16,7 +16,6 @@ import org.koitharu.kotatsu.core.util.ext.getThemeColor
|
|||||||
import org.koitharu.kotatsu.settings.SettingsActivity
|
import org.koitharu.kotatsu.settings.SettingsActivity
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@Suppress("LeakingThis")
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
|
abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
|
||||||
PreferenceFragmentCompat(),
|
PreferenceFragmentCompat(),
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import kotlinx.coroutines.plus
|
|||||||
import org.koitharu.kotatsu.core.model.ids
|
import org.koitharu.kotatsu.core.model.ids
|
||||||
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
||||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.require
|
||||||
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
||||||
import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteCategoriesSheet.Companion.KEY_MANGA_LIST
|
import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteCategoriesSheet.Companion.KEY_MANGA_LIST
|
||||||
import org.koitharu.kotatsu.favourites.ui.categories.select.model.CategoriesHeaderItem
|
import org.koitharu.kotatsu.favourites.ui.categories.select.model.CategoriesHeaderItem
|
||||||
@@ -25,7 +26,7 @@ class MangaCategoriesViewModel @Inject constructor(
|
|||||||
private val favouritesRepository: FavouritesRepository,
|
private val favouritesRepository: FavouritesRepository,
|
||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
|
|
||||||
private val manga = requireNotNull(savedStateHandle.get<List<ParcelableManga>>(KEY_MANGA_LIST)).map { it.manga }
|
private val manga = savedStateHandle.require<List<ParcelableManga>>(KEY_MANGA_LIST).map { it.manga }
|
||||||
private val header = CategoriesHeaderItem()
|
private val header = CategoriesHeaderItem()
|
||||||
|
|
||||||
val content: StateFlow<List<ListModel>> = combine(
|
val content: StateFlow<List<ListModel>> = combine(
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import org.koitharu.kotatsu.core.parser.MangaRepository
|
|||||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||||
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
|
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
|
||||||
import org.koitharu.kotatsu.core.util.ext.call
|
import org.koitharu.kotatsu.core.util.ext.call
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.require
|
||||||
import org.koitharu.kotatsu.parsers.model.MangaPage
|
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||||
import org.koitharu.kotatsu.reader.domain.ReaderColorFilter
|
import org.koitharu.kotatsu.reader.domain.ReaderColorFilter
|
||||||
import org.koitharu.kotatsu.reader.ui.colorfilter.ColorFilterConfigActivity.Companion.EXTRA_MANGA
|
import org.koitharu.kotatsu.reader.ui.colorfilter.ColorFilterConfigActivity.Companion.EXTRA_MANGA
|
||||||
@@ -23,7 +24,7 @@ class ColorFilterConfigViewModel @Inject constructor(
|
|||||||
private val mangaDataRepository: MangaDataRepository,
|
private val mangaDataRepository: MangaDataRepository,
|
||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
|
|
||||||
private val manga = checkNotNull(savedStateHandle.get<ParcelableManga>(EXTRA_MANGA)?.manga)
|
private val manga = savedStateHandle.require<ParcelableManga>(EXTRA_MANGA).manga
|
||||||
|
|
||||||
private var initialColorFilter: ReaderColorFilter? = null
|
private var initialColorFilter: ReaderColorFilter? = null
|
||||||
val colorFilter = MutableStateFlow<ReaderColorFilter?>(null)
|
val colorFilter = MutableStateFlow<ReaderColorFilter?>(null)
|
||||||
@@ -34,9 +35,7 @@ class ColorFilterConfigViewModel @Inject constructor(
|
|||||||
get() = colorFilter.value != initialColorFilter
|
get() = colorFilter.value != initialColorFilter
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val page = checkNotNull(
|
val page = savedStateHandle.require<ParcelableMangaPages>(ColorFilterConfigActivity.EXTRA_PAGES).pages.first()
|
||||||
savedStateHandle.get<ParcelableMangaPages>(ColorFilterConfigActivity.EXTRA_PAGES)?.pages?.firstOrNull(),
|
|
||||||
)
|
|
||||||
launchLoadingJob {
|
launchLoadingJob {
|
||||||
initialColorFilter = mangaDataRepository.getColorFilter(manga.id)
|
initialColorFilter = mangaDataRepository.getColorFilter(manga.id)
|
||||||
colorFilter.value = initialColorFilter
|
colorFilter.value = initialColorFilter
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||||||
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
||||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.require
|
||||||
import org.koitharu.kotatsu.details.domain.DoubleMangaLoadUseCase
|
import org.koitharu.kotatsu.details.domain.DoubleMangaLoadUseCase
|
||||||
import org.koitharu.kotatsu.list.ui.model.ListHeader
|
import org.koitharu.kotatsu.list.ui.model.ListHeader
|
||||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||||
@@ -26,7 +27,7 @@ class PagesThumbnailsViewModel @Inject constructor(
|
|||||||
|
|
||||||
private val currentPageIndex: Int = savedStateHandle[PagesThumbnailsSheet.ARG_CURRENT_PAGE] ?: -1
|
private val currentPageIndex: Int = savedStateHandle[PagesThumbnailsSheet.ARG_CURRENT_PAGE] ?: -1
|
||||||
private val initialChapterId: Long = savedStateHandle[PagesThumbnailsSheet.ARG_CHAPTER_ID] ?: 0L
|
private val initialChapterId: Long = savedStateHandle[PagesThumbnailsSheet.ARG_CHAPTER_ID] ?: 0L
|
||||||
val manga = requireNotNull(savedStateHandle.get<ParcelableManga>(PagesThumbnailsSheet.ARG_MANGA)).manga
|
val manga = savedStateHandle.require<ParcelableManga>(PagesThumbnailsSheet.ARG_MANGA).manga
|
||||||
|
|
||||||
private val repository = mangaRepositoryFactory.create(manga.source)
|
private val repository = mangaRepositoryFactory.create(manga.source)
|
||||||
private val mangaDetails = SuspendLazy {
|
private val mangaDetails = SuspendLazy {
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import androidx.core.app.LocaleManagerCompat
|
|||||||
import androidx.core.view.postDelayed
|
import androidx.core.view.postDelayed
|
||||||
import androidx.preference.ListPreference
|
import androidx.preference.ListPreference
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.TwoStatePreference
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
@@ -26,7 +25,6 @@ import org.koitharu.kotatsu.core.util.ext.setDefaultValueCompat
|
|||||||
import org.koitharu.kotatsu.core.util.ext.toList
|
import org.koitharu.kotatsu.core.util.ext.toList
|
||||||
import org.koitharu.kotatsu.parsers.util.names
|
import org.koitharu.kotatsu.parsers.util.names
|
||||||
import org.koitharu.kotatsu.parsers.util.toTitleCase
|
import org.koitharu.kotatsu.parsers.util.toTitleCase
|
||||||
import org.koitharu.kotatsu.settings.protect.ProtectSetupActivity
|
|
||||||
import org.koitharu.kotatsu.settings.utils.ActivityListPreference
|
import org.koitharu.kotatsu.settings.utils.ActivityListPreference
|
||||||
import org.koitharu.kotatsu.settings.utils.SliderPreference
|
import org.koitharu.kotatsu.settings.utils.SliderPreference
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
@@ -50,12 +48,10 @@ class AppearanceSettingsFragment :
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
preferenceScreen?.findPreference<ListPreference>(AppSettings.KEY_LIST_MODE)?.run {
|
findPreference<ListPreference>(AppSettings.KEY_LIST_MODE)?.run {
|
||||||
entryValues = ListMode.values().names()
|
entryValues = ListMode.values().names()
|
||||||
setDefaultValueCompat(ListMode.GRID.name)
|
setDefaultValueCompat(ListMode.GRID.name)
|
||||||
}
|
}
|
||||||
findPreference<TwoStatePreference>(AppSettings.KEY_PROTECT_APP)
|
|
||||||
?.isChecked = !settings.appPassword.isNullOrEmpty()
|
|
||||||
findPreference<ActivityListPreference>(AppSettings.KEY_APP_LOCALE)?.run {
|
findPreference<ActivityListPreference>(AppSettings.KEY_APP_LOCALE)?.run {
|
||||||
initLocalePicker(this)
|
initLocalePicker(this)
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
@@ -93,34 +89,12 @@ class AppearanceSettingsFragment :
|
|||||||
postRestart()
|
postRestart()
|
||||||
}
|
}
|
||||||
|
|
||||||
AppSettings.KEY_APP_PASSWORD -> {
|
|
||||||
findPreference<TwoStatePreference>(AppSettings.KEY_PROTECT_APP)
|
|
||||||
?.isChecked = !settings.appPassword.isNullOrEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
AppSettings.KEY_APP_LOCALE -> {
|
AppSettings.KEY_APP_LOCALE -> {
|
||||||
AppCompatDelegate.setApplicationLocales(settings.appLocales)
|
AppCompatDelegate.setApplicationLocales(settings.appLocales)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPreferenceTreeClick(preference: Preference): Boolean {
|
|
||||||
return when (preference.key) {
|
|
||||||
AppSettings.KEY_PROTECT_APP -> {
|
|
||||||
val pref = (preference as? TwoStatePreference ?: return false)
|
|
||||||
if (pref.isChecked) {
|
|
||||||
pref.isChecked = false
|
|
||||||
startActivity(Intent(preference.context, ProtectSetupActivity::class.java))
|
|
||||||
} else {
|
|
||||||
settings.appPassword = null
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> super.onPreferenceTreeClick(preference)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun postRestart() {
|
private fun postRestart() {
|
||||||
view?.postDelayed(400) {
|
view?.postDelayed(400) {
|
||||||
activityRecreationHandle.recreateAll()
|
activityRecreationHandle.recreateAll()
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import org.koitharu.kotatsu.databinding.ActivitySettingsBinding
|
|||||||
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
|
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
|
||||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||||
import org.koitharu.kotatsu.settings.about.AboutSettingsFragment
|
import org.koitharu.kotatsu.settings.about.AboutSettingsFragment
|
||||||
|
import org.koitharu.kotatsu.settings.sources.SourceSettingsFragment
|
||||||
import org.koitharu.kotatsu.settings.sources.SourcesListFragment
|
import org.koitharu.kotatsu.settings.sources.SourcesListFragment
|
||||||
import org.koitharu.kotatsu.settings.tracker.TrackerSettingsFragment
|
import org.koitharu.kotatsu.settings.tracker.TrackerSettingsFragment
|
||||||
|
|
||||||
|
|||||||
@@ -1,133 +0,0 @@
|
|||||||
package org.koitharu.kotatsu.settings
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.View
|
|
||||||
import androidx.lifecycle.LifecycleOwner
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import androidx.preference.Preference
|
|
||||||
import com.google.android.material.snackbar.Snackbar
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.ensureActive
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import org.koitharu.kotatsu.R
|
|
||||||
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
|
||||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
|
||||||
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
|
|
||||||
import org.koitharu.kotatsu.core.ui.BasePreferenceFragment
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.awaitViewLifecycle
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.requireSerializable
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.withArgs
|
|
||||||
import org.koitharu.kotatsu.parsers.exception.AuthRequiredException
|
|
||||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
|
||||||
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
|
|
||||||
import org.koitharu.kotatsu.settings.sources.auth.SourceAuthActivity
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
|
||||||
class SourceSettingsFragment : BasePreferenceFragment(0) {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var mangaRepositoryFactory: MangaRepository.Factory
|
|
||||||
|
|
||||||
private lateinit var source: MangaSource
|
|
||||||
private var repository: RemoteMangaRepository? = null
|
|
||||||
private val exceptionResolver = ExceptionResolver(this)
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
source = requireArguments().requireSerializable(EXTRA_SOURCE)
|
|
||||||
repository = mangaRepositoryFactory.create(source) as? RemoteMangaRepository
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
setTitle(source.title)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
|
||||||
preferenceManager.sharedPreferencesName = source.name
|
|
||||||
val repo = repository ?: return
|
|
||||||
addPreferencesFromResource(R.xml.pref_source)
|
|
||||||
addPreferencesFromRepository(repo)
|
|
||||||
|
|
||||||
findPreference<Preference>(KEY_AUTH)?.run {
|
|
||||||
val authProvider = repo.getAuthProvider()
|
|
||||||
isVisible = authProvider != null
|
|
||||||
isEnabled = authProvider?.isAuthorized == false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
findPreference<Preference>(KEY_AUTH)?.run {
|
|
||||||
if (isVisible) {
|
|
||||||
loadUsername(viewLifecycleOwner, this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPreferenceTreeClick(preference: Preference): Boolean {
|
|
||||||
return when (preference.key) {
|
|
||||||
KEY_AUTH -> {
|
|
||||||
startActivity(SourceAuthActivity.newIntent(preference.context, source))
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> super.onPreferenceTreeClick(preference)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadUsername(owner: LifecycleOwner, preference: Preference) = owner.lifecycleScope.launch {
|
|
||||||
runCatchingCancellable {
|
|
||||||
preference.summary = null
|
|
||||||
withContext(Dispatchers.Default) {
|
|
||||||
requireNotNull(repository?.getAuthProvider()?.getUsername())
|
|
||||||
}
|
|
||||||
}.onSuccess { username ->
|
|
||||||
preference.title = getString(R.string.logged_in_as, username)
|
|
||||||
}.onFailure { error ->
|
|
||||||
when {
|
|
||||||
error is AuthRequiredException -> Unit
|
|
||||||
ExceptionResolver.canResolve(error) -> {
|
|
||||||
ensureActive()
|
|
||||||
Snackbar.make(
|
|
||||||
listView ?: return@onFailure,
|
|
||||||
error.getDisplayMessage(preference.context.resources),
|
|
||||||
Snackbar.LENGTH_INDEFINITE,
|
|
||||||
).setAction(ExceptionResolver.getResolveStringId(error)) { resolveError(error) }
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> preference.summary = error.getDisplayMessage(preference.context.resources)
|
|
||||||
}
|
|
||||||
error.printStackTraceDebug()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resolveError(error: Throwable) {
|
|
||||||
view ?: return
|
|
||||||
viewLifecycleScope.launch {
|
|
||||||
if (exceptionResolver.resolve(error)) {
|
|
||||||
val pref = findPreference<Preference>(KEY_AUTH) ?: return@launch
|
|
||||||
val lifecycleOwner = awaitViewLifecycle()
|
|
||||||
loadUsername(lifecycleOwner, pref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
private const val KEY_AUTH = "auth"
|
|
||||||
|
|
||||||
private const val EXTRA_SOURCE = "source"
|
|
||||||
|
|
||||||
fun newInstance(source: MangaSource) = SourceSettingsFragment().withArgs(1) {
|
|
||||||
putSerializable(EXTRA_SOURCE, source)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package org.koitharu.kotatsu.settings
|
package org.koitharu.kotatsu.settings
|
||||||
|
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.SharedPreferences
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -8,6 +10,7 @@ import androidx.activity.result.ActivityResultCallback
|
|||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.TwoStatePreference
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
@@ -24,18 +27,21 @@ import org.koitharu.kotatsu.core.ui.BasePreferenceFragment
|
|||||||
import org.koitharu.kotatsu.core.util.FileSize
|
import org.koitharu.kotatsu.core.util.FileSize
|
||||||
import org.koitharu.kotatsu.core.util.ext.awaitStateAtLeast
|
import org.koitharu.kotatsu.core.util.ext.awaitStateAtLeast
|
||||||
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
|
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
|
||||||
import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope
|
import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope
|
||||||
import org.koitharu.kotatsu.local.data.CacheDir
|
import org.koitharu.kotatsu.local.data.CacheDir
|
||||||
import org.koitharu.kotatsu.local.data.LocalStorageManager
|
import org.koitharu.kotatsu.local.data.LocalStorageManager
|
||||||
import org.koitharu.kotatsu.search.domain.MangaSearchRepository
|
import org.koitharu.kotatsu.search.domain.MangaSearchRepository
|
||||||
import org.koitharu.kotatsu.settings.backup.BackupDialogFragment
|
import org.koitharu.kotatsu.settings.backup.BackupDialogFragment
|
||||||
import org.koitharu.kotatsu.settings.backup.RestoreDialogFragment
|
import org.koitharu.kotatsu.settings.backup.RestoreDialogFragment
|
||||||
|
import org.koitharu.kotatsu.settings.protect.ProtectSetupActivity
|
||||||
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
||||||
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class UserDataSettingsFragment : BasePreferenceFragment(R.string.data_and_privacy), ActivityResultCallback<Uri?> {
|
class UserDataSettingsFragment : BasePreferenceFragment(R.string.data_and_privacy),
|
||||||
|
SharedPreferences.OnSharedPreferenceChangeListener,
|
||||||
|
ActivityResultCallback<Uri?> {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var trackerRepo: TrackingRepository
|
lateinit var trackerRepo: TrackingRepository
|
||||||
@@ -64,6 +70,8 @@ class UserDataSettingsFragment : BasePreferenceFragment(R.string.data_and_privac
|
|||||||
addPreferencesFromResource(R.xml.pref_user_data)
|
addPreferencesFromResource(R.xml.pref_user_data)
|
||||||
findPreference<Preference>(AppSettings.KEY_SHORTCUTS)?.isVisible =
|
findPreference<Preference>(AppSettings.KEY_SHORTCUTS)?.isVisible =
|
||||||
shortcutsUpdater.isDynamicShortcutsAvailable()
|
shortcutsUpdater.isDynamicShortcutsAvailable()
|
||||||
|
findPreference<TwoStatePreference>(AppSettings.KEY_PROTECT_APP)
|
||||||
|
?.isChecked = !settings.appPassword.isNullOrEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
@@ -85,6 +93,12 @@ class UserDataSettingsFragment : BasePreferenceFragment(R.string.data_and_privac
|
|||||||
pref.summary = pref.context.resources.getQuantityString(R.plurals.items, items, items)
|
pref.summary = pref.context.resources.getQuantityString(R.plurals.items, items, items)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
settings.subscribe(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
settings.unsubscribe(this)
|
||||||
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPreferenceTreeClick(preference: Preference): Boolean {
|
override fun onPreferenceTreeClick(preference: Preference): Boolean {
|
||||||
@@ -145,10 +159,30 @@ class UserDataSettingsFragment : BasePreferenceFragment(R.string.data_and_privac
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AppSettings.KEY_PROTECT_APP -> {
|
||||||
|
val pref = (preference as? TwoStatePreference ?: return false)
|
||||||
|
if (pref.isChecked) {
|
||||||
|
pref.isChecked = false
|
||||||
|
startActivity(Intent(preference.context, ProtectSetupActivity::class.java))
|
||||||
|
} else {
|
||||||
|
settings.appPassword = null
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
else -> super.onPreferenceTreeClick(preference)
|
else -> super.onPreferenceTreeClick(preference)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||||
|
when (key) {
|
||||||
|
AppSettings.KEY_APP_PASSWORD -> {
|
||||||
|
findPreference<TwoStatePreference>(AppSettings.KEY_PROTECT_APP)
|
||||||
|
?.isChecked = !settings.appPassword.isNullOrEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onActivityResult(result: Uri?) {
|
override fun onActivityResult(result: Uri?) {
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
RestoreDialogFragment.show(childFragmentManager, result)
|
RestoreDialogFragment.show(childFragmentManager, result)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.koitharu.kotatsu.settings
|
package org.koitharu.kotatsu.settings.sources
|
||||||
|
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import androidx.preference.EditTextPreference
|
import androidx.preference.EditTextPreference
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package org.koitharu.kotatsu.settings.sources
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
||||||
|
import org.koitharu.kotatsu.core.ui.BasePreferenceFragment
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.observe
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.observeEvent
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.withArgs
|
||||||
|
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||||
|
import org.koitharu.kotatsu.settings.sources.auth.SourceAuthActivity
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class SourceSettingsFragment : BasePreferenceFragment(0) {
|
||||||
|
|
||||||
|
private val viewModel: SourceSettingsViewModel by viewModels()
|
||||||
|
private val exceptionResolver = ExceptionResolver(this)
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
setTitle(viewModel.source.title)
|
||||||
|
viewModel.onResume()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
preferenceManager.sharedPreferencesName = viewModel.source.name
|
||||||
|
addPreferencesFromResource(R.xml.pref_source)
|
||||||
|
addPreferencesFromRepository(viewModel.repository)
|
||||||
|
|
||||||
|
findPreference<Preference>(KEY_AUTH)?.run {
|
||||||
|
val authProvider = viewModel.repository.getAuthProvider()
|
||||||
|
isVisible = authProvider != null
|
||||||
|
isEnabled = authProvider?.isAuthorized == false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
viewModel.username.observe(viewLifecycleOwner) { username ->
|
||||||
|
findPreference<Preference>(KEY_AUTH)?.summary = username?.let {
|
||||||
|
getString(R.string.logged_in_as, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewModel.onError.observeEvent(viewLifecycleOwner, ::onError)
|
||||||
|
viewModel.isLoading.observe(viewLifecycleOwner) { isLoading ->
|
||||||
|
findPreference<Preference>(KEY_AUTH)?.isEnabled = !isLoading
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPreferenceTreeClick(preference: Preference): Boolean {
|
||||||
|
return when (preference.key) {
|
||||||
|
KEY_AUTH -> {
|
||||||
|
startActivity(SourceAuthActivity.newIntent(preference.context, viewModel.source))
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> super.onPreferenceTreeClick(preference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onError(error: Throwable) {
|
||||||
|
val snackbar = Snackbar.make(
|
||||||
|
listView ?: return,
|
||||||
|
error.getDisplayMessage(resources),
|
||||||
|
Snackbar.LENGTH_INDEFINITE,
|
||||||
|
)
|
||||||
|
if (ExceptionResolver.canResolve(error)) {
|
||||||
|
snackbar.setAction(ExceptionResolver.getResolveStringId(error)) { resolveError(error) }
|
||||||
|
}
|
||||||
|
snackbar.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resolveError(error: Throwable) {
|
||||||
|
view ?: return
|
||||||
|
viewLifecycleScope.launch {
|
||||||
|
if (exceptionResolver.resolve(error)) {
|
||||||
|
viewModel.onResume()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private const val KEY_AUTH = "auth"
|
||||||
|
|
||||||
|
const val EXTRA_SOURCE = "source"
|
||||||
|
|
||||||
|
fun newInstance(source: MangaSource) = SourceSettingsFragment().withArgs(1) {
|
||||||
|
putSerializable(EXTRA_SOURCE, source)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package org.koitharu.kotatsu.settings.sources
|
||||||
|
|
||||||
|
import androidx.lifecycle.SavedStateHandle
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||||
|
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
|
||||||
|
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.require
|
||||||
|
import org.koitharu.kotatsu.parsers.exception.AuthRequiredException
|
||||||
|
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class SourceSettingsViewModel @Inject constructor(
|
||||||
|
savedStateHandle: SavedStateHandle,
|
||||||
|
mangaRepositoryFactory: MangaRepository.Factory,
|
||||||
|
) : BaseViewModel() {
|
||||||
|
|
||||||
|
val source = savedStateHandle.require<MangaSource>(SourceSettingsFragment.EXTRA_SOURCE)
|
||||||
|
val repository = mangaRepositoryFactory.create(source) as RemoteMangaRepository
|
||||||
|
|
||||||
|
val username = MutableStateFlow<String?>(null)
|
||||||
|
private var usernameLoadJob: Job? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
loadUsername()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onResume() {
|
||||||
|
if (usernameLoadJob?.isActive != true) {
|
||||||
|
loadUsername()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadUsername() {
|
||||||
|
launchLoadingJob(Dispatchers.Default) {
|
||||||
|
try {
|
||||||
|
username.value = null
|
||||||
|
username.value = repository.getAuthProvider()?.getUsername()
|
||||||
|
} catch (_: AuthRequiredException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,7 +26,6 @@ import org.koitharu.kotatsu.core.util.ext.observeEvent
|
|||||||
import org.koitharu.kotatsu.databinding.FragmentSettingsSourcesBinding
|
import org.koitharu.kotatsu.databinding.FragmentSettingsSourcesBinding
|
||||||
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
|
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
|
||||||
import org.koitharu.kotatsu.settings.SettingsActivity
|
import org.koitharu.kotatsu.settings.SettingsActivity
|
||||||
import org.koitharu.kotatsu.settings.SourceSettingsFragment
|
|
||||||
import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigAdapter
|
import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigAdapter
|
||||||
import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigListener
|
import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigListener
|
||||||
import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem
|
import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem
|
||||||
|
|||||||
@@ -56,14 +56,13 @@ class TrackerSettingsFragment :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
updateDozePreference()
|
||||||
updateCategoriesEnabled()
|
updateCategoriesEnabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
findPreference<Preference>(KEY_IGNORE_DOZE)?.run {
|
updateDozePreference()
|
||||||
isVisible = isDozeIgnoreAvailable(context)
|
|
||||||
}
|
|
||||||
updateNotificationsSummary()
|
updateNotificationsSummary()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,8 +81,7 @@ class TrackerSettingsFragment :
|
|||||||
when (key) {
|
when (key) {
|
||||||
AppSettings.KEY_TRACKER_NOTIFICATIONS -> updateNotificationsSummary()
|
AppSettings.KEY_TRACKER_NOTIFICATIONS -> updateNotificationsSummary()
|
||||||
AppSettings.KEY_TRACK_SOURCES,
|
AppSettings.KEY_TRACK_SOURCES,
|
||||||
AppSettings.KEY_TRACKER_ENABLED,
|
AppSettings.KEY_TRACKER_ENABLED -> updateCategoriesEnabled()
|
||||||
-> updateCategoriesEnabled()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,9 +102,7 @@ class TrackerSettingsFragment :
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> super.onPreferenceTreeClick(preference)
|
||||||
super.onPreferenceTreeClick(preference)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AppSettings.KEY_TRACK_CATEGORIES -> {
|
AppSettings.KEY_TRACK_CATEGORIES -> {
|
||||||
@@ -123,6 +119,12 @@ class TrackerSettingsFragment :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateDozePreference() {
|
||||||
|
findPreference<Preference>(KEY_IGNORE_DOZE)?.run {
|
||||||
|
isVisible = isDozeIgnoreAvailable(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateNotificationsSummary() {
|
private fun updateNotificationsSummary() {
|
||||||
val pref = findPreference<Preference>(AppSettings.KEY_NOTIFICATIONS_SETTINGS) ?: return
|
val pref = findPreference<Preference>(AppSettings.KEY_NOTIFICATIONS_SETTINGS) ?: return
|
||||||
pref.setSummary(
|
pref.setSummary(
|
||||||
|
|||||||
Reference in New Issue
Block a user