Fix settings issues
parent
b930272221
commit
b1ba70bf77
@ -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,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.settings
|
||||
package org.koitharu.kotatsu.settings.sources
|
||||
|
||||
import android.view.inputmethod.EditorInfo
|
||||
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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue