Fix warnings and code cleanup

master
Koitharu 1 year ago
parent 10bd46f077
commit f91f55fa66
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -70,6 +70,7 @@ android {
'-opt-in=kotlin.ExperimentalStdlibApi', '-opt-in=kotlin.ExperimentalStdlibApi',
'-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi', '-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi',
'-opt-in=kotlinx.coroutines.ExperimentalForInheritanceCoroutinesApi', '-opt-in=kotlinx.coroutines.ExperimentalForInheritanceCoroutinesApi',
'-opt-in=kotlinx.coroutines.InternalForInheritanceCoroutinesApi',
'-opt-in=kotlinx.coroutines.FlowPreview', '-opt-in=kotlinx.coroutines.FlowPreview',
'-opt-in=kotlin.contracts.ExperimentalContracts', '-opt-in=kotlin.contracts.ExperimentalContracts',
'-opt-in=coil3.annotation.ExperimentalCoilApi', '-opt-in=coil3.annotation.ExperimentalCoilApi',

@ -4,9 +4,9 @@ import android.app.PendingIntent
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri
import android.os.BadParcelableException import android.os.BadParcelableException
import androidx.core.app.PendingIntentCompat import androidx.core.app.PendingIntentCompat
import androidx.core.net.toUri
import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.nav.AppRouter import org.koitharu.kotatsu.core.nav.AppRouter
import org.koitharu.kotatsu.core.util.ext.getSerializableExtraCompat import org.koitharu.kotatsu.core.util.ext.getSerializableExtraCompat
@ -27,7 +27,7 @@ class ErrorReporterReceiver : BroadcastReceiver() {
fun getPendingIntent(context: Context, e: Throwable): PendingIntent? = try { fun getPendingIntent(context: Context, e: Throwable): PendingIntent? = try {
val intent = Intent(context, ErrorReporterReceiver::class.java) val intent = Intent(context, ErrorReporterReceiver::class.java)
intent.setAction(ACTION_REPORT) intent.setAction(ACTION_REPORT)
intent.setData(Uri.parse("err://${e.hashCode()}")) intent.setData("err://${e.hashCode()}".toUri())
intent.putExtra(AppRouter.KEY_ERROR, e) intent.putExtra(AppRouter.KEY_ERROR, e)
PendingIntentCompat.getBroadcast(context, 0, intent, 0, false) PendingIntentCompat.getBroadcast(context, 0, intent, 0, false)
} catch (e: BadParcelableException) { } catch (e: BadParcelableException) {

@ -1,13 +1,9 @@
package org.koitharu.kotatsu.core.model package org.koitharu.kotatsu.core.model
import android.content.Context import android.content.Context
import android.graphics.Color
import android.os.Build import android.os.Build
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan
import android.text.style.ImageSpan import android.text.style.ImageSpan
import android.text.style.RelativeSizeSpan
import android.text.style.SuperscriptSpan
import android.widget.TextView import android.widget.TextView
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
@ -16,7 +12,6 @@ import androidx.core.text.inSpans
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.parser.external.ExternalMangaSource import org.koitharu.kotatsu.core.parser.external.ExternalMangaSource
import org.koitharu.kotatsu.core.util.ext.getDisplayName import org.koitharu.kotatsu.core.util.ext.getDisplayName
import org.koitharu.kotatsu.core.util.ext.getThemeColor
import org.koitharu.kotatsu.core.util.ext.toLocale import org.koitharu.kotatsu.core.util.ext.toLocale
import org.koitharu.kotatsu.core.util.ext.toLocaleOrNull import org.koitharu.kotatsu.core.util.ext.toLocaleOrNull
import org.koitharu.kotatsu.parsers.model.ContentType import org.koitharu.kotatsu.parsers.model.ContentType
@ -24,7 +19,6 @@ import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.util.splitTwoParts import org.koitharu.kotatsu.parsers.util.splitTwoParts
import java.util.Locale import java.util.Locale
import androidx.appcompat.R as appcompatR
data object LocalMangaSource : MangaSource { data object LocalMangaSource : MangaSource {
override val name = "LOCAL" override val name = "LOCAL"
@ -102,14 +96,6 @@ fun MangaSource.getTitle(context: Context): String = when (val source = unwrap()
else -> context.getString(R.string.unknown) else -> context.getString(R.string.unknown)
} }
fun SpannableStringBuilder.appendNsfwLabel(context: Context) = inSpans(
ForegroundColorSpan(context.getThemeColor(appcompatR.attr.colorError, Color.RED)),
RelativeSizeSpan(0.74f),
SuperscriptSpan(),
) {
append(context.getString(R.string.nsfw))
}
fun SpannableStringBuilder.appendIcon(textView: TextView, @DrawableRes resId: Int): SpannableStringBuilder { fun SpannableStringBuilder.appendIcon(textView: TextView, @DrawableRes resId: Int): SpannableStringBuilder {
val icon = ContextCompat.getDrawable(textView.context, resId) ?: return this val icon = ContextCompat.getDrawable(textView.context, resId) ?: return this
icon.setTintList(textView.textColors) icon.setTintList(textView.textColors)

@ -675,7 +675,7 @@ class AppRouter private constructor(
companion object { companion object {
fun from(view: View): AppRouter? = runCatching { fun from(view: View): AppRouter? = runCatching {
AppRouter(view.findFragment<Fragment>()) AppRouter(view.findFragment())
}.getOrElse { }.getOrElse {
(view.context.findActivity() as? FragmentActivity)?.let(::AppRouter) (view.context.findActivity() as? FragmentActivity)?.let(::AppRouter)
} }

@ -7,7 +7,7 @@ import java.io.InputStreamReader
object RomCompat { object RomCompat {
val isMiui = suspendLazy<Boolean>(Dispatchers.IO) { val isMiui = suspendLazy(Dispatchers.IO) {
getProp("ro.miui.ui.version.name").isNotEmpty() getProp("ro.miui.ui.version.name").isNotEmpty()
} }

@ -1,6 +1,7 @@
package org.koitharu.kotatsu.core.parser package org.koitharu.kotatsu.core.parser
import android.graphics.Canvas import android.graphics.Canvas
import androidx.core.graphics.createBitmap
import org.koitharu.kotatsu.parsers.bitmap.Bitmap import org.koitharu.kotatsu.parsers.bitmap.Bitmap
import org.koitharu.kotatsu.parsers.bitmap.Rect import org.koitharu.kotatsu.parsers.bitmap.Rect
import java.io.OutputStream import java.io.OutputStream
@ -35,7 +36,7 @@ class BitmapWrapper private constructor(
companion object { companion object {
fun create(width: Int, height: Int) = BitmapWrapper( fun create(width: Int, height: Int) = BitmapWrapper(
AndroidBitmap.createBitmap(width, height, AndroidBitmap.Config.ARGB_8888), createBitmap(width, height, AndroidBitmap.Config.ARGB_8888),
) )
fun create(bitmap: AndroidBitmap) = BitmapWrapper( fun create(bitmap: AndroidBitmap) = BitmapWrapper(

@ -2,11 +2,11 @@ package org.koitharu.kotatsu.core.parser.favicon
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.AdaptiveIconDrawable import android.graphics.drawable.AdaptiveIconDrawable
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable import android.graphics.drawable.LayerDrawable
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import coil3.ColorImage
import coil3.ImageLoader import coil3.ImageLoader
import coil3.asImage import coil3.asImage
import coil3.decode.DataSource import coil3.decode.DataSource
@ -45,7 +45,7 @@ class FaviconFetcher(
is ParserMangaRepository -> fetchParserFavicon(repo) is ParserMangaRepository -> fetchParserFavicon(repo)
is ExternalMangaRepository -> fetchPluginIcon(repo) is ExternalMangaRepository -> fetchPluginIcon(repo)
is EmptyMangaRepository -> ImageFetchResult( is EmptyMangaRepository -> ImageFetchResult(
image = ColorDrawable(Color.WHITE).asImage(), image = ColorImage(Color.WHITE),
isSampled = false, isSampled = false,
dataSource = DataSource.MEMORY, dataSource = DataSource.MEMORY,
) )

@ -30,7 +30,7 @@ abstract class FragmentContainerActivity(private val fragmentClass: Class<out Fr
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityContainerBinding.inflate(layoutInflater)) setContentView(ActivityContainerBinding.inflate(layoutInflater))
setDisplayHomeAsUp(true, false) setDisplayHomeAsUp(isEnabled = true, showUpAsClose = false)
val fm = supportFragmentManager val fm = supportFragmentManager
if (fm.findFragmentById(R.id.container) == null) { if (fm.findFragmentById(R.id.container) == null) {
fm.commit { fm.commit {

@ -2,6 +2,7 @@ package org.koitharu.kotatsu.core.ui.list.lifecycle
import android.view.View import android.view.View
import androidx.core.view.children import androidx.core.view.children
import androidx.core.view.isEmpty
import androidx.viewpager2.widget.ViewPager2 import androidx.viewpager2.widget.ViewPager2
import org.koitharu.kotatsu.core.util.ext.recyclerView import org.koitharu.kotatsu.core.util.ext.recyclerView
@ -28,7 +29,7 @@ class PagerLifecycleDispatcher(
pendingUpdate = null pendingUpdate = null
var hasResumedItem = false var hasResumedItem = false
val rv = pager.recyclerView ?: return val rv = pager.recyclerView ?: return
if (rv.childCount == 0) { if (rv.isEmpty()) {
return return
} }
for (child in rv.children) { for (child in rv.children) {

@ -5,7 +5,6 @@ import android.os.Parcel
import android.os.Parcelable import android.os.Parcelable
import android.os.Parcelable.Creator import android.os.Parcelable.Creator
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View
import android.widget.Checkable import android.widget.Checkable
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.appcompat.widget.AppCompatImageView import androidx.appcompat.widget.AppCompatImageView
@ -63,12 +62,6 @@ class CheckableImageView @JvmOverloads constructor(
} }
} }
class ToggleOnClickListener : OnClickListener {
override fun onClick(view: View) {
(view as? Checkable)?.toggle()
}
}
fun interface OnCheckedChangeListener { fun interface OnCheckedChangeListener {
fun onCheckedChanged(view: CheckableImageView, isChecked: Boolean) fun onCheckedChanged(view: CheckableImageView, isChecked: Boolean)

@ -7,6 +7,7 @@ import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.core.content.withStyledAttributes import androidx.core.content.withStyledAttributes
import androidx.core.view.isNotEmpty
import androidx.core.view.isVisible import androidx.core.view.isVisible
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
@ -82,7 +83,7 @@ class IconsView @JvmOverloads constructor(
private fun addImageView() = ImageView(context).also { private fun addImageView() = ImageView(context).also {
it.scaleType = ImageView.ScaleType.FIT_CENTER it.scaleType = ImageView.ScaleType.FIT_CENTER
val lp = LayoutParams(iconSize, iconSize) val lp = LayoutParams(iconSize, iconSize)
if (childCount != 0) { if (isNotEmpty()) {
lp.marginStart = iconSpacing lp.marginStart = iconSpacing
} }
addView(it, lp) addView(it, lp)

@ -1,29 +1,18 @@
package org.koitharu.kotatsu.core.util.ext package org.koitharu.kotatsu.core.util.ext
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleDestroyedException
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.lifecycle.RetainedLifecycle import dagger.hilt.android.lifecycle.RetainedLifecycle
import kotlinx.coroutines.CancellableContinuation
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.joinAll import kotlinx.coroutines.joinAll
import kotlinx.coroutines.plus import kotlinx.coroutines.plus
import kotlinx.coroutines.suspendCancellableCoroutine
import org.koitharu.kotatsu.core.util.AcraCoroutineErrorHandler import org.koitharu.kotatsu.core.util.AcraCoroutineErrorHandler
import org.koitharu.kotatsu.core.util.RetainedLifecycleCoroutineScope import org.koitharu.kotatsu.core.util.RetainedLifecycleCoroutineScope
import org.koitharu.kotatsu.parsers.util.cancelAll import org.koitharu.kotatsu.parsers.util.cancelAll
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.cancellation.CancellationException import kotlin.coroutines.cancellation.CancellationException
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
val processLifecycleScope: CoroutineScope val processLifecycleScope: CoroutineScope
get() = ProcessLifecycleOwner.get().lifecycleScope + AcraCoroutineErrorHandler() get() = ProcessLifecycleOwner.get().lifecycleScope + AcraCoroutineErrorHandler()
@ -31,54 +20,6 @@ val processLifecycleScope: CoroutineScope
val RetainedLifecycle.lifecycleScope: RetainedLifecycleCoroutineScope val RetainedLifecycle.lifecycleScope: RetainedLifecycleCoroutineScope
inline get() = RetainedLifecycleCoroutineScope(this) inline get() = RetainedLifecycleCoroutineScope(this)
suspend fun Lifecycle.awaitStateAtLeast(state: Lifecycle.State) {
if (currentState.isAtLeast(state)) {
return
}
suspendCancellableCoroutine { cont ->
val observer = ContinuationLifecycleObserver(this, cont, state)
addObserverFromAnyThread(observer)
cont.invokeOnCancellation {
removeObserverFromAnyThread(observer)
}
}
}
private class ContinuationLifecycleObserver(
private val lifecycle: Lifecycle,
private val continuation: CancellableContinuation<Unit>,
private val targetState: Lifecycle.State,
) : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event == Lifecycle.Event.upTo(targetState)) {
lifecycle.removeObserver(this)
continuation.resume(Unit)
} else if (event == Lifecycle.Event.ON_DESTROY) {
lifecycle.removeObserver(this)
continuation.resumeWithException(LifecycleDestroyedException())
}
}
}
private fun Lifecycle.addObserverFromAnyThread(observer: LifecycleObserver) {
val dispatcher = Dispatchers.Main.immediate
if (dispatcher.isDispatchNeeded(EmptyCoroutineContext)) {
dispatcher.dispatch(EmptyCoroutineContext) { addObserver(observer) }
} else {
addObserver(observer)
}
}
private fun Lifecycle.removeObserverFromAnyThread(observer: LifecycleObserver) {
val dispatcher = Dispatchers.Main.immediate
if (dispatcher.isDispatchNeeded(EmptyCoroutineContext)) {
dispatcher.dispatch(EmptyCoroutineContext) { removeObserver(observer) }
} else {
removeObserver(observer)
}
}
fun <T> Deferred<T>.getCompletionResultOrNull(): Result<T>? = if (isCompleted) { fun <T> Deferred<T>.getCompletionResultOrNull(): Result<T>? = if (isCompleted) {
getCompletionExceptionOrNull()?.let { error -> getCompletionExceptionOrNull()?.let { error ->
Result.failure(error) Result.failure(error)

@ -35,7 +35,6 @@ fun calculateTimeAgo(instant: Instant, showMonths: Boolean = false): DateTimeAgo
} }
} }
@Suppress("KotlinConstantConditions")
fun Long.toInstantOrNull() = if (this == 0L) null else Instant.ofEpochMilli(this) fun Long.toInstantOrNull() = if (this == 0L) null else Instant.ofEpochMilli(this)
fun Resources.formatDurationShort(millis: Long): String? { fun Resources.formatDurationShort(millis: Long): String? {

@ -2,17 +2,17 @@ package org.koitharu.kotatsu.core.util.ext
import android.graphics.Typeface import android.graphics.Typeface
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.view.View
import android.widget.TextView import android.widget.TextView
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.annotation.StyleRes import androidx.annotation.StyleRes
import androidx.core.content.res.use import androidx.core.content.res.use
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.core.widget.TextViewCompat import androidx.core.widget.TextViewCompat
var TextView.textAndVisible: CharSequence? var TextView.textAndVisible: CharSequence?
get() = text?.takeIf { visibility == View.VISIBLE } get() = text?.takeIf { isVisible }
set(value) { set(value) {
text = value text = value
isGone = value.isNullOrEmpty() isGone = value.isNullOrEmpty()

@ -158,7 +158,7 @@ class ZipOutput(
private fun Closeable.closeSafe() { private fun Closeable.closeSafe() {
try { try {
cachedOutput?.close() close()
} catch (e: NullPointerException) { } catch (e: NullPointerException) {
// Don't throw the "Deflater has been closed" exception // Don't throw the "Deflater has been closed" exception
e.printStackTraceDebug() e.printStackTraceDebug()

@ -5,7 +5,6 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChangedBy import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.observeAsFlow import org.koitharu.kotatsu.core.prefs.observeAsFlow
@ -31,11 +30,6 @@ class DetailsInteractor @Inject constructor(
private val scrobblers: Set<@JvmSuppressWildcards Scrobbler>, private val scrobblers: Set<@JvmSuppressWildcards Scrobbler>,
) { ) {
fun observeIsFavourite(mangaId: Long): Flow<Boolean> {
return favouritesRepository.observeCategoriesIds(mangaId)
.map { it.isNotEmpty() }
}
fun observeFavourite(mangaId: Long): Flow<Set<FavouriteCategory>> { fun observeFavourite(mangaId: Long): Flow<Set<FavouriteCategory>> {
return favouritesRepository.observeCategories(mangaId) return favouritesRepository.observeCategories(mangaId)
} }

@ -126,7 +126,7 @@ class DetailsActivity :
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityDetailsBinding.inflate(layoutInflater)) setContentView(ActivityDetailsBinding.inflate(layoutInflater))
infoBinding = LayoutDetailsTableBinding.bind(viewBinding.root) infoBinding = LayoutDetailsTableBinding.bind(viewBinding.root)
setDisplayHomeAsUp(true, false) setDisplayHomeAsUp(isEnabled = true, showUpAsClose = false)
supportActionBar?.setDisplayShowTitleEnabled(false) supportActionBar?.setDisplayShowTitleEnabled(false)
viewBinding.chipFavorite.setOnClickListener(this) viewBinding.chipFavorite.setOnClickListener(this)
infoBinding.textViewLocal.setOnClickListener(this) infoBinding.textViewLocal.setOnClickListener(this)
@ -377,7 +377,7 @@ class DetailsActivity :
if (adapter != null) { if (adapter != null) {
adapter.items = scrobblings adapter.items = scrobblings
} else { } else {
adapter = ScrollingInfoAdapter(this, coil, router) adapter = ScrollingInfoAdapter(router)
adapter.items = scrobblings adapter.items = scrobblings
viewBinding.recyclerViewScrobbling.adapter = adapter viewBinding.recyclerViewScrobbling.adapter = adapter
viewBinding.recyclerViewScrobbling.addItemDecoration(ScrobblingItemDecoration()) viewBinding.recyclerViewScrobbling.addItemDecoration(ScrobblingItemDecoration())

@ -1,8 +1,6 @@
package org.koitharu.kotatsu.details.ui.pager.pages package org.koitharu.kotatsu.details.ui.pager.pages
import android.content.Context import android.content.Context
import androidx.lifecycle.LifecycleOwner
import coil3.ImageLoader
import org.koitharu.kotatsu.core.ui.BaseListAdapter import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller
@ -11,8 +9,6 @@ import org.koitharu.kotatsu.list.ui.adapter.listHeaderAD
import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.ListModel
class PageThumbnailAdapter( class PageThumbnailAdapter(
coil: ImageLoader,
lifecycleOwner: LifecycleOwner,
clickListener: OnListItemClickListener<PageThumbnail>, clickListener: OnListItemClickListener<PageThumbnail>,
) : BaseListAdapter<ListModel>(), FastScroller.SectionIndexer { ) : BaseListAdapter<ListModel>(), FastScroller.SectionIndexer {

@ -15,7 +15,6 @@ import androidx.core.view.isVisible
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import coil3.ImageLoader
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
@ -59,9 +58,6 @@ class PagesFragment :
RecyclerViewOwner, RecyclerViewOwner,
ListSelectionController.Callback { ListSelectionController.Callback {
@Inject
lateinit var coil: ImageLoader
@Inject @Inject
lateinit var settings: AppSettings lateinit var settings: AppSettings
@ -113,8 +109,6 @@ class PagesFragment :
callback = this, callback = this,
) )
thumbnailsAdapter = PageThumbnailAdapter( thumbnailsAdapter = PageThumbnailAdapter(
coil = coil,
lifecycleOwner = viewLifecycleOwner,
clickListener = this@PagesFragment, clickListener = this@PagesFragment,
) )
viewModel.gridScale.observe(viewLifecycleOwner, ::onGridScaleChanged) // before rv initialization viewModel.gridScale.observe(viewLifecycleOwner, ::onGridScaleChanged) // before rv initialization

@ -13,7 +13,6 @@ import androidx.core.text.method.LinkMovementMethodCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import coil3.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 org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
@ -29,7 +28,6 @@ import org.koitharu.kotatsu.databinding.SheetScrobblingBinding
import org.koitharu.kotatsu.details.ui.DetailsViewModel import org.koitharu.kotatsu.details.ui.DetailsViewModel
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingStatus import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingStatus
import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class ScrobblingInfoSheet : class ScrobblingInfoSheet :
@ -42,9 +40,6 @@ class ScrobblingInfoSheet :
private val viewModel by activityViewModels<DetailsViewModel>() private val viewModel by activityViewModels<DetailsViewModel>()
private var scrobblerIndex: Int = -1 private var scrobblerIndex: Int = -1
@Inject
lateinit var coil: ImageLoader
private var menu: PopupMenu? = null private var menu: PopupMenu? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {

@ -1,14 +1,10 @@
package org.koitharu.kotatsu.details.ui.scrobbling package org.koitharu.kotatsu.details.ui.scrobbling
import androidx.lifecycle.LifecycleOwner
import coil3.ImageLoader
import org.koitharu.kotatsu.core.nav.AppRouter import org.koitharu.kotatsu.core.nav.AppRouter
import org.koitharu.kotatsu.core.ui.BaseListAdapter import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.ListModel
class ScrollingInfoAdapter( class ScrollingInfoAdapter(
lifecycleOwner: LifecycleOwner,
coil: ImageLoader,
router: AppRouter, router: AppRouter,
) : BaseListAdapter<ListModel>() { ) : BaseListAdapter<ListModel>() {

@ -7,7 +7,6 @@ import androidx.core.text.bold
import androidx.core.text.buildSpannedString import androidx.core.text.buildSpannedString
import androidx.core.text.color import androidx.core.text.color
import androidx.work.WorkInfo import androidx.work.WorkInfo
import coil3.memory.MemoryCache
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import org.koitharu.kotatsu.core.util.ext.getThemeColor import org.koitharu.kotatsu.core.util.ext.getThemeColor
import org.koitharu.kotatsu.download.ui.list.chapters.DownloadChapter import org.koitharu.kotatsu.download.ui.list.chapters.DownloadChapter
@ -35,8 +34,6 @@ data class DownloadItemModel(
val chapters: StateFlow<List<DownloadChapter>?>, val chapters: StateFlow<List<DownloadChapter>?>,
) : ListModel, Comparable<DownloadItemModel> { ) : ListModel, Comparable<DownloadItemModel> {
val coverCacheKey = MemoryCache.Key(manga?.coverUrl.orEmpty(), mapOf("dl" to "1"))
val percent: Float val percent: Float
get() = if (max > 0) progress / max.toFloat() else 0f get() = if (max > 0) progress / max.toFloat() else 0f

@ -43,7 +43,7 @@ class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityDownloadsBinding.inflate(layoutInflater)) setContentView(ActivityDownloadsBinding.inflate(layoutInflater))
setDisplayHomeAsUp(true, false) setDisplayHomeAsUp(isEnabled = true, showUpAsClose = false)
val downloadsAdapter = DownloadsAdapter(this, this) val downloadsAdapter = DownloadsAdapter(this, this)
val decoration = TypedListSpacingDecoration(this, false) val decoration = TypedListSpacingDecoration(this, false)
selectionController = ListSelectionController( selectionController = ListSelectionController(
@ -80,7 +80,7 @@ class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
right = bars.right, right = bars.right,
top = bars.top, top = bars.top,
) )
return return WindowInsetsCompat.Builder(insets) return WindowInsetsCompat.Builder(insets)
.setInsets(WindowInsetsCompat.Type.systemBars(), Insets.NONE) .setInsets(WindowInsetsCompat.Type.systemBars(), Insets.NONE)
.build() .build()
} }

@ -4,9 +4,9 @@ import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.net.Uri
import android.os.PatternMatcher import android.os.PatternMatcher
import androidx.core.app.PendingIntentCompat import androidx.core.app.PendingIntentCompat
import androidx.core.net.toUri
import org.koitharu.kotatsu.core.util.ext.toUUIDOrNull import org.koitharu.kotatsu.core.util.ext.toUUIDOrNull
import java.util.UUID import java.util.UUID
@ -81,7 +81,7 @@ class PausingReceiver(
) )
private fun createIntent(context: Context, id: UUID, action: String) = Intent(action) private fun createIntent(context: Context, id: UUID, action: String) = Intent(action)
.setData(Uri.parse("$SCHEME://$id")) .setData("$SCHEME://$id".toUri())
.setPackage(context.packageName) .setPackage(context.packageName)
.putExtra(EXTRA_UUID, id.toString()) .putExtra(EXTRA_UUID, id.toString())
} }

@ -1,7 +1,6 @@
package org.koitharu.kotatsu.favourites.ui package org.koitharu.kotatsu.favourites.ui
import android.os.Bundle import android.os.Bundle
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.core.nav.AppRouter import org.koitharu.kotatsu.core.nav.AppRouter
import org.koitharu.kotatsu.core.ui.FragmentContainerActivity import org.koitharu.kotatsu.core.ui.FragmentContainerActivity
import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment

@ -49,7 +49,7 @@ class FavouriteCategoriesActivity :
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityCategoriesBinding.inflate(layoutInflater)) setContentView(ActivityCategoriesBinding.inflate(layoutInflater))
setDisplayHomeAsUp(true, false) setDisplayHomeAsUp(isEnabled = true, showUpAsClose = false)
adapter = CategoriesAdapter(this, this) adapter = CategoriesAdapter(this, this)
selectionController = ListSelectionController( selectionController = ListSelectionController(
appCompatDelegate = delegate, appCompatDelegate = delegate,

@ -40,7 +40,7 @@ class FavouritesCategoryEditActivity :
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityCategoryEditBinding.inflate(layoutInflater)) setContentView(ActivityCategoryEditBinding.inflate(layoutInflater))
setDisplayHomeAsUp(true, true) setDisplayHomeAsUp(isEnabled = true, showUpAsClose = true)
initSortSpinner() initSortSpinner()
viewBinding.buttonDone.setOnClickListener(this) viewBinding.buttonDone.setOnClickListener(this)
viewBinding.editName.addTextChangedListener(this) viewBinding.editName.addTextChangedListener(this)

@ -18,12 +18,12 @@ import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.joinToStringWithLimit import org.koitharu.kotatsu.core.util.ext.joinToStringWithLimit
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.databinding.SheetFavoriteCategoriesBinding import org.koitharu.kotatsu.databinding.DialogFavoriteBinding
import org.koitharu.kotatsu.favourites.ui.categories.select.adapter.MangaCategoriesAdapter import org.koitharu.kotatsu.favourites.ui.categories.select.adapter.MangaCategoriesAdapter
import org.koitharu.kotatsu.favourites.ui.categories.select.model.MangaCategoryItem import org.koitharu.kotatsu.favourites.ui.categories.select.model.MangaCategoryItem
@AndroidEntryPoint @AndroidEntryPoint
class FavoriteDialog : AlertDialogFragment<SheetFavoriteCategoriesBinding>(), class FavoriteDialog : AlertDialogFragment<DialogFavoriteBinding>(),
OnListItemClickListener<MangaCategoryItem>, DialogInterface.OnClickListener { OnListItemClickListener<MangaCategoryItem>, DialogInterface.OnClickListener {
private val viewModel by viewModels<FavoriteDialogViewModel>() private val viewModel by viewModels<FavoriteDialogViewModel>()
@ -31,7 +31,7 @@ class FavoriteDialog : AlertDialogFragment<SheetFavoriteCategoriesBinding>(),
override fun onCreateViewBinding( override fun onCreateViewBinding(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
) = SheetFavoriteCategoriesBinding.inflate(inflater, container, false) ) = DialogFavoriteBinding.inflate(inflater, container, false)
override fun onBuildDialog(builder: MaterialAlertDialogBuilder): MaterialAlertDialogBuilder { override fun onBuildDialog(builder: MaterialAlertDialogBuilder): MaterialAlertDialogBuilder {
return super.onBuildDialog(builder) return super.onBuildDialog(builder)
@ -40,7 +40,7 @@ class FavoriteDialog : AlertDialogFragment<SheetFavoriteCategoriesBinding>(),
} }
override fun onViewBindingCreated( override fun onViewBindingCreated(
binding: SheetFavoriteCategoriesBinding, binding: DialogFavoriteBinding,
savedInstanceState: Bundle?, savedInstanceState: Bundle?,
) { ) {
super.onViewBindingCreated(binding, savedInstanceState) super.onViewBindingCreated(binding, savedInstanceState)

@ -66,10 +66,6 @@ class HistoryRepository @Inject constructor(
return entities.toMangaList() return entities.toMangaList()
} }
suspend fun getCount(): Int {
return db.getHistoryDao().getCount()
}
suspend fun getLastOrNull(): Manga? { suspend fun getLastOrNull(): Manga? {
val entity = db.getHistoryDao().findAll(0, 1).firstOrNull() ?: return null val entity = db.getHistoryDao().findAll(0, 1).firstOrNull() ?: return null
return entity.toManga() return entity.toManga()
@ -116,12 +112,6 @@ class HistoryRepository @Inject constructor(
} }
} }
fun observeHasItems(): Flow<Boolean> {
return db.getHistoryDao().observeCount()
.map { it > 0 }
.distinctUntilChanged()
}
suspend fun addOrUpdate(manga: Manga, chapterId: Long, page: Int, scroll: Int, percent: Float, force: Boolean) { suspend fun addOrUpdate(manga: Manga, chapterId: Long, page: Int, scroll: Int, percent: Float, force: Boolean) {
if (!force && shouldSkip(manga)) { if (!force && shouldSkip(manga)) {
return return
@ -158,7 +148,7 @@ class HistoryRepository @Inject constructor(
return ReadingProgress( return ReadingProgress(
percent = fixedPercent, percent = fixedPercent,
totalChapters = entity.chaptersCount, totalChapters = entity.chaptersCount,
mode = mode mode = mode,
).takeIf { it.isValid() } ).takeIf { it.isValid() }
} }

@ -9,6 +9,7 @@ import androidx.annotation.Px
import androidx.core.content.withStyledAttributes import androidx.core.content.withStyledAttributes
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
import androidx.core.view.children import androidx.core.view.children
import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import androidx.core.widget.ImageViewCompat import androidx.core.widget.ImageViewCompat
@ -33,10 +34,12 @@ class CoverStackView @JvmOverloads constructor(
binding.imageViewCover2, binding.imageViewCover2,
binding.imageViewCover3, binding.imageViewCover3,
) )
private var hideEmptyView: Boolean = true private var hideEmptyView: Boolean = false
init { init {
context.withStyledAttributes(attrs, R.styleable.CoverStackView, defStyleAttr) { context.withStyledAttributes(attrs, R.styleable.CoverStackView, defStyleAttr) {
hideEmptyView = getBoolean(R.styleable.CoverStackView_hideEmptyViews, hideEmptyView)
children.forEach { it.isGone = hideEmptyView }
val coverSize = getDimension(R.styleable.CoverStackView_coverSize, 0f) val coverSize = getDimension(R.styleable.CoverStackView_coverSize, 0f)
if (coverSize > 0f) { if (coverSize > 0f) {
setCoverSize(coverSize) setCoverSize(coverSize)

@ -9,7 +9,6 @@ import androidx.core.text.method.LinkMovementMethodCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import coil3.ImageLoader
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
@ -24,14 +23,10 @@ import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.parsers.util.ifNullOrEmpty import org.koitharu.kotatsu.parsers.util.ifNullOrEmpty
import org.koitharu.kotatsu.search.ui.MangaListActivity import org.koitharu.kotatsu.search.ui.MangaListActivity
import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class PreviewFragment : BaseFragment<FragmentPreviewBinding>(), View.OnClickListener, ChipsView.OnChipClickListener { class PreviewFragment : BaseFragment<FragmentPreviewBinding>(), View.OnClickListener, ChipsView.OnChipClickListener {
@Inject
lateinit var coil: ImageLoader
private val viewModel: PreviewViewModel by viewModels() private val viewModel: PreviewViewModel by viewModels()
override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentPreviewBinding { override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentPreviewBinding {
@ -64,9 +59,9 @@ class PreviewFragment : BaseFragment<FragmentPreviewBinding>(), View.OnClickList
R.id.button_open -> router.openDetails(manga) R.id.button_open -> router.openDetails(manga)
R.id.button_read -> router.openReader(manga) R.id.button_read -> router.openReader(manga)
R.id.textView_author -> router.openSearch( R.id.textView_author -> router.showAuthorDialog(
author = manga.authors.firstOrNull() ?: return,
source = manga.source, source = manga.source,
query = manga.author ?: return,
) )
R.id.imageView_cover -> router.openImage( R.id.imageView_cover -> router.openImage(
@ -93,8 +88,8 @@ class PreviewFragment : BaseFragment<FragmentPreviewBinding>(), View.OnClickList
// Main // Main
loadCover(manga) loadCover(manga)
textViewTitle.text = manga.title textViewTitle.text = manga.title
textViewSubtitle.textAndVisible = manga.altTitle textViewSubtitle.textAndVisible = manga.altTitles.firstOrNull()
textViewAuthor.textAndVisible = manga.author textViewAuthor.textAndVisible = manga.authors.firstOrNull()
if (manga.hasRating) { if (manga.hasRating) {
ratingBar.rating = manga.rating * ratingBar.numStars ratingBar.rating = manga.rating * ratingBar.numStars
ratingBar.isVisible = true ratingBar.isVisible = true
@ -110,8 +105,8 @@ class PreviewFragment : BaseFragment<FragmentPreviewBinding>(), View.OnClickList
buttonRead.setText( buttonRead.setText(
when { when {
footer == null -> R.string.loading_ footer == null -> R.string.loading_
footer.isIncognito == true -> R.string.incognito footer.isIncognito -> R.string.incognito
footer.isInProgress() == true -> R.string._continue footer.isInProgress() -> R.string._continue
else -> R.string.read else -> R.string.read
}, },
) )

@ -1,6 +0,0 @@
package org.koitharu.kotatsu.main.ui.owners
interface NoModalBottomSheetOwner {
fun getBottomSheetCollapsedHeight(): Int
}

@ -3,7 +3,6 @@ package org.koitharu.kotatsu.main.ui.welcome
import android.content.Context import android.content.Context
import androidx.core.os.ConfigurationCompat import androidx.core.os.ConfigurationCompat
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow

@ -1,9 +1,9 @@
package org.koitharu.kotatsu.reader.domain package org.koitharu.kotatsu.reader.domain
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.net.Uri
import android.util.Size import android.util.Size
import androidx.core.net.toFile import androidx.core.net.toFile
import androidx.core.net.toUri
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runInterruptible import kotlinx.coroutines.runInterruptible
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -62,7 +62,7 @@ class DetectReaderModeUseCase @Inject constructor(
val pageIndex = (pages.size * 0.3).roundToInt() val pageIndex = (pages.size * 0.3).roundToInt()
val page = requireNotNull(pages.getOrNull(pageIndex)) { "No pages" } val page = requireNotNull(pages.getOrNull(pageIndex)) { "No pages" }
val url = repository.getPageUrl(page) val url = repository.getPageUrl(page)
val uri = Uri.parse(url) val uri = url.toUri()
val size = when { val size = when {
uri.isZipUri() -> runInterruptible(Dispatchers.IO) { uri.isZipUri() -> runInterruptible(Dispatchers.IO) {

@ -3,7 +3,6 @@ package org.koitharu.kotatsu.reader.domain
import android.content.Context import android.content.Context
import android.graphics.Rect import android.graphics.Rect
import android.net.Uri import android.net.Uri
import android.util.Log
import androidx.annotation.AnyThread import androidx.annotation.AnyThread
import androidx.annotation.CheckResult import androidx.annotation.CheckResult
import androidx.collection.LongSparseArray import androidx.collection.LongSparseArray

@ -11,7 +11,6 @@ import androidx.documentfile.provider.DocumentFile
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CancellableContinuation import kotlinx.coroutines.CancellableContinuation
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runInterruptible import kotlinx.coroutines.runInterruptible

@ -33,9 +33,6 @@ class ColorFilterConfigViewModel @Inject constructor(
val isChanged: Boolean val isChanged: Boolean
get() = colorFilter.value != initialColorFilter get() = colorFilter.value != initialColorFilter
val is32BitColorsEnabled: Boolean
get() = settings.is32BitColorsEnabled
init { init {
launchLoadingJob { launchLoadingJob {
initialColorFilter = mangaDataRepository.getColorFilter(manga.id) ?: settings.readerColorFilter initialColorFilter = mangaDataRepository.getColorFilter(manga.id) ?: settings.readerColorFilter

@ -1,8 +0,0 @@
package org.koitharu.kotatsu.reader.ui.pager
interface OnBoundsScrollListener {
fun onScrolledToStart()
fun onScrolledToEnd()
}

@ -1,21 +1,13 @@
package org.koitharu.kotatsu.reader.ui.pager.reversed package org.koitharu.kotatsu.reader.ui.pager.reversed
import android.graphics.PointF import android.graphics.PointF
import android.os.Build
import android.view.Gravity import android.view.Gravity
import android.view.RoundedCorner
import android.view.ViewGroup
import android.view.WindowInsets
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.annotation.RequiresApi
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
import org.koitharu.kotatsu.core.model.ZoomMode import org.koitharu.kotatsu.core.model.ZoomMode
import org.koitharu.kotatsu.core.os.NetworkState import org.koitharu.kotatsu.core.os.NetworkState
import org.koitharu.kotatsu.core.util.ext.isRtl
import org.koitharu.kotatsu.databinding.ItemPageBinding import org.koitharu.kotatsu.databinding.ItemPageBinding
import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.domain.PageLoader
import org.koitharu.kotatsu.reader.ui.config.ReaderSettings import org.koitharu.kotatsu.reader.ui.config.ReaderSettings

@ -5,6 +5,8 @@ import android.util.AttributeSet
import android.view.View import android.view.View
import androidx.core.view.ViewCompat.TYPE_TOUCH import androidx.core.view.ViewCompat.TYPE_TOUCH
import androidx.core.view.forEach import androidx.core.view.forEach
import androidx.core.view.isEmpty
import androidx.core.view.isNotEmpty
import androidx.core.view.iterator import androidx.core.view.iterator
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -33,7 +35,7 @@ class WebtoonRecyclerView @JvmOverloads constructor(
override fun startNestedScroll(axes: Int) = startNestedScroll(axes, TYPE_TOUCH) override fun startNestedScroll(axes: Int) = startNestedScroll(axes, TYPE_TOUCH)
override fun startNestedScroll(axes: Int, type: Int): Boolean = childCount != 0 override fun startNestedScroll(axes: Int, type: Int): Boolean = isNotEmpty()
override fun dispatchNestedPreScroll( override fun dispatchNestedPreScroll(
dx: Int, dx: Int,
@ -59,7 +61,7 @@ class WebtoonRecyclerView @JvmOverloads constructor(
} }
private fun consumeVerticalScroll(dy: Int): Int { private fun consumeVerticalScroll(dy: Int): Int {
if (childCount == 0) { if (isEmpty()) {
return 0 return 0
} }
when { when {

@ -3,7 +3,7 @@ package org.koitharu.kotatsu.scrobbling.common.ui
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import androidx.core.net.toUri
import org.koitharu.kotatsu.scrobbling.common.domain.ScrobblerRepositoryMap import org.koitharu.kotatsu.scrobbling.common.domain.ScrobblerRepositoryMap
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser
@ -31,7 +31,7 @@ class ScrobblerAuthHelper @Inject constructor(
} else { } else {
val repository = repositoriesMap[scrobbler] val repository = repositoriesMap[scrobbler]
val intent = Intent(Intent.ACTION_VIEW) val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse(repository.oauthUrl) intent.data = repository.oauthUrl.toUri()
context.startActivity(intent) context.startActivity(intent)
} }
} }

@ -6,7 +6,6 @@ import android.view.View
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import coil3.ImageLoader
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
@ -24,25 +23,21 @@ import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo
import org.koitharu.kotatsu.scrobbling.common.ui.config.adapter.ScrobblingMangaAdapter import org.koitharu.kotatsu.scrobbling.common.ui.config.adapter.ScrobblingMangaAdapter
import javax.inject.Inject
import androidx.appcompat.R as appcompatR import androidx.appcompat.R as appcompatR
@AndroidEntryPoint @AndroidEntryPoint
class ScrobblerConfigActivity : BaseActivity<ActivityScrobblerConfigBinding>(), class ScrobblerConfigActivity : BaseActivity<ActivityScrobblerConfigBinding>(),
OnListItemClickListener<ScrobblingInfo>, View.OnClickListener { OnListItemClickListener<ScrobblingInfo>, View.OnClickListener {
@Inject
lateinit var coil: ImageLoader
private val viewModel: ScrobblerConfigViewModel by viewModels() private val viewModel: ScrobblerConfigViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityScrobblerConfigBinding.inflate(layoutInflater)) setContentView(ActivityScrobblerConfigBinding.inflate(layoutInflater))
setTitle(viewModel.titleResId) setTitle(viewModel.titleResId)
setDisplayHomeAsUp(true, false) setDisplayHomeAsUp(isEnabled = true, showUpAsClose = false)
val listAdapter = ScrobblingMangaAdapter(this, coil, this) val listAdapter = ScrobblingMangaAdapter(this)
with(viewBinding.recyclerView) { with(viewBinding.recyclerView) {
adapter = listAdapter adapter = listAdapter
setHasFixedSize(true) setHasFixedSize(true)

@ -1,7 +1,5 @@
package org.koitharu.kotatsu.scrobbling.common.ui.config.adapter package org.koitharu.kotatsu.scrobbling.common.ui.config.adapter
import androidx.lifecycle.LifecycleOwner
import coil3.ImageLoader
import org.koitharu.kotatsu.core.ui.BaseListAdapter import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.list.ui.adapter.ListItemType import org.koitharu.kotatsu.list.ui.adapter.ListItemType
@ -11,8 +9,6 @@ import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo
class ScrobblingMangaAdapter( class ScrobblingMangaAdapter(
clickListener: OnListItemClickListener<ScrobblingInfo>, clickListener: OnListItemClickListener<ScrobblingInfo>,
coil: ImageLoader,
lifecycleOwner: LifecycleOwner,
) : BaseListAdapter<ListModel>() { ) : BaseListAdapter<ListModel>() {
init { init {

@ -12,7 +12,6 @@ import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.AsyncListDiffer import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.RecyclerView.NO_ID import androidx.recyclerview.widget.RecyclerView.NO_ID
import coil3.ImageLoader
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -40,7 +39,6 @@ import org.koitharu.kotatsu.list.ui.model.LoadingFooter
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga
import org.koitharu.kotatsu.scrobbling.common.ui.selector.adapter.ScrobblerMangaSelectionDecoration import org.koitharu.kotatsu.scrobbling.common.ui.selector.adapter.ScrobblerMangaSelectionDecoration
import org.koitharu.kotatsu.scrobbling.common.ui.selector.adapter.ScrobblerSelectorAdapter import org.koitharu.kotatsu.scrobbling.common.ui.selector.adapter.ScrobblerSelectorAdapter
import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class ScrobblingSelectorSheet : class ScrobblingSelectorSheet :
@ -54,9 +52,6 @@ class ScrobblingSelectorSheet :
ListStateHolderListener, ListStateHolderListener,
AsyncListDiffer.ListListener<ListModel> { AsyncListDiffer.ListListener<ListModel> {
@Inject
lateinit var coil: ImageLoader
private var collapsibleActionViewCallback: CollapseActionViewCallback? = null private var collapsibleActionViewCallback: CollapseActionViewCallback? = null
private var paginationScrollListener: PaginationScrollListener? = null private var paginationScrollListener: PaginationScrollListener? = null
private val viewModel by viewModels<ScrobblingSelectorViewModel>() private val viewModel by viewModels<ScrobblingSelectorViewModel>()
@ -68,7 +63,7 @@ class ScrobblingSelectorSheet :
override fun onViewBindingCreated(binding: SheetScrobblingSelectorBinding, savedInstanceState: Bundle?) { override fun onViewBindingCreated(binding: SheetScrobblingSelectorBinding, savedInstanceState: Bundle?) {
super.onViewBindingCreated(binding, savedInstanceState) super.onViewBindingCreated(binding, savedInstanceState)
disableFitToContents() disableFitToContents()
val listAdapter = ScrobblerSelectorAdapter(viewLifecycleOwner, coil, this, this) val listAdapter = ScrobblerSelectorAdapter(this, this)
listAdapter.addListListener(this) listAdapter.addListListener(this)
val decoration = ScrobblerMangaSelectionDecoration(binding.root.context) val decoration = ScrobblerMangaSelectionDecoration(binding.root.context)
with(binding.recyclerView) { with(binding.recyclerView) {

@ -1,7 +1,5 @@
package org.koitharu.kotatsu.scrobbling.common.ui.selector.adapter package org.koitharu.kotatsu.scrobbling.common.ui.selector.adapter
import androidx.lifecycle.LifecycleOwner
import coil3.ImageLoader
import org.koitharu.kotatsu.core.ui.BaseListAdapter import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.list.ui.adapter.ListItemType import org.koitharu.kotatsu.list.ui.adapter.ListItemType
@ -12,8 +10,6 @@ import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga
class ScrobblerSelectorAdapter( class ScrobblerSelectorAdapter(
lifecycleOwner: LifecycleOwner,
coil: ImageLoader,
clickListener: OnListItemClickListener<ScrobblerManga>, clickListener: OnListItemClickListener<ScrobblerManga>,
stateHolderListener: ListStateHolderListener, stateHolderListener: ListStateHolderListener,
) : BaseListAdapter<ListModel>() { ) : BaseListAdapter<ListModel>() {

@ -76,7 +76,7 @@ class MangaListActivity :
val filter = intent.getParcelableExtraCompat<ParcelableMangaListFilter>(AppRouter.KEY_FILTER)?.filter val filter = intent.getParcelableExtraCompat<ParcelableMangaListFilter>(AppRouter.KEY_FILTER)?.filter
val sortOrder = intent.getSerializableExtraCompat<SortOrder>(AppRouter.KEY_SORT_ORDER) val sortOrder = intent.getSerializableExtraCompat<SortOrder>(AppRouter.KEY_SORT_ORDER)
source = MangaSource(intent.getStringExtra(AppRouter.KEY_SOURCE)) source = MangaSource(intent.getStringExtra(AppRouter.KEY_SOURCE))
setDisplayHomeAsUp(true, false) setDisplayHomeAsUp(isEnabled = true, showUpAsClose = false)
if (viewBinding.containerFilterHeader != null) { if (viewBinding.containerFilterHeader != null) {
viewBinding.appbar.addOnOffsetChangedListener(this) viewBinding.appbar.addOnOffsetChangedListener(this)
} }

@ -6,6 +6,7 @@ import android.content.Context
import android.content.SearchRecentSuggestionsProvider import android.content.SearchRecentSuggestionsProvider
import android.net.Uri import android.net.Uri
import android.provider.SearchRecentSuggestions import android.provider.SearchRecentSuggestions
import androidx.core.net.toUri
import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.BuildConfig
class MangaSuggestionsProvider : SearchRecentSuggestionsProvider() { class MangaSuggestionsProvider : SearchRecentSuggestionsProvider() {
@ -29,6 +30,6 @@ class MangaSuggestionsProvider : SearchRecentSuggestionsProvider() {
.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY) .appendPath(SearchManager.SUGGEST_URI_PATH_QUERY)
.build() .build()
val URI: Uri = Uri.parse("content://$AUTHORITY/suggestions") val URI: Uri = "content://$AUTHORITY/suggestions".toUri()
} }
} }

@ -9,7 +9,6 @@ import androidx.activity.viewModels
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import coil3.ImageLoader
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.exceptions.resolve.SnackbarErrorObserver import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
@ -44,9 +43,6 @@ class SearchActivity :
MangaListListener, MangaListListener,
ListSelectionController.Callback { ListSelectionController.Callback {
@Inject
lateinit var coil: ImageLoader
@Inject @Inject
lateinit var settings: AppSettings lateinit var settings: AppSettings
@ -85,8 +81,6 @@ class SearchActivity :
callback = this, callback = this,
) )
val adapter = SearchAdapter( val adapter = SearchAdapter(
lifecycleOwner = this,
coil = coil,
listener = this, listener = this,
itemClickListener = itemClickListener, itemClickListener = itemClickListener,
sizeResolver = sizeResolver, sizeResolver = sizeResolver,
@ -96,7 +90,7 @@ class SearchActivity :
viewBinding.recyclerView.setHasFixedSize(true) viewBinding.recyclerView.setHasFixedSize(true)
viewBinding.recyclerView.addItemDecoration(TypedListSpacingDecoration(this, true)) viewBinding.recyclerView.addItemDecoration(TypedListSpacingDecoration(this, true))
setDisplayHomeAsUp(true, false) setDisplayHomeAsUp(isEnabled = true, showUpAsClose = false)
supportActionBar?.setSubtitle(R.string.search_results) supportActionBar?.setSubtitle(R.string.search_results)
addMenuProvider(SearchKindMenuProvider(this, viewModel.query, viewModel.kind)) addMenuProvider(SearchKindMenuProvider(this, viewModel.query, viewModel.kind))

@ -1,9 +1,7 @@
package org.koitharu.kotatsu.search.ui.multi.adapter package org.koitharu.kotatsu.search.ui.multi.adapter
import android.content.Context import android.content.Context
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.RecyclerView.RecycledViewPool import androidx.recyclerview.widget.RecyclerView.RecycledViewPool
import coil3.ImageLoader
import org.koitharu.kotatsu.core.ui.BaseListAdapter import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller
@ -20,8 +18,6 @@ import org.koitharu.kotatsu.list.ui.size.ItemSizeResolver
import org.koitharu.kotatsu.search.ui.multi.SearchResultsListModel import org.koitharu.kotatsu.search.ui.multi.SearchResultsListModel
class SearchAdapter( class SearchAdapter(
lifecycleOwner: LifecycleOwner,
coil: ImageLoader,
listener: MangaListListener, listener: MangaListListener,
itemClickListener: OnListItemClickListener<SearchResultsListModel>, itemClickListener: OnListItemClickListener<SearchResultsListModel>,
sizeResolver: ItemSizeResolver, sizeResolver: ItemSizeResolver,

@ -1,5 +1,6 @@
package org.koitharu.kotatsu.search.ui.multi.adapter package org.koitharu.kotatsu.search.ui.multi.adapter
import android.annotation.SuppressLint
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView.RecycledViewPool import androidx.recyclerview.widget.RecyclerView.RecycledViewPool
@ -20,6 +21,7 @@ import org.koitharu.kotatsu.list.ui.size.ItemSizeResolver
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.search.ui.multi.SearchResultsListModel import org.koitharu.kotatsu.search.ui.multi.SearchResultsListModel
@SuppressLint("NotifyDataSetChanged")
fun searchResultsAD( fun searchResultsAD(
sharedPool: RecycledViewPool, sharedPool: RecycledViewPool,
sizeResolver: ItemSizeResolver, sizeResolver: ItemSizeResolver,

@ -7,7 +7,6 @@ import android.view.ViewGroup
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import coil3.ImageLoader
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.core.os.VoiceInputContract import org.koitharu.kotatsu.core.os.VoiceInputContract
import org.koitharu.kotatsu.core.ui.BaseFragment import org.koitharu.kotatsu.core.ui.BaseFragment
@ -16,16 +15,12 @@ import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.databinding.FragmentSearchSuggestionBinding import org.koitharu.kotatsu.databinding.FragmentSearchSuggestionBinding
import org.koitharu.kotatsu.search.ui.suggestion.adapter.SearchSuggestionAdapter import org.koitharu.kotatsu.search.ui.suggestion.adapter.SearchSuggestionAdapter
import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class SearchSuggestionFragment : class SearchSuggestionFragment :
BaseFragment<FragmentSearchSuggestionBinding>(), BaseFragment<FragmentSearchSuggestionBinding>(),
SearchSuggestionItemCallback.SuggestionItemListener { SearchSuggestionItemCallback.SuggestionItemListener {
@Inject
lateinit var coil: ImageLoader
private val viewModel by activityViewModels<SearchSuggestionViewModel>() private val viewModel by activityViewModels<SearchSuggestionViewModel>()
private val voiceInputLauncher = registerForActivityResult(VoiceInputContract()) { result -> private val voiceInputLauncher = registerForActivityResult(VoiceInputContract()) { result ->
if (result != null) { if (result != null) {
@ -41,8 +36,6 @@ class SearchSuggestionFragment :
override fun onViewBindingCreated(binding: FragmentSearchSuggestionBinding, savedInstanceState: Bundle?) { override fun onViewBindingCreated(binding: FragmentSearchSuggestionBinding, savedInstanceState: Bundle?) {
super.onViewBindingCreated(binding, savedInstanceState) super.onViewBindingCreated(binding, savedInstanceState)
val adapter = SearchSuggestionAdapter( val adapter = SearchSuggestionAdapter(
coil = coil,
lifecycleOwner = viewLifecycleOwner,
listener = requireActivity() as SearchSuggestionListener, listener = requireActivity() as SearchSuggestionListener,
) )
addMenuProvider(SearchSuggestionMenuProvider(binding.root.context, voiceInputLauncher, viewModel)) addMenuProvider(SearchSuggestionMenuProvider(binding.root.context, voiceInputLauncher, viewModel))

@ -1,7 +1,5 @@
package org.koitharu.kotatsu.search.ui.suggestion.adapter package org.koitharu.kotatsu.search.ui.suggestion.adapter
import androidx.lifecycle.LifecycleOwner
import coil3.ImageLoader
import org.koitharu.kotatsu.core.ui.BaseListAdapter import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener
import org.koitharu.kotatsu.search.ui.suggestion.model.SearchSuggestionItem import org.koitharu.kotatsu.search.ui.suggestion.model.SearchSuggestionItem
@ -9,8 +7,6 @@ import org.koitharu.kotatsu.search.ui.suggestion.model.SearchSuggestionItem
const val SEARCH_SUGGESTION_ITEM_TYPE_QUERY = 0 const val SEARCH_SUGGESTION_ITEM_TYPE_QUERY = 0
class SearchSuggestionAdapter( class SearchSuggestionAdapter(
coil: ImageLoader,
lifecycleOwner: LifecycleOwner,
listener: SearchSuggestionListener, listener: SearchSuggestionListener,
) : BaseListAdapter<SearchSuggestionItem>() { ) : BaseListAdapter<SearchSuggestionItem>() {

@ -6,25 +6,18 @@ import android.view.View
import androidx.preference.ListPreference import androidx.preference.ListPreference
import androidx.preference.Preference import androidx.preference.Preference
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.cache.MemoryContentCache
import org.koitharu.kotatsu.core.network.DoHProvider import org.koitharu.kotatsu.core.network.DoHProvider
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.ui.BasePreferenceFragment import org.koitharu.kotatsu.core.ui.BasePreferenceFragment
import org.koitharu.kotatsu.core.util.ext.setDefaultValueCompat import org.koitharu.kotatsu.core.util.ext.setDefaultValueCompat
import org.koitharu.kotatsu.parsers.util.names import org.koitharu.kotatsu.parsers.util.names
import java.net.Proxy import java.net.Proxy
import javax.inject.Inject
@AndroidEntryPoint
class NetworkSettingsFragment : class NetworkSettingsFragment :
BasePreferenceFragment(R.string.network), BasePreferenceFragment(R.string.network),
SharedPreferences.OnSharedPreferenceChangeListener { SharedPreferences.OnSharedPreferenceChangeListener {
@Inject
lateinit var contentCache: MemoryContentCache
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.pref_network) addPreferencesFromResource(R.xml.pref_network)
findPreference<ListPreference>(AppSettings.KEY_DOH)?.run { findPreference<ListPreference>(AppSettings.KEY_DOH)?.run {

@ -8,7 +8,6 @@ import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import coil3.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 kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.filterNotNull
@ -24,7 +23,6 @@ import org.koitharu.kotatsu.core.util.ext.tryLaunch
import org.koitharu.kotatsu.databinding.ActivityOverrideEditBinding import org.koitharu.kotatsu.databinding.ActivityOverrideEditBinding
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.util.ifNullOrEmpty import org.koitharu.kotatsu.parsers.util.ifNullOrEmpty
import javax.inject.Inject
import androidx.appcompat.R as appcompatR import androidx.appcompat.R as appcompatR
import com.google.android.material.R as materialR import com.google.android.material.R as materialR
@ -42,9 +40,6 @@ class OverrideConfigActivity : BaseActivity<ActivityOverrideEditBinding>(), View
} }
} }
@Inject
lateinit var coil: ImageLoader
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityOverrideEditBinding.inflate(layoutInflater)) setContentView(ActivityOverrideEditBinding.inflate(layoutInflater))

@ -40,7 +40,7 @@ class ReaderTapGridConfigActivity : BaseActivity<ActivityReaderTapActionsBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityReaderTapActionsBinding.inflate(layoutInflater)) setContentView(ActivityReaderTapActionsBinding.inflate(layoutInflater))
setDisplayHomeAsUp(true, false) setDisplayHomeAsUp(isEnabled = true, showUpAsClose = false)
controls[TapGridArea.TOP_LEFT] = viewBinding.textViewTopLeft controls[TapGridArea.TOP_LEFT] = viewBinding.textViewTopLeft
controls[TapGridArea.TOP_CENTER] = viewBinding.textViewTopCenter controls[TapGridArea.TOP_CENTER] = viewBinding.textViewTopCenter
controls[TapGridArea.TOP_RIGHT] = viewBinding.textViewTopRight controls[TapGridArea.TOP_RIGHT] = viewBinding.textViewTopRight

@ -8,7 +8,6 @@ import androidx.preference.PreferenceManager
import androidx.preference.PreferenceScreen import androidx.preference.PreferenceScreen
import androidx.preference.get import androidx.preference.get
import dagger.Reusable import dagger.Reusable
import dagger.hilt.android.qualifiers.ApplicationContext
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.LocalizedAppContext import org.koitharu.kotatsu.core.LocalizedAppContext
import org.koitharu.kotatsu.settings.AppearanceSettingsFragment import org.koitharu.kotatsu.settings.AppearanceSettingsFragment

@ -1,14 +1,10 @@
package org.koitharu.kotatsu.settings.sources.adapter package org.koitharu.kotatsu.settings.sources.adapter
import androidx.lifecycle.LifecycleOwner
import coil3.ImageLoader
import org.koitharu.kotatsu.core.ui.ReorderableListAdapter import org.koitharu.kotatsu.core.ui.ReorderableListAdapter
import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem
class SourceConfigAdapter( class SourceConfigAdapter(
listener: SourceConfigListener, listener: SourceConfigListener,
coil: ImageLoader,
lifecycleOwner: LifecycleOwner,
) : ReorderableListAdapter<SourceConfigItem>() { ) : ReorderableListAdapter<SourceConfigItem>() {
init { init {

@ -3,7 +3,6 @@ package org.koitharu.kotatsu.settings.sources.manage
import android.content.Context import android.content.Context
import androidx.room.InvalidationTracker import androidx.room.InvalidationTracker
import dagger.hilt.android.ViewModelLifecycle import dagger.hilt.android.ViewModelLifecycle
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.scopes.ViewModelScoped import dagger.hilt.android.scopes.ViewModelScoped
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.cancelAndJoin

@ -13,7 +13,6 @@ import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import coil3.ImageLoader
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
@ -49,9 +48,6 @@ class SourcesManageFragment :
SourceConfigListener, SourceConfigListener,
RecyclerViewOwner { RecyclerViewOwner {
@Inject
lateinit var coil: ImageLoader
@Inject @Inject
lateinit var settings: AppSettings lateinit var settings: AppSettings
@ -75,7 +71,7 @@ class SourcesManageFragment :
savedInstanceState: Bundle?, savedInstanceState: Bundle?,
) { ) {
super.onViewBindingCreated(binding, savedInstanceState) super.onViewBindingCreated(binding, savedInstanceState)
sourcesAdapter = SourceConfigAdapter(this, coil, viewLifecycleOwner) sourcesAdapter = SourceConfigAdapter(this)
with(binding.recyclerView) { with(binding.recyclerView) {
setHasFixedSize(true) setHasFixedSize(true)
adapter = sourcesAdapter adapter = sourcesAdapter

@ -62,7 +62,7 @@ class MangaDirectoriesActivity : BaseActivity<ActivityMangaDirectoriesBinding>()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityMangaDirectoriesBinding.inflate(layoutInflater)) setContentView(ActivityMangaDirectoriesBinding.inflate(layoutInflater))
setDisplayHomeAsUp(true, false) setDisplayHomeAsUp(isEnabled = true, showUpAsClose = false)
val adapter = AsyncListDifferDelegationAdapter(DirectoryDiffCallback(), directoryConfigAD(this)) val adapter = AsyncListDifferDelegationAdapter(DirectoryDiffCallback(), directoryConfigAD(this))
viewBinding.recyclerView.adapter = adapter viewBinding.recyclerView.adapter = adapter
viewBinding.fabAdd.setOnClickListener(this) viewBinding.fabAdd.setOnClickListener(this)

@ -7,6 +7,7 @@ import android.util.AttributeSet
import androidx.preference.ListPreference import androidx.preference.ListPreference
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
@Suppress("unused")
class ActivityListPreference : ListPreference { class ActivityListPreference : ListPreference {
var activityIntent: Intent? = null var activityIntent: Intent? = null

@ -11,6 +11,7 @@ import android.view.View
import android.view.ViewTreeObserver import android.view.ViewTreeObserver
import android.widget.HorizontalScrollView import android.widget.HorizontalScrollView
import androidx.appcompat.view.ContextThemeWrapper import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.view.isEmpty
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updatePaddingRelative import androidx.core.view.updatePaddingRelative
import androidx.customview.view.AbsSavedState import androidx.customview.view.AbsSavedState
@ -55,7 +56,7 @@ class ThemeChooserPreference @JvmOverloads constructor(
val context = ContextThemeWrapper(context, theme.styleResId) val context = ContextThemeWrapper(context, theme.styleResId)
val item = val item =
ItemColorSchemeBinding.inflate(LayoutInflater.from(context), binding.linear, false) ItemColorSchemeBinding.inflate(LayoutInflater.from(context), binding.linear, false)
if (binding.linear.childCount == 0) { if (binding.linear.isEmpty()) {
item.root.updatePaddingRelative(start = 0) item.root.updatePaddingRelative(start = 0)
} }
val isSelected = theme == currentValue val isSelected = theme == currentValue

@ -16,7 +16,6 @@ import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePaddingRelative import androidx.core.view.updatePaddingRelative
import androidx.recyclerview.widget.AsyncListDiffer import androidx.recyclerview.widget.AsyncListDiffer
import coil3.ImageLoader
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipDrawable import com.google.android.material.chip.ChipDrawable
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@ -42,7 +41,6 @@ import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.stats.domain.StatsPeriod import org.koitharu.kotatsu.stats.domain.StatsPeriod
import org.koitharu.kotatsu.stats.domain.StatsRecord import org.koitharu.kotatsu.stats.domain.StatsRecord
import org.koitharu.kotatsu.stats.ui.views.PieChartView import org.koitharu.kotatsu.stats.ui.views.PieChartView
import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class StatsActivity : BaseActivity<ActivityStatsBinding>(), class StatsActivity : BaseActivity<ActivityStatsBinding>(),
@ -53,15 +51,12 @@ class StatsActivity : BaseActivity<ActivityStatsBinding>(),
View.OnClickListener, View.OnClickListener,
CompoundButton.OnCheckedChangeListener { CompoundButton.OnCheckedChangeListener {
@Inject
lateinit var coil: ImageLoader
private val viewModel: StatsViewModel by viewModels() private val viewModel: StatsViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityStatsBinding.inflate(layoutInflater)) setContentView(ActivityStatsBinding.inflate(layoutInflater))
setDisplayHomeAsUp(true, false) setDisplayHomeAsUp(isEnabled = true, showUpAsClose = false)
val adapter = BaseListAdapter<StatsRecord>() val adapter = BaseListAdapter<StatsRecord>()
.addDelegate(ListItemType.FEED, statsAD(this)) .addDelegate(ListItemType.FEED, statsAD(this))
.addListListener(this) .addListListener(this)

@ -1,6 +1,5 @@
package org.koitharu.kotatsu.stats.ui.sheet package org.koitharu.kotatsu.stats.ui.sheet
import androidx.collection.IntList
import androidx.collection.MutableIntList import androidx.collection.MutableIntList
import androidx.collection.emptyIntList import androidx.collection.emptyIntList
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
@ -26,7 +25,7 @@ class MangaStatsViewModel @Inject constructor(
val manga = savedStateHandle.require<ParcelableManga>(AppRouter.KEY_MANGA).manga val manga = savedStateHandle.require<ParcelableManga>(AppRouter.KEY_MANGA).manga
val stats = MutableStateFlow<IntList>(emptyIntList()) val stats = MutableStateFlow(emptyIntList())
val startDate = MutableStateFlow<DateTimeAgo?>(null) val startDate = MutableStateFlow<DateTimeAgo?>(null)
val totalPagesRead = MutableStateFlow(0) val totalPagesRead = MutableStateFlow(0)

@ -9,10 +9,10 @@ import android.content.OperationApplicationException
import android.content.SyncResult import android.content.SyncResult
import android.content.SyncStats import android.content.SyncStats
import android.database.Cursor import android.database.Cursor
import android.net.Uri
import android.util.Log import android.util.Log
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import androidx.core.content.contentValuesOf import androidx.core.content.contentValuesOf
import androidx.core.net.toUri
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
@ -288,7 +288,7 @@ class SyncHelper @AssistedInject constructor(
?: throw OperationApplicationException("Query failed: $uri") ?: throw OperationApplicationException("Query failed: $uri")
} }
private fun uri(authority: String, table: String) = Uri.parse("content://$authority/$table") private fun uri(authority: String, table: String) = "content://$authority/$table".toUri()
private fun JSONObject.removeJSONObject(name: String) = remove(name) as JSONObject private fun JSONObject.removeJSONObject(name: String) = remove(name) as JSONObject

@ -5,7 +5,6 @@ import android.view.View
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import coil3.ImageLoader
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.core.nav.router import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
@ -17,20 +16,16 @@ import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityTrackerDebugBinding import org.koitharu.kotatsu.databinding.ActivityTrackerDebugBinding
import org.koitharu.kotatsu.list.ui.adapter.ListItemType import org.koitharu.kotatsu.list.ui.adapter.ListItemType
import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration
import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class TrackerDebugActivity : BaseActivity<ActivityTrackerDebugBinding>(), OnListItemClickListener<TrackDebugItem> { class TrackerDebugActivity : BaseActivity<ActivityTrackerDebugBinding>(), OnListItemClickListener<TrackDebugItem> {
@Inject
lateinit var coil: ImageLoader
private val viewModel by viewModels<TrackerDebugViewModel>() private val viewModel by viewModels<TrackerDebugViewModel>()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityTrackerDebugBinding.inflate(layoutInflater)) setContentView(ActivityTrackerDebugBinding.inflate(layoutInflater))
setDisplayHomeAsUp(true, false) setDisplayHomeAsUp(isEnabled = true, showUpAsClose = false)
val tracksAdapter = BaseListAdapter<TrackDebugItem>() val tracksAdapter = BaseListAdapter<TrackDebugItem>()
.addDelegate(ListItemType.FEED, trackDebugAD(this)) .addDelegate(ListItemType.FEED, trackDebugAD(this))
with(viewBinding.recyclerView) { with(viewBinding.recyclerView) {

@ -23,7 +23,7 @@ class RecentWidgetConfigActivity :
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityAppwidgetRecentBinding.inflate(layoutInflater)) setContentView(ActivityAppwidgetRecentBinding.inflate(layoutInflater))
setDisplayHomeAsUp(true, true) setDisplayHomeAsUp(isEnabled = true, showUpAsClose = true)
viewBinding.buttonDone.setOnClickListener(this) viewBinding.buttonDone.setOnClickListener(this)
val appWidgetId = intent?.getIntExtra( val appWidgetId = intent?.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.EXTRA_APPWIDGET_ID,

@ -5,9 +5,9 @@ import android.appwidget.AppWidgetManager
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.net.Uri
import android.widget.RemoteViews import android.widget.RemoteViews
import androidx.core.app.PendingIntentCompat import androidx.core.app.PendingIntentCompat
import androidx.core.net.toUri
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.nav.ReaderIntent import org.koitharu.kotatsu.core.nav.ReaderIntent
import org.koitharu.kotatsu.core.prefs.AppWidgetConfig import org.koitharu.kotatsu.core.prefs.AppWidgetConfig
@ -34,7 +34,7 @@ class RecentWidgetProvider : BaseAppWidgetProvider() {
} }
val adapter = Intent(context, RecentWidgetService::class.java) val adapter = Intent(context, RecentWidgetService::class.java)
adapter.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, config.widgetId) adapter.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, config.widgetId)
adapter.data = Uri.parse(adapter.toUri(Intent.URI_INTENT_SCHEME)) adapter.data = adapter.toUri(Intent.URI_INTENT_SCHEME).toUri()
views.setRemoteAdapter(R.id.stackView, adapter) views.setRemoteAdapter(R.id.stackView, adapter)
val intent = Intent(context, ReaderActivity::class.java) val intent = Intent(context, ReaderActivity::class.java)
intent.action = ReaderIntent.ACTION_MANGA_READ intent.action = ReaderIntent.ACTION_MANGA_READ

@ -35,7 +35,7 @@ class ShelfWidgetConfigActivity :
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityAppwidgetShelfBinding.inflate(layoutInflater)) setContentView(ActivityAppwidgetShelfBinding.inflate(layoutInflater))
setDisplayHomeAsUp(true, true) setDisplayHomeAsUp(isEnabled = true, showUpAsClose = true)
adapter = CategorySelectAdapter(this) adapter = CategorySelectAdapter(this)
viewBinding.recyclerView.adapter = adapter viewBinding.recyclerView.adapter = adapter
viewBinding.buttonDone.setOnClickListener(this) viewBinding.buttonDone.setOnClickListener(this)

@ -5,9 +5,9 @@ import android.appwidget.AppWidgetManager
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.net.Uri
import android.widget.RemoteViews import android.widget.RemoteViews
import androidx.core.app.PendingIntentCompat import androidx.core.app.PendingIntentCompat
import androidx.core.net.toUri
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.nav.ReaderIntent import org.koitharu.kotatsu.core.nav.ReaderIntent
import org.koitharu.kotatsu.core.prefs.AppWidgetConfig import org.koitharu.kotatsu.core.prefs.AppWidgetConfig
@ -34,7 +34,7 @@ class ShelfWidgetProvider : BaseAppWidgetProvider() {
} }
val adapter = Intent(context, ShelfWidgetService::class.java) val adapter = Intent(context, ShelfWidgetService::class.java)
adapter.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, config.widgetId) adapter.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, config.widgetId)
adapter.data = Uri.parse(adapter.toUri(Intent.URI_INTENT_SCHEME)) adapter.data = adapter.toUri(Intent.URI_INTENT_SCHEME).toUri()
views.setRemoteAdapter(R.id.gridView, adapter) views.setRemoteAdapter(R.id.gridView, adapter)
val intent = Intent(context, ReaderActivity::class.java) val intent = Intent(context, ReaderActivity::class.java)
intent.action = ReaderIntent.ACTION_MANGA_READ intent.action = ReaderIntent.ACTION_MANGA_READ

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="0.2" android:color="@color/kotatsu_primary" />
</selector>

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/kotatsu_secondaryContainer" android:state_checked="true" />
<item android:color="@color/kotatsu_onSurfaceVariant" android:state_checked="false" />
</selector>

@ -1,11 +0,0 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="60dp"
android:height="60dp"
android:tint="?attr/colorTertiary"
android:viewportWidth="60"
android:viewportHeight="60">
<path
android:fillColor="#FF000000"
android:pathData="M21.7,40c-0.4,0 -0.8,-0.2 -1.2,-0.5c-0.3,-0.3 -0.5,-0.7 -0.5,-1.2V21.7c0,-0.4 0.2,-0.8 0.5,-1.2s0.7,-0.5 1.2,-0.5h16.7c0.4,0 0.8,0.2 1.2,0.5s0.5,0.7 0.5,1.2v16.7c0,0.4 -0.2,0.8 -0.5,1.2c-0.3,0.3 -0.7,0.5 -1.2,0.5H21.7zM22.9,31.3l4.8,-4.8l4.7,4.7l4.8,-4.8l1.2,1.2v-6H21.7v8.4L22.9,31.3zM21.7,38.4h16.7v-8.3l-1.2,-1.2l-4.8,4.8l-4.7,-4.7l-4.8,4.8l-1.2,-1.2V38.4zM21.7,38.4v-8.3v1.7V21.7V38.4z" />
</vector>

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M17,12A5,5 0 0,1 12,17A5,5 0 0,1 7,12C7,9.58 8.72,7.56 11,7.1V3H13V7.1C15.28,7.56 17,9.58 17,12M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9Z" />
</vector>

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M7,12A5,5 0 0,1 12,7A5,5 0 0,1 17,12C17,14.42 15.28,16.44 13,16.9V21H11V16.9C8.72,16.44 7,14.42 7,12M12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15M13,3V5H11V3H13Z" />
</vector>

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M12,7A5,5 0 0,1 17,12C17,14.42 15.28,16.44 13,16.9V21H11V16.9C8.72,16.44 7,14.42 7,12A5,5 0 0,1 12,7M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9Z" />
</vector>

@ -64,7 +64,7 @@
app:fabSize="normal" app:fabSize="normal"
app:layout_anchor="@id/recyclerView" app:layout_anchor="@id/recyclerView"
app:layout_anchorGravity="bottom|end" app:layout_anchorGravity="bottom|end"
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior" app:layout_behavior="com.google.android.material.behavior.HideViewOnScrollBehavior"
app:layout_dodgeInsetEdges="bottom" /> app:layout_dodgeInsetEdges="bottom" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

@ -13,6 +13,7 @@
android:layout_height="@dimen/category_covers_height" android:layout_height="@dimen/category_covers_height"
android:layout_marginStart="@dimen/screen_padding" android:layout_marginStart="@dimen/screen_padding"
app:coverSize="3.4dp" app:coverSize="3.4dp"
app:hideEmptyViews="true"
app:layout_constraintDimensionRatio="13:18" app:layout_constraintDimensionRatio="13:18"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout <FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu <menu
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:tools="http://schemas.android.com/tools">
<item <item
android:id="@+id/action_clear" android:id="@+id/action_clear"

@ -31,6 +31,7 @@
<declare-styleable name="CoverStackView"> <declare-styleable name="CoverStackView">
<attr name="coverSize" format="dimension" /> <attr name="coverSize" format="dimension" />
<attr name="hideEmptyViews" format="boolean" />
</declare-styleable> </declare-styleable>
<declare-styleable name="FaviconView"> <declare-styleable name="FaviconView">

@ -17,7 +17,7 @@ diskLruCache = "1.5"
fragment = "1.8.6" fragment = "1.8.6"
gradle = "8.9.1" gradle = "8.9.1"
guava = "33.4.8-android" guava = "33.4.8-android"
dagger = "2.56.1" dagger = "2.56.2"
hilt = "1.2.0" hilt = "1.2.0"
json = "20250107" json = "20250107"
junit = "4.13.2" junit = "4.13.2"
@ -27,22 +27,22 @@ ksp = "2.1.20-2.0.0"
leakcanary = "3.0-alpha-8" leakcanary = "3.0-alpha-8"
lifecycle = "2.8.7" lifecycle = "2.8.7"
markwon = "4.6.2" markwon = "4.6.2"
material = "1.13.0-alpha12" material = "1.13.0-alpha13"
moshi = "1.15.2" moshi = "1.15.2"
okhttp = "4.12.0" okhttp = "4.12.0"
okio = "3.11.0" okio = "3.11.0"
parsers = "e874837efb" parsers = "e874837efb"
preference = "1.2.1" preference = "1.2.1"
recyclerview = "1.4.0" recyclerview = "1.4.0"
room = "2.7.0" room = "2.7.1"
ssiv = "9a67b6a7c9" ssiv = "9a67b6a7c9"
swiperefreshlayout = "1.1.0" swiperefreshlayout = "1.1.0"
testRules = "1.6.1" testRules = "1.6.1"
testRunner = "1.6.2" testRunner = "1.6.2"
transition = "1.5.1" transition = "1.6.0"
viewpager2 = "1.1.0" viewpager2 = "1.1.0"
webkit = "1.13.0" webkit = "1.13.0"
workRuntime = "2.10.0" workRuntime = "2.10.1"
workinspector = "1.2" workinspector = "1.2"
[libraries] [libraries]

Loading…
Cancel
Save