Refactor error handling
This commit is contained in:
@@ -1,14 +1,12 @@
|
|||||||
package org.koitharu.kotatsu.base.ui.util
|
package org.koitharu.kotatsu.base.ui.util
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.ContextWrapper
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.domain.reverseAsync
|
import org.koitharu.kotatsu.base.domain.reverseAsync
|
||||||
import org.koitharu.kotatsu.main.ui.owners.BottomNavOwner
|
import org.koitharu.kotatsu.main.ui.owners.BottomNavOwner
|
||||||
|
import org.koitharu.kotatsu.utils.ext.findActivity
|
||||||
|
|
||||||
class ReversibleActionObserver(
|
class ReversibleActionObserver(
|
||||||
private val snackbarHost: View,
|
private val snackbarHost: View,
|
||||||
@@ -29,10 +27,4 @@ class ReversibleActionObserver(
|
|||||||
}
|
}
|
||||||
snackbar.show()
|
snackbar.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Context.findActivity(): Activity? = when (this) {
|
|
||||||
is Activity -> this
|
|
||||||
is ContextWrapper -> baseContext.findActivity()
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package org.koitharu.kotatsu.bookmarks.ui
|
package org.koitharu.kotatsu.bookmarks.ui
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.core.graphics.Insets
|
import androidx.core.graphics.Insets
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
@@ -10,7 +14,6 @@ import androidx.fragment.app.viewModels
|
|||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import javax.inject.Inject
|
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.domain.reverseAsync
|
import org.koitharu.kotatsu.base.domain.reverseAsync
|
||||||
import org.koitharu.kotatsu.base.ui.BaseFragment
|
import org.koitharu.kotatsu.base.ui.BaseFragment
|
||||||
@@ -24,6 +27,7 @@ import org.koitharu.kotatsu.bookmarks.data.ids
|
|||||||
import org.koitharu.kotatsu.bookmarks.domain.Bookmark
|
import org.koitharu.kotatsu.bookmarks.domain.Bookmark
|
||||||
import org.koitharu.kotatsu.bookmarks.ui.adapter.BookmarksGroupAdapter
|
import org.koitharu.kotatsu.bookmarks.ui.adapter.BookmarksGroupAdapter
|
||||||
import org.koitharu.kotatsu.bookmarks.ui.model.BookmarksGroup
|
import org.koitharu.kotatsu.bookmarks.ui.model.BookmarksGroup
|
||||||
|
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
||||||
import org.koitharu.kotatsu.databinding.FragmentListSimpleBinding
|
import org.koitharu.kotatsu.databinding.FragmentListSimpleBinding
|
||||||
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||||
import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener
|
import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener
|
||||||
@@ -32,9 +36,9 @@ import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
|
|||||||
import org.koitharu.kotatsu.main.ui.owners.SnackbarOwner
|
import org.koitharu.kotatsu.main.ui.owners.SnackbarOwner
|
||||||
import org.koitharu.kotatsu.parsers.model.Manga
|
import org.koitharu.kotatsu.parsers.model.Manga
|
||||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
||||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
|
||||||
import org.koitharu.kotatsu.utils.ext.invalidateNestedItemDecorations
|
import org.koitharu.kotatsu.utils.ext.invalidateNestedItemDecorations
|
||||||
import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf
|
import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class BookmarksFragment :
|
class BookmarksFragment :
|
||||||
@@ -76,7 +80,7 @@ class BookmarksFragment :
|
|||||||
binding.recyclerView.addItemDecoration(spacingDecoration)
|
binding.recyclerView.addItemDecoration(spacingDecoration)
|
||||||
|
|
||||||
viewModel.content.observe(viewLifecycleOwner, ::onListChanged)
|
viewModel.content.observe(viewLifecycleOwner, ::onListChanged)
|
||||||
viewModel.onError.observe(viewLifecycleOwner, ::onError)
|
viewModel.onError.observe(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this))
|
||||||
viewModel.onActionDone.observe(viewLifecycleOwner, ::onActionDone)
|
viewModel.onActionDone.observe(viewLifecycleOwner, ::onActionDone)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,6 +136,7 @@ class BookmarksFragment :
|
|||||||
mode.finish()
|
mode.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,14 +159,6 @@ class BookmarksFragment :
|
|||||||
adapter?.items = list
|
adapter?.items = list
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onError(e: Throwable) {
|
|
||||||
Snackbar.make(
|
|
||||||
binding.recyclerView,
|
|
||||||
e.getDisplayMessage(resources),
|
|
||||||
Snackbar.LENGTH_SHORT,
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onActionDone(action: ReversibleAction) {
|
private fun onActionDone(action: ReversibleAction) {
|
||||||
val handle = action.handle
|
val handle = action.handle
|
||||||
val length = if (handle == null) Snackbar.LENGTH_SHORT else Snackbar.LENGTH_LONG
|
val length = if (handle == null) Snackbar.LENGTH_SHORT else Snackbar.LENGTH_LONG
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package org.koitharu.kotatsu.core.exceptions.resolve
|
||||||
|
|
||||||
|
import android.content.DialogInterface
|
||||||
|
import android.view.View
|
||||||
|
import androidx.core.util.Consumer
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.core.ui.MangaErrorDialog
|
||||||
|
import org.koitharu.kotatsu.parsers.exception.ParseException
|
||||||
|
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
||||||
|
|
||||||
|
class DialogErrorObserver(
|
||||||
|
host: View,
|
||||||
|
fragment: Fragment?,
|
||||||
|
resolver: ExceptionResolver?,
|
||||||
|
private val onResolved: Consumer<Boolean>?,
|
||||||
|
) : ErrorObserver(host, fragment, resolver, onResolved) {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
host: View,
|
||||||
|
fragment: Fragment?,
|
||||||
|
) : this(host, fragment, null, null)
|
||||||
|
|
||||||
|
override fun onChanged(error: Throwable?) {
|
||||||
|
if (error == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val listener = DialogListener(error)
|
||||||
|
val dialogBuilder = MaterialAlertDialogBuilder(activity ?: host.context)
|
||||||
|
.setMessage(error.getDisplayMessage(host.context.resources))
|
||||||
|
.setNegativeButton(R.string.close, listener)
|
||||||
|
.setOnCancelListener(listener)
|
||||||
|
if (canResolve(error)) {
|
||||||
|
dialogBuilder.setPositiveButton(ExceptionResolver.getResolveStringId(error), listener)
|
||||||
|
} else if (error is ParseException) {
|
||||||
|
val fm = fragmentManager
|
||||||
|
if (fm != null) {
|
||||||
|
dialogBuilder.setPositiveButton(R.string.details) { _, _ ->
|
||||||
|
MangaErrorDialog.show(fm, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val dialog = dialogBuilder.create()
|
||||||
|
if (activity != null) {
|
||||||
|
dialog.setOwnerActivity(activity)
|
||||||
|
}
|
||||||
|
dialog.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class DialogListener(
|
||||||
|
private val error: Throwable,
|
||||||
|
) : DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
|
||||||
|
|
||||||
|
override fun onClick(dialog: DialogInterface?, which: Int) {
|
||||||
|
when (which) {
|
||||||
|
DialogInterface.BUTTON_NEGATIVE -> onResolved?.accept(false)
|
||||||
|
DialogInterface.BUTTON_POSITIVE -> resolve(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCancel(dialog: DialogInterface?) {
|
||||||
|
onResolved?.accept(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package org.koitharu.kotatsu.core.exceptions.resolve
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.util.Consumer
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import androidx.lifecycle.LifecycleCoroutineScope
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.lifecycle.coroutineScope
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.koitharu.kotatsu.utils.ext.findActivity
|
||||||
|
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
|
||||||
|
|
||||||
|
abstract class ErrorObserver(
|
||||||
|
protected val host: View,
|
||||||
|
protected val fragment: Fragment?,
|
||||||
|
private val resolver: ExceptionResolver?,
|
||||||
|
private val onResolved: Consumer<Boolean>?,
|
||||||
|
) : Observer<Throwable> {
|
||||||
|
|
||||||
|
protected val activity = host.context.findActivity()
|
||||||
|
|
||||||
|
private val lifecycleScope: LifecycleCoroutineScope
|
||||||
|
get() = checkNotNull(fragment?.viewLifecycleScope ?: (activity as? LifecycleOwner)?.lifecycle?.coroutineScope)
|
||||||
|
|
||||||
|
protected val fragmentManager: FragmentManager?
|
||||||
|
get() = fragment?.childFragmentManager ?: (activity as? AppCompatActivity)?.supportFragmentManager
|
||||||
|
|
||||||
|
protected fun canResolve(error: Throwable): Boolean {
|
||||||
|
return resolver != null && ExceptionResolver.canResolve(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun resolve(error: Throwable) {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
val isResolved = resolver?.resolve(error) ?: false
|
||||||
|
if (isActive) {
|
||||||
|
onResolved?.accept(isResolved)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package org.koitharu.kotatsu.core.exceptions.resolve
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import androidx.core.util.Consumer
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.core.ui.MangaErrorDialog
|
||||||
|
import org.koitharu.kotatsu.main.ui.owners.BottomNavOwner
|
||||||
|
import org.koitharu.kotatsu.parsers.exception.ParseException
|
||||||
|
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
||||||
|
|
||||||
|
class SnackbarErrorObserver(
|
||||||
|
host: View,
|
||||||
|
fragment: Fragment?,
|
||||||
|
resolver: ExceptionResolver?,
|
||||||
|
onResolved: Consumer<Boolean>?,
|
||||||
|
) : ErrorObserver(host, fragment, resolver, onResolved) {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
host: View,
|
||||||
|
fragment: Fragment?,
|
||||||
|
) : this(host, fragment, null, null)
|
||||||
|
|
||||||
|
override fun onChanged(error: Throwable?) {
|
||||||
|
if (error == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val snackbar = Snackbar.make(host, error.getDisplayMessage(host.context.resources), Snackbar.LENGTH_SHORT)
|
||||||
|
if (activity is BottomNavOwner) {
|
||||||
|
snackbar.anchorView = activity.bottomNav
|
||||||
|
}
|
||||||
|
if (canResolve(error)) {
|
||||||
|
snackbar.setAction(ExceptionResolver.getResolveStringId(error)) {
|
||||||
|
resolve(error)
|
||||||
|
}
|
||||||
|
} else if (error is ParseException) {
|
||||||
|
val fm = fragmentManager
|
||||||
|
if (fm != null) {
|
||||||
|
snackbar.setAction(R.string.details) {
|
||||||
|
MangaErrorDialog.show(fm, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snackbar.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,24 +12,20 @@ import androidx.fragment.app.FragmentManager
|
|||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.ui.AlertDialogFragment
|
import org.koitharu.kotatsu.base.ui.AlertDialogFragment
|
||||||
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
|
||||||
import org.koitharu.kotatsu.databinding.DialogMangaErrorBinding
|
import org.koitharu.kotatsu.databinding.DialogMangaErrorBinding
|
||||||
import org.koitharu.kotatsu.parsers.model.Manga
|
import org.koitharu.kotatsu.parsers.exception.ParseException
|
||||||
import org.koitharu.kotatsu.utils.ext.report
|
import org.koitharu.kotatsu.utils.ext.report
|
||||||
import org.koitharu.kotatsu.utils.ext.requireParcelable
|
|
||||||
import org.koitharu.kotatsu.utils.ext.requireSerializable
|
import org.koitharu.kotatsu.utils.ext.requireSerializable
|
||||||
import org.koitharu.kotatsu.utils.ext.withArgs
|
import org.koitharu.kotatsu.utils.ext.withArgs
|
||||||
|
|
||||||
class MangaErrorDialog : AlertDialogFragment<DialogMangaErrorBinding>() {
|
class MangaErrorDialog : AlertDialogFragment<DialogMangaErrorBinding>() {
|
||||||
|
|
||||||
private lateinit var error: Throwable
|
private lateinit var exception: ParseException
|
||||||
private lateinit var manga: Manga
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
val args = requireArguments()
|
val args = requireArguments()
|
||||||
manga = args.requireParcelable<ParcelableManga>(ARG_MANGA).manga
|
exception = args.requireSerializable(ARG_ERROR)
|
||||||
error = args.requireSerializable(ARG_ERROR)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): DialogMangaErrorBinding {
|
override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): DialogMangaErrorBinding {
|
||||||
@@ -42,8 +38,8 @@ class MangaErrorDialog : AlertDialogFragment<DialogMangaErrorBinding>() {
|
|||||||
movementMethod = LinkMovementMethod.getInstance()
|
movementMethod = LinkMovementMethod.getInstance()
|
||||||
text = context.getString(
|
text = context.getString(
|
||||||
R.string.manga_error_description_pattern,
|
R.string.manga_error_description_pattern,
|
||||||
this@MangaErrorDialog.error.message?.htmlEncode().orEmpty(),
|
exception.message?.htmlEncode().orEmpty(),
|
||||||
manga.publicUrl,
|
exception.url,
|
||||||
).parseAsHtml(HtmlCompat.FROM_HTML_MODE_LEGACY)
|
).parseAsHtml(HtmlCompat.FROM_HTML_MODE_LEGACY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,7 +50,7 @@ class MangaErrorDialog : AlertDialogFragment<DialogMangaErrorBinding>() {
|
|||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setPositiveButton(R.string.report) { _, _ ->
|
.setPositiveButton(R.string.report) { _, _ ->
|
||||||
dismiss()
|
dismiss()
|
||||||
error.report()
|
exception.report()
|
||||||
}.setTitle(R.string.error_occurred)
|
}.setTitle(R.string.error_occurred)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,10 +58,8 @@ class MangaErrorDialog : AlertDialogFragment<DialogMangaErrorBinding>() {
|
|||||||
|
|
||||||
private const val TAG = "MangaErrorDialog"
|
private const val TAG = "MangaErrorDialog"
|
||||||
private const val ARG_ERROR = "error"
|
private const val ARG_ERROR = "error"
|
||||||
private const val ARG_MANGA = "manga"
|
|
||||||
|
|
||||||
fun show(fm: FragmentManager, manga: Manga, error: Throwable) = MangaErrorDialog().withArgs(2) {
|
fun show(fm: FragmentManager, error: ParseException) = MangaErrorDialog().withArgs(1) {
|
||||||
putParcelable(ARG_MANGA, ParcelableManga(manga, false))
|
|
||||||
putSerializable(ARG_ERROR, error)
|
putSerializable(ARG_ERROR, error)
|
||||||
}.show(fm, TAG)
|
}.show(fm, TAG)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,9 @@ import org.koitharu.kotatsu.R
|
|||||||
import org.koitharu.kotatsu.base.domain.MangaIntent
|
import org.koitharu.kotatsu.base.domain.MangaIntent
|
||||||
import org.koitharu.kotatsu.base.ui.BaseActivity
|
import org.koitharu.kotatsu.base.ui.BaseActivity
|
||||||
import org.koitharu.kotatsu.base.ui.widgets.BottomSheetHeaderBar
|
import org.koitharu.kotatsu.base.ui.widgets.BottomSheetHeaderBar
|
||||||
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
||||||
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
||||||
import org.koitharu.kotatsu.core.os.ShortcutsUpdater
|
import org.koitharu.kotatsu.core.os.ShortcutsUpdater
|
||||||
import org.koitharu.kotatsu.core.ui.MangaErrorDialog
|
|
||||||
import org.koitharu.kotatsu.databinding.ActivityDetailsBinding
|
import org.koitharu.kotatsu.databinding.ActivityDetailsBinding
|
||||||
import org.koitharu.kotatsu.details.service.MangaPrefetchService
|
import org.koitharu.kotatsu.details.service.MangaPrefetchService
|
||||||
import org.koitharu.kotatsu.details.ui.model.ChapterListItem
|
import org.koitharu.kotatsu.details.ui.model.ChapterListItem
|
||||||
@@ -45,7 +44,6 @@ import org.koitharu.kotatsu.reader.ui.ReaderState
|
|||||||
import org.koitharu.kotatsu.utils.ViewBadge
|
import org.koitharu.kotatsu.utils.ViewBadge
|
||||||
import org.koitharu.kotatsu.utils.ext.assistedViewModels
|
import org.koitharu.kotatsu.utils.ext.assistedViewModels
|
||||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
||||||
import org.koitharu.kotatsu.utils.ext.isReportable
|
|
||||||
import org.koitharu.kotatsu.utils.ext.setNavigationBarTransparentCompat
|
import org.koitharu.kotatsu.utils.ext.setNavigationBarTransparentCompat
|
||||||
import org.koitharu.kotatsu.utils.ext.textAndVisible
|
import org.koitharu.kotatsu.utils.ext.textAndVisible
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -105,7 +103,19 @@ class DetailsActivity :
|
|||||||
viewModel.manga.observe(this, ::onMangaUpdated)
|
viewModel.manga.observe(this, ::onMangaUpdated)
|
||||||
viewModel.newChaptersCount.observe(this, ::onNewChaptersChanged)
|
viewModel.newChaptersCount.observe(this, ::onNewChaptersChanged)
|
||||||
viewModel.onMangaRemoved.observe(this, ::onMangaRemoved)
|
viewModel.onMangaRemoved.observe(this, ::onMangaRemoved)
|
||||||
viewModel.onError.observe(this, ::onError)
|
viewModel.onError.observe(
|
||||||
|
this,
|
||||||
|
SnackbarErrorObserver(
|
||||||
|
host = binding.containerDetails,
|
||||||
|
fragment = null,
|
||||||
|
resolver = exceptionResolver,
|
||||||
|
onResolved = { isResolved ->
|
||||||
|
if (isResolved) {
|
||||||
|
viewModel.reload()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
viewModel.onShowToast.observe(this) {
|
viewModel.onShowToast.observe(this) {
|
||||||
makeSnackbar(getString(it), Snackbar.LENGTH_SHORT).show()
|
makeSnackbar(getString(it), Snackbar.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
@@ -191,37 +201,6 @@ class DetailsActivity :
|
|||||||
finishAfterTransition()
|
finishAfterTransition()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onError(e: Throwable) {
|
|
||||||
val manga = viewModel.manga.value
|
|
||||||
when {
|
|
||||||
ExceptionResolver.canResolve(e) -> {
|
|
||||||
resolveError(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
manga == null -> {
|
|
||||||
Toast.makeText(this, e.getDisplayMessage(resources), Toast.LENGTH_LONG).show()
|
|
||||||
finishAfterTransition()
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
val snackbar = makeSnackbar(
|
|
||||||
e.getDisplayMessage(resources),
|
|
||||||
if (viewModel.manga.value?.chapters == null) {
|
|
||||||
Snackbar.LENGTH_INDEFINITE
|
|
||||||
} else {
|
|
||||||
Snackbar.LENGTH_LONG
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if (e.isReportable()) {
|
|
||||||
snackbar.setAction(R.string.details) {
|
|
||||||
MangaErrorDialog.show(supportFragmentManager, manga, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
snackbar.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onWindowInsetsChanged(insets: Insets) {
|
override fun onWindowInsetsChanged(insets: Insets) {
|
||||||
binding.root.updatePadding(
|
binding.root.updatePadding(
|
||||||
left = insets.left,
|
left = insets.left,
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import androidx.recyclerview.widget.GridLayoutManager
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import com.google.android.material.snackbar.Snackbar
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.ui.BaseFragment
|
import org.koitharu.kotatsu.base.ui.BaseFragment
|
||||||
@@ -22,6 +21,7 @@ import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner
|
|||||||
import org.koitharu.kotatsu.base.ui.util.ReversibleActionObserver
|
import org.koitharu.kotatsu.base.ui.util.ReversibleActionObserver
|
||||||
import org.koitharu.kotatsu.base.ui.util.SpanSizeResolver
|
import org.koitharu.kotatsu.base.ui.util.SpanSizeResolver
|
||||||
import org.koitharu.kotatsu.bookmarks.ui.BookmarksActivity
|
import org.koitharu.kotatsu.bookmarks.ui.BookmarksActivity
|
||||||
|
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
||||||
import org.koitharu.kotatsu.databinding.FragmentExploreBinding
|
import org.koitharu.kotatsu.databinding.FragmentExploreBinding
|
||||||
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||||
import org.koitharu.kotatsu.explore.ui.adapter.ExploreAdapter
|
import org.koitharu.kotatsu.explore.ui.adapter.ExploreAdapter
|
||||||
@@ -29,14 +29,12 @@ import org.koitharu.kotatsu.explore.ui.adapter.ExploreListEventListener
|
|||||||
import org.koitharu.kotatsu.explore.ui.model.ExploreItem
|
import org.koitharu.kotatsu.explore.ui.model.ExploreItem
|
||||||
import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity
|
import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity
|
||||||
import org.koitharu.kotatsu.history.ui.HistoryActivity
|
import org.koitharu.kotatsu.history.ui.HistoryActivity
|
||||||
import org.koitharu.kotatsu.main.ui.owners.BottomNavOwner
|
|
||||||
import org.koitharu.kotatsu.parsers.model.Manga
|
import org.koitharu.kotatsu.parsers.model.Manga
|
||||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||||
import org.koitharu.kotatsu.search.ui.MangaListActivity
|
import org.koitharu.kotatsu.search.ui.MangaListActivity
|
||||||
import org.koitharu.kotatsu.settings.SettingsActivity
|
import org.koitharu.kotatsu.settings.SettingsActivity
|
||||||
import org.koitharu.kotatsu.suggestions.ui.SuggestionsActivity
|
import org.koitharu.kotatsu.suggestions.ui.SuggestionsActivity
|
||||||
import org.koitharu.kotatsu.utils.ext.addMenuProvider
|
import org.koitharu.kotatsu.utils.ext.addMenuProvider
|
||||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@@ -74,7 +72,7 @@ class ExploreFragment :
|
|||||||
viewModel.content.observe(viewLifecycleOwner) {
|
viewModel.content.observe(viewLifecycleOwner) {
|
||||||
exploreAdapter?.items = it
|
exploreAdapter?.items = it
|
||||||
}
|
}
|
||||||
viewModel.onError.observe(viewLifecycleOwner, ::onError)
|
viewModel.onError.observe(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this))
|
||||||
viewModel.onOpenManga.observe(viewLifecycleOwner, ::onOpenManga)
|
viewModel.onOpenManga.observe(viewLifecycleOwner, ::onOpenManga)
|
||||||
viewModel.onActionDone.observe(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView))
|
viewModel.onActionDone.observe(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView))
|
||||||
viewModel.isGrid.observe(viewLifecycleOwner, ::onGridModeChanged)
|
viewModel.isGrid.observe(viewLifecycleOwner, ::onGridModeChanged)
|
||||||
@@ -129,16 +127,6 @@ class ExploreFragment :
|
|||||||
|
|
||||||
override fun onEmptyActionClick() = onManageClick(requireView())
|
override fun onEmptyActionClick() = onManageClick(requireView())
|
||||||
|
|
||||||
private fun onError(e: Throwable) {
|
|
||||||
val snackbar = Snackbar.make(
|
|
||||||
binding.recyclerView,
|
|
||||||
e.getDisplayMessage(resources),
|
|
||||||
Snackbar.LENGTH_SHORT,
|
|
||||||
)
|
|
||||||
snackbar.anchorView = (activity as? BottomNavOwner)?.bottomNav
|
|
||||||
snackbar.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onOpenManga(manga: Manga) {
|
private fun onOpenManga(manga: Manga) {
|
||||||
val intent = DetailsActivity.newIntent(context ?: return, manga)
|
val intent = DetailsActivity.newIntent(context ?: return, manga)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ import androidx.core.view.updatePadding
|
|||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import com.google.android.material.snackbar.Snackbar
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.ui.BaseActivity
|
import org.koitharu.kotatsu.base.ui.BaseActivity
|
||||||
import org.koitharu.kotatsu.base.ui.list.ListSelectionController
|
import org.koitharu.kotatsu.base.ui.list.ListSelectionController
|
||||||
|
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
||||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
import org.koitharu.kotatsu.databinding.ActivityCategoriesBinding
|
import org.koitharu.kotatsu.databinding.ActivityCategoriesBinding
|
||||||
import org.koitharu.kotatsu.favourites.ui.FavouritesActivity
|
import org.koitharu.kotatsu.favourites.ui.FavouritesActivity
|
||||||
@@ -31,7 +31,6 @@ import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEdit
|
|||||||
import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener
|
import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener
|
||||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||||
import org.koitharu.kotatsu.parsers.model.SortOrder
|
import org.koitharu.kotatsu.parsers.model.SortOrder
|
||||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
|
||||||
import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf
|
import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -72,7 +71,7 @@ class FavouriteCategoriesActivity :
|
|||||||
onBackPressedDispatcher.addCallback(exitReorderModeCallback)
|
onBackPressedDispatcher.addCallback(exitReorderModeCallback)
|
||||||
|
|
||||||
viewModel.detalizedCategories.observe(this, ::onCategoriesChanged)
|
viewModel.detalizedCategories.observe(this, ::onCategoriesChanged)
|
||||||
viewModel.onError.observe(this, ::onError)
|
viewModel.onError.observe(this, SnackbarErrorObserver(binding.recyclerView, null))
|
||||||
viewModel.isInReorderMode.observe(this, ::onReorderModeChanged)
|
viewModel.isInReorderMode.observe(this, ::onReorderModeChanged)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,11 +145,6 @@ class FavouriteCategoriesActivity :
|
|||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onError(e: Throwable) {
|
|
||||||
Snackbar.make(binding.recyclerView, e.getDisplayMessage(resources), Snackbar.LENGTH_LONG)
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onReorderModeChanged(isReorderMode: Boolean) {
|
private fun onReorderModeChanged(isReorderMode: Boolean) {
|
||||||
val transition = Fade().apply {
|
val transition = Fade().apply {
|
||||||
duration = resources.getInteger(android.R.integer.config_shortAnimTime).toLong()
|
duration = resources.getInteger(android.R.integer.config_shortAnimTime).toLong()
|
||||||
|
|||||||
@@ -31,9 +31,8 @@ import org.koitharu.kotatsu.base.ui.list.decor.SpacingItemDecoration
|
|||||||
import org.koitharu.kotatsu.base.ui.list.decor.TypedSpacingItemDecoration
|
import org.koitharu.kotatsu.base.ui.list.decor.TypedSpacingItemDecoration
|
||||||
import org.koitharu.kotatsu.base.ui.list.fastscroll.FastScroller
|
import org.koitharu.kotatsu.base.ui.list.fastscroll.FastScroller
|
||||||
import org.koitharu.kotatsu.base.ui.util.ReversibleAction
|
import org.koitharu.kotatsu.base.ui.util.ReversibleAction
|
||||||
import org.koitharu.kotatsu.browser.cloudflare.CloudFlareDialog
|
|
||||||
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
|
|
||||||
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
||||||
|
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
||||||
import org.koitharu.kotatsu.core.prefs.ListMode
|
import org.koitharu.kotatsu.core.prefs.ListMode
|
||||||
import org.koitharu.kotatsu.databinding.FragmentListBinding
|
import org.koitharu.kotatsu.databinding.FragmentListBinding
|
||||||
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||||
@@ -55,7 +54,6 @@ import org.koitharu.kotatsu.search.ui.MangaListActivity
|
|||||||
import org.koitharu.kotatsu.utils.ShareHelper
|
import org.koitharu.kotatsu.utils.ShareHelper
|
||||||
import org.koitharu.kotatsu.utils.ext.addMenuProvider
|
import org.koitharu.kotatsu.utils.ext.addMenuProvider
|
||||||
import org.koitharu.kotatsu.utils.ext.clearItemDecorations
|
import org.koitharu.kotatsu.utils.ext.clearItemDecorations
|
||||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
|
||||||
import org.koitharu.kotatsu.utils.ext.getThemeColor
|
import org.koitharu.kotatsu.utils.ext.getThemeColor
|
||||||
import org.koitharu.kotatsu.utils.ext.measureHeight
|
import org.koitharu.kotatsu.utils.ext.measureHeight
|
||||||
import org.koitharu.kotatsu.utils.ext.resolveDp
|
import org.koitharu.kotatsu.utils.ext.resolveDp
|
||||||
@@ -128,7 +126,7 @@ abstract class MangaListFragment :
|
|||||||
viewModel.gridScale.observe(viewLifecycleOwner, ::onGridScaleChanged)
|
viewModel.gridScale.observe(viewLifecycleOwner, ::onGridScaleChanged)
|
||||||
viewModel.isLoading.observe(viewLifecycleOwner, ::onLoadingStateChanged)
|
viewModel.isLoading.observe(viewLifecycleOwner, ::onLoadingStateChanged)
|
||||||
viewModel.content.observe(viewLifecycleOwner, ::onListChanged)
|
viewModel.content.observe(viewLifecycleOwner, ::onListChanged)
|
||||||
viewModel.onError.observe(viewLifecycleOwner, ::onError)
|
viewModel.onError.observe(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this))
|
||||||
viewModel.onActionDone.observe(viewLifecycleOwner, ::onActionDone)
|
viewModel.onActionDone.observe(viewLifecycleOwner, ::onActionDone)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,18 +173,6 @@ abstract class MangaListFragment :
|
|||||||
listAdapter?.setItems(list, listCommitCallback)
|
listAdapter?.setItems(list, listCommitCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onError(e: Throwable) {
|
|
||||||
if (e is CloudFlareProtectedException) {
|
|
||||||
CloudFlareDialog.newInstance(e.url, e.headers).show(childFragmentManager, CloudFlareDialog.TAG)
|
|
||||||
} else {
|
|
||||||
Snackbar.make(
|
|
||||||
binding.recyclerView,
|
|
||||||
e.getDisplayMessage(resources),
|
|
||||||
Snackbar.LENGTH_SHORT,
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onActionDone(action: ReversibleAction) {
|
private fun onActionDone(action: ReversibleAction) {
|
||||||
val handle = action.handle
|
val handle = action.handle
|
||||||
val length = if (handle == null) Snackbar.LENGTH_SHORT else Snackbar.LENGTH_LONG
|
val length = if (handle == null) Snackbar.LENGTH_SHORT else Snackbar.LENGTH_LONG
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_
|
|||||||
import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL
|
import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL
|
||||||
import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
|
import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
|
||||||
import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP
|
import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP
|
||||||
import com.google.android.material.snackbar.Snackbar
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -41,6 +40,7 @@ import kotlinx.coroutines.withContext
|
|||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.ui.BaseActivity
|
import org.koitharu.kotatsu.base.ui.BaseActivity
|
||||||
import org.koitharu.kotatsu.base.ui.widgets.SlidingBottomNavigationView
|
import org.koitharu.kotatsu.base.ui.widgets.SlidingBottomNavigationView
|
||||||
|
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
||||||
import org.koitharu.kotatsu.databinding.ActivityMainBinding
|
import org.koitharu.kotatsu.databinding.ActivityMainBinding
|
||||||
import org.koitharu.kotatsu.details.service.MangaPrefetchService
|
import org.koitharu.kotatsu.details.service.MangaPrefetchService
|
||||||
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||||
@@ -62,7 +62,6 @@ import org.koitharu.kotatsu.suggestions.ui.SuggestionsWorker
|
|||||||
import org.koitharu.kotatsu.tracker.work.TrackWorker
|
import org.koitharu.kotatsu.tracker.work.TrackWorker
|
||||||
import org.koitharu.kotatsu.utils.VoiceInputContract
|
import org.koitharu.kotatsu.utils.VoiceInputContract
|
||||||
import org.koitharu.kotatsu.utils.ext.drawableEnd
|
import org.koitharu.kotatsu.utils.ext.drawableEnd
|
||||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
|
||||||
import org.koitharu.kotatsu.utils.ext.hideKeyboard
|
import org.koitharu.kotatsu.utils.ext.hideKeyboard
|
||||||
import org.koitharu.kotatsu.utils.ext.resolve
|
import org.koitharu.kotatsu.utils.ext.resolve
|
||||||
import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf
|
import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf
|
||||||
@@ -132,7 +131,7 @@ class MainActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewModel.onOpenReader.observe(this, this::onOpenReader)
|
viewModel.onOpenReader.observe(this, this::onOpenReader)
|
||||||
viewModel.onError.observe(this, this::onError)
|
viewModel.onError.observe(this, SnackbarErrorObserver(binding.container, null))
|
||||||
viewModel.isLoading.observe(this, this::onLoadingStateChanged)
|
viewModel.isLoading.observe(this, this::onLoadingStateChanged)
|
||||||
viewModel.isResumeEnabled.observe(this, this::onResumeEnabledChanged)
|
viewModel.isResumeEnabled.observe(this, this::onResumeEnabledChanged)
|
||||||
viewModel.counters.observe(this, ::onCountersChanged)
|
viewModel.counters.observe(this, ::onCountersChanged)
|
||||||
@@ -252,10 +251,6 @@ class MainActivity :
|
|||||||
startActivity(ReaderActivity.newIntent(this, manga), options)
|
startActivity(ReaderActivity.newIntent(this, manga), options)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onError(e: Throwable) {
|
|
||||||
Snackbar.make(binding.container, e.getDisplayMessage(resources), Snackbar.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onCountersChanged(counters: SparseIntArray) {
|
private fun onCountersChanged(counters: SparseIntArray) {
|
||||||
repeat(counters.size) { i ->
|
repeat(counters.size) { i ->
|
||||||
val id = counters.keyAt(i)
|
val id = counters.keyAt(i)
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.koitharu.kotatsu.reader.ui
|
package org.koitharu.kotatsu.reader.ui
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.DialogInterface
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@@ -23,7 +22,6 @@ import androidx.core.view.isGone
|
|||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
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
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -34,7 +32,7 @@ import org.koitharu.kotatsu.R
|
|||||||
import org.koitharu.kotatsu.base.domain.MangaIntent
|
import org.koitharu.kotatsu.base.domain.MangaIntent
|
||||||
import org.koitharu.kotatsu.base.ui.BaseFullscreenActivity
|
import org.koitharu.kotatsu.base.ui.BaseFullscreenActivity
|
||||||
import org.koitharu.kotatsu.bookmarks.domain.Bookmark
|
import org.koitharu.kotatsu.bookmarks.domain.Bookmark
|
||||||
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
import org.koitharu.kotatsu.core.exceptions.resolve.DialogErrorObserver
|
||||||
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
||||||
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
||||||
import org.koitharu.kotatsu.databinding.ActivityReaderBinding
|
import org.koitharu.kotatsu.databinding.ActivityReaderBinding
|
||||||
@@ -51,13 +49,10 @@ import org.koitharu.kotatsu.utils.GridTouchHelper
|
|||||||
import org.koitharu.kotatsu.utils.IdlingDetector
|
import org.koitharu.kotatsu.utils.IdlingDetector
|
||||||
import org.koitharu.kotatsu.utils.ShareHelper
|
import org.koitharu.kotatsu.utils.ShareHelper
|
||||||
import org.koitharu.kotatsu.utils.ext.assistedViewModels
|
import org.koitharu.kotatsu.utils.ext.assistedViewModels
|
||||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
|
||||||
import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat
|
import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat
|
||||||
import org.koitharu.kotatsu.utils.ext.hasGlobalPoint
|
import org.koitharu.kotatsu.utils.ext.hasGlobalPoint
|
||||||
import org.koitharu.kotatsu.utils.ext.isReportable
|
|
||||||
import org.koitharu.kotatsu.utils.ext.observeWithPrevious
|
import org.koitharu.kotatsu.utils.ext.observeWithPrevious
|
||||||
import org.koitharu.kotatsu.utils.ext.postDelayed
|
import org.koitharu.kotatsu.utils.ext.postDelayed
|
||||||
import org.koitharu.kotatsu.utils.ext.report
|
|
||||||
import org.koitharu.kotatsu.utils.ext.setValueRounded
|
import org.koitharu.kotatsu.utils.ext.setValueRounded
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -116,7 +111,21 @@ class ReaderActivity :
|
|||||||
insetsDelegate.interceptingWindowInsetsListener = this
|
insetsDelegate.interceptingWindowInsetsListener = this
|
||||||
idlingDetector.bindToLifecycle(this)
|
idlingDetector.bindToLifecycle(this)
|
||||||
|
|
||||||
viewModel.onError.observe(this, this::onError)
|
viewModel.onError.observe(
|
||||||
|
this,
|
||||||
|
DialogErrorObserver(
|
||||||
|
host = binding.container,
|
||||||
|
fragment = null,
|
||||||
|
resolver = exceptionResolver,
|
||||||
|
onResolved = { isResolved ->
|
||||||
|
if (isResolved) {
|
||||||
|
viewModel.reload()
|
||||||
|
} else if (viewModel.content.value?.pages.isNullOrEmpty()) {
|
||||||
|
finishAfterTransition()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
viewModel.readerMode.observe(this, this::onInitReader)
|
viewModel.readerMode.observe(this, this::onInitReader)
|
||||||
viewModel.onPageSaved.observe(this, this::onPageSaved)
|
viewModel.onPageSaved.observe(this, this::onPageSaved)
|
||||||
viewModel.uiState.observeWithPrevious(this, this::onUiStateChanged)
|
viewModel.uiState.observeWithPrevious(this, this::onUiStateChanged)
|
||||||
@@ -218,22 +227,6 @@ class ReaderActivity :
|
|||||||
menu.findItem(R.id.action_pages_thumbs).isVisible = hasPages
|
menu.findItem(R.id.action_pages_thumbs).isVisible = hasPages
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onError(e: Throwable) {
|
|
||||||
val listener = ErrorDialogListener(e)
|
|
||||||
val dialog = MaterialAlertDialogBuilder(this)
|
|
||||||
.setTitle(R.string.error_occurred)
|
|
||||||
.setMessage(e.getDisplayMessage(resources))
|
|
||||||
.setNegativeButton(R.string.close, listener)
|
|
||||||
.setOnCancelListener(listener)
|
|
||||||
val resolveTextId = ExceptionResolver.getResolveStringId(e)
|
|
||||||
if (resolveTextId != 0) {
|
|
||||||
dialog.setPositiveButton(resolveTextId, listener)
|
|
||||||
} else if (e.isReportable()) {
|
|
||||||
dialog.setPositiveButton(R.string.report, listener)
|
|
||||||
}
|
|
||||||
dialog.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onGridTouch(area: Int) {
|
override fun onGridTouch(area: Int) {
|
||||||
controlDelegate.onGridTouch(area, binding.container)
|
controlDelegate.onGridTouch(area, binding.container)
|
||||||
}
|
}
|
||||||
@@ -396,40 +389,6 @@ class ReaderActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class ErrorDialogListener(
|
|
||||||
private val exception: Throwable,
|
|
||||||
) : DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
|
|
||||||
|
|
||||||
override fun onClick(dialog: DialogInterface?, which: Int) {
|
|
||||||
if (which == DialogInterface.BUTTON_POSITIVE) {
|
|
||||||
dialog?.dismiss()
|
|
||||||
if (ExceptionResolver.canResolve(exception)) {
|
|
||||||
tryResolve(exception)
|
|
||||||
} else {
|
|
||||||
exception.report()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
onCancel(dialog)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCancel(dialog: DialogInterface?) {
|
|
||||||
if (viewModel.content.value?.pages.isNullOrEmpty()) {
|
|
||||||
finishAfterTransition()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun tryResolve(e: Throwable) {
|
|
||||||
lifecycleScope.launch {
|
|
||||||
if (exceptionResolver.resolve(e)) {
|
|
||||||
viewModel.reload()
|
|
||||||
} else {
|
|
||||||
onCancel(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val ACTION_MANGA_READ = "${BuildConfig.APPLICATION_ID}.action.READ_MANGA"
|
const val ACTION_MANGA_READ = "${BuildConfig.APPLICATION_ID}.action.READ_MANGA"
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ import androidx.core.view.isVisible
|
|||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.snackbar.Snackbar
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.ui.BaseActivity
|
import org.koitharu.kotatsu.base.ui.BaseActivity
|
||||||
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||||
import org.koitharu.kotatsu.base.ui.list.decor.TypedSpacingItemDecoration
|
import org.koitharu.kotatsu.base.ui.list.decor.TypedSpacingItemDecoration
|
||||||
|
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
||||||
import org.koitharu.kotatsu.databinding.ActivityScrobblerConfigBinding
|
import org.koitharu.kotatsu.databinding.ActivityScrobblerConfigBinding
|
||||||
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||||
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService
|
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService
|
||||||
@@ -25,7 +25,6 @@ import org.koitharu.kotatsu.tracker.ui.feed.adapter.FeedAdapter
|
|||||||
import org.koitharu.kotatsu.utils.ext.assistedViewModels
|
import org.koitharu.kotatsu.utils.ext.assistedViewModels
|
||||||
import org.koitharu.kotatsu.utils.ext.disposeImageRequest
|
import org.koitharu.kotatsu.utils.ext.disposeImageRequest
|
||||||
import org.koitharu.kotatsu.utils.ext.enqueueWith
|
import org.koitharu.kotatsu.utils.ext.enqueueWith
|
||||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
|
||||||
import org.koitharu.kotatsu.utils.ext.hideCompat
|
import org.koitharu.kotatsu.utils.ext.hideCompat
|
||||||
import org.koitharu.kotatsu.utils.ext.newImageRequest
|
import org.koitharu.kotatsu.utils.ext.newImageRequest
|
||||||
import org.koitharu.kotatsu.utils.ext.showCompat
|
import org.koitharu.kotatsu.utils.ext.showCompat
|
||||||
@@ -72,7 +71,7 @@ class ScrobblerConfigActivity : BaseActivity<ActivityScrobblerConfigBinding>(),
|
|||||||
viewModel.content.observe(this, listAdapter::setItems)
|
viewModel.content.observe(this, listAdapter::setItems)
|
||||||
viewModel.user.observe(this, this::onUserChanged)
|
viewModel.user.observe(this, this::onUserChanged)
|
||||||
viewModel.isLoading.observe(this, this::onLoadingStateChanged)
|
viewModel.isLoading.observe(this, this::onLoadingStateChanged)
|
||||||
viewModel.onError.observe(this, this::onError)
|
viewModel.onError.observe(this, SnackbarErrorObserver(binding.recyclerView, null))
|
||||||
viewModel.onLoggedOut.observe(this) {
|
viewModel.onLoggedOut.observe(this) {
|
||||||
finishAfterTransition()
|
finishAfterTransition()
|
||||||
}
|
}
|
||||||
@@ -139,14 +138,6 @@ class ScrobblerConfigActivity : BaseActivity<ActivityScrobblerConfigBinding>(),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onError(e: Throwable) {
|
|
||||||
Snackbar.make(
|
|
||||||
binding.recyclerView,
|
|
||||||
e.getDisplayMessage(resources),
|
|
||||||
Snackbar.LENGTH_LONG,
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showUserDialog() {
|
private fun showUserDialog() {
|
||||||
MaterialAlertDialogBuilder(this)
|
MaterialAlertDialogBuilder(this)
|
||||||
.setTitle(title)
|
.setTitle(title)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import org.koitharu.kotatsu.base.ui.BaseFragment
|
|||||||
import org.koitharu.kotatsu.base.ui.list.SectionedSelectionController
|
import org.koitharu.kotatsu.base.ui.list.SectionedSelectionController
|
||||||
import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner
|
import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner
|
||||||
import org.koitharu.kotatsu.base.ui.util.ReversibleAction
|
import org.koitharu.kotatsu.base.ui.util.ReversibleAction
|
||||||
|
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
import org.koitharu.kotatsu.databinding.FragmentShelfBinding
|
import org.koitharu.kotatsu.databinding.FragmentShelfBinding
|
||||||
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||||
@@ -36,7 +37,6 @@ import org.koitharu.kotatsu.shelf.ui.adapter.ShelfListEventListener
|
|||||||
import org.koitharu.kotatsu.shelf.ui.model.ShelfSectionModel
|
import org.koitharu.kotatsu.shelf.ui.model.ShelfSectionModel
|
||||||
import org.koitharu.kotatsu.tracker.ui.updates.UpdatesActivity
|
import org.koitharu.kotatsu.tracker.ui.updates.UpdatesActivity
|
||||||
import org.koitharu.kotatsu.utils.ext.addMenuProvider
|
import org.koitharu.kotatsu.utils.ext.addMenuProvider
|
||||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@@ -82,7 +82,7 @@ class ShelfFragment :
|
|||||||
addMenuProvider(ShelfMenuProvider(view.context, childFragmentManager, viewModel))
|
addMenuProvider(ShelfMenuProvider(view.context, childFragmentManager, viewModel))
|
||||||
|
|
||||||
viewModel.content.observe(viewLifecycleOwner, ::onListChanged)
|
viewModel.content.observe(viewLifecycleOwner, ::onListChanged)
|
||||||
viewModel.onError.observe(viewLifecycleOwner, ::onError)
|
viewModel.onError.observe(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this))
|
||||||
viewModel.onActionDone.observe(viewLifecycleOwner, ::onActionDone)
|
viewModel.onActionDone.observe(viewLifecycleOwner, ::onActionDone)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,16 +135,6 @@ class ShelfFragment :
|
|||||||
adapter?.items = list
|
adapter?.items = list
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onError(e: Throwable) {
|
|
||||||
val snackbar = Snackbar.make(
|
|
||||||
binding.recyclerView,
|
|
||||||
e.getDisplayMessage(resources),
|
|
||||||
Snackbar.LENGTH_SHORT,
|
|
||||||
)
|
|
||||||
snackbar.anchorView = (activity as? BottomNavOwner)?.bottomNav
|
|
||||||
snackbar.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onActionDone(action: ReversibleAction) {
|
private fun onActionDone(action: ReversibleAction) {
|
||||||
val handle = action.handle
|
val handle = action.handle
|
||||||
val length = if (handle == null) Snackbar.LENGTH_SHORT else Snackbar.LENGTH_LONG
|
val length = if (handle == null) Snackbar.LENGTH_SHORT else Snackbar.LENGTH_LONG
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import org.koitharu.kotatsu.R
|
|||||||
import org.koitharu.kotatsu.base.ui.BaseFragment
|
import org.koitharu.kotatsu.base.ui.BaseFragment
|
||||||
import org.koitharu.kotatsu.base.ui.list.PaginationScrollListener
|
import org.koitharu.kotatsu.base.ui.list.PaginationScrollListener
|
||||||
import org.koitharu.kotatsu.base.ui.list.decor.TypedSpacingItemDecoration
|
import org.koitharu.kotatsu.base.ui.list.decor.TypedSpacingItemDecoration
|
||||||
|
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
||||||
import org.koitharu.kotatsu.databinding.FragmentFeedBinding
|
import org.koitharu.kotatsu.databinding.FragmentFeedBinding
|
||||||
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||||
import org.koitharu.kotatsu.list.ui.adapter.MangaListListener
|
import org.koitharu.kotatsu.list.ui.adapter.MangaListListener
|
||||||
@@ -25,7 +26,6 @@ import org.koitharu.kotatsu.parsers.model.MangaTag
|
|||||||
import org.koitharu.kotatsu.tracker.ui.feed.adapter.FeedAdapter
|
import org.koitharu.kotatsu.tracker.ui.feed.adapter.FeedAdapter
|
||||||
import org.koitharu.kotatsu.tracker.work.TrackWorker
|
import org.koitharu.kotatsu.tracker.work.TrackWorker
|
||||||
import org.koitharu.kotatsu.utils.ext.addMenuProvider
|
import org.koitharu.kotatsu.utils.ext.addMenuProvider
|
||||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
|
||||||
import org.koitharu.kotatsu.utils.ext.getThemeColor
|
import org.koitharu.kotatsu.utils.ext.getThemeColor
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ class FeedFragment :
|
|||||||
)
|
)
|
||||||
|
|
||||||
viewModel.content.observe(viewLifecycleOwner, this::onListChanged)
|
viewModel.content.observe(viewLifecycleOwner, this::onListChanged)
|
||||||
viewModel.onError.observe(viewLifecycleOwner, this::onError)
|
viewModel.onError.observe(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this))
|
||||||
viewModel.onFeedCleared.observe(viewLifecycleOwner) {
|
viewModel.onFeedCleared.observe(viewLifecycleOwner) {
|
||||||
onFeedCleared()
|
onFeedCleared()
|
||||||
}
|
}
|
||||||
@@ -118,16 +118,6 @@ class FeedFragment :
|
|||||||
snackbar.show()
|
snackbar.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onError(e: Throwable) {
|
|
||||||
val snackbar = Snackbar.make(
|
|
||||||
binding.recyclerView,
|
|
||||||
e.getDisplayMessage(resources),
|
|
||||||
Snackbar.LENGTH_SHORT,
|
|
||||||
)
|
|
||||||
snackbar.anchorView = (activity as? BottomNavOwner)?.bottomNav
|
|
||||||
snackbar.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onIsTrackerRunningChanged(isRunning: Boolean) {
|
private fun onIsTrackerRunningChanged(isRunning: Boolean) {
|
||||||
binding.swipeRefreshLayout.isRefreshing = isRunning
|
binding.swipeRefreshLayout.isRefreshing = isRunning
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package org.koitharu.kotatsu.utils.ext
|
package org.koitharu.kotatsu.utils.ext
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.app.ActivityManager
|
import android.app.ActivityManager
|
||||||
import android.app.ActivityOptions
|
import android.app.ActivityOptions
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Context.ACTIVITY_SERVICE
|
import android.content.Context.ACTIVITY_SERVICE
|
||||||
|
import android.content.ContextWrapper
|
||||||
import android.content.OperationApplicationException
|
import android.content.OperationApplicationException
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.content.SyncResult
|
import android.content.SyncResult
|
||||||
@@ -172,3 +174,9 @@ fun Resources.getLocalesConfig(): LocaleListCompat {
|
|||||||
}
|
}
|
||||||
return LocaleListCompat.forLanguageTags(tagsList.complete())
|
return LocaleListCompat.forLanguageTags(tagsList.complete())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Context.findActivity(): Activity? = when (this) {
|
||||||
|
is Activity -> this
|
||||||
|
is ContextWrapper -> baseContext.findActivity()
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,17 +11,16 @@ import androidx.core.graphics.Insets
|
|||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import com.google.android.material.R as materialR
|
|
||||||
import com.google.android.material.snackbar.Snackbar
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.ui.BaseActivity
|
import org.koitharu.kotatsu.base.ui.BaseActivity
|
||||||
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||||
|
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
||||||
import org.koitharu.kotatsu.core.prefs.AppWidgetConfig
|
import org.koitharu.kotatsu.core.prefs.AppWidgetConfig
|
||||||
import org.koitharu.kotatsu.databinding.ActivityCategoriesBinding
|
import org.koitharu.kotatsu.databinding.ActivityCategoriesBinding
|
||||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
|
||||||
import org.koitharu.kotatsu.widget.shelf.adapter.CategorySelectAdapter
|
import org.koitharu.kotatsu.widget.shelf.adapter.CategorySelectAdapter
|
||||||
import org.koitharu.kotatsu.widget.shelf.model.CategoryItem
|
import org.koitharu.kotatsu.widget.shelf.model.CategoryItem
|
||||||
|
import com.google.android.material.R as materialR
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class ShelfConfigActivity :
|
class ShelfConfigActivity :
|
||||||
@@ -58,7 +57,7 @@ class ShelfConfigActivity :
|
|||||||
viewModel.checkedId = config.categoryId
|
viewModel.checkedId = config.categoryId
|
||||||
|
|
||||||
viewModel.content.observe(this, this::onContentChanged)
|
viewModel.content.observe(this, this::onContentChanged)
|
||||||
viewModel.onError.observe(this, this::onError)
|
viewModel.onError.observe(this, SnackbarErrorObserver(binding.recyclerView, null))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
@@ -105,11 +104,6 @@ class ShelfConfigActivity :
|
|||||||
adapter.items = categories
|
adapter.items = categories
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onError(e: Throwable) {
|
|
||||||
Snackbar.make(binding.recyclerView, e.getDisplayMessage(resources), Snackbar.LENGTH_LONG)
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateWidget() {
|
private fun updateWidget() {
|
||||||
val intent = Intent(this, ShelfWidgetProvider::class.java)
|
val intent = Intent(this, ShelfWidgetProvider::class.java)
|
||||||
intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
||||||
|
|||||||
Reference in New Issue
Block a user