Fix some warnings and remove unused code

pull/592/head
Koitharu 2 years ago
parent 0d62408918
commit b2e53d4938
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -40,7 +40,7 @@ open class BaseApp : Application(), Configuration.Provider {
lateinit var activityLifecycleCallbacks: Set<@JvmSuppressWildcards ActivityLifecycleCallbacks>
@Inject
lateinit var database: MangaDatabase
lateinit var database: Provider<MangaDatabase>
@Inject
lateinit var settings: AppSettings
@ -52,7 +52,7 @@ open class BaseApp : Application(), Configuration.Provider {
lateinit var appValidator: AppValidator
@Inject
lateinit var workScheduleManager: WorkScheduleManager
lateinit var workScheduleManager: Provider<WorkScheduleManager>
@Inject
lateinit var workManagerProvider: Provider<WorkManager>
@ -76,7 +76,7 @@ open class BaseApp : Application(), Configuration.Provider {
processLifecycleScope.launch(Dispatchers.Default) {
setupDatabaseObservers()
}
workScheduleManager.init()
workScheduleManager.get().init()
WorkServiceStopHelper(workManagerProvider).setup()
}
@ -115,7 +115,7 @@ open class BaseApp : Application(), Configuration.Provider {
@WorkerThread
private fun setupDatabaseObservers() {
val tracker = database.invalidationTracker
val tracker = database.get().invalidationTracker
databaseObservers.forEach {
tracker.addObserver(it)
}

@ -12,7 +12,7 @@ class ExpiringLruCache<T>(
private val cache = LruCache<ContentCache.Key, ExpiringValue<T>>(maxSize)
operator fun get(key: ContentCache.Key): T? {
val value = cache.get(key) ?: return null
val value = cache[key] ?: return null
if (value.isExpired) {
cache.remove(key)
}

@ -1,8 +0,0 @@
package org.koitharu.kotatsu.core.exceptions
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
class CompositeException(val errors: Collection<Throwable>) : Exception() {
override val message: String = errors.mapNotNullToSet { it.message }.joinToString()
}

@ -1,6 +1,5 @@
package org.koitharu.kotatsu.core.prefs
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import android.net.ConnectivityManager
@ -14,16 +13,12 @@ import androidx.core.content.edit
import androidx.core.os.LocaleListCompat
import androidx.preference.PreferenceManager
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.json.JSONArray
import org.koitharu.kotatsu.core.model.ZoomMode
import org.koitharu.kotatsu.core.network.DoHProvider
import org.koitharu.kotatsu.core.util.ext.connectivityManager
import org.koitharu.kotatsu.core.util.ext.getEnumValue
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.processLifecycleScope
import org.koitharu.kotatsu.core.util.ext.putEnumValue
import org.koitharu.kotatsu.core.util.ext.takeIfReadable
import org.koitharu.kotatsu.core.util.ext.toUriOrNull

@ -1,100 +0,0 @@
package org.koitharu.kotatsu.core.ui.drawable
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.ColorFilter
import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.os.Build
import android.text.Layout
import android.text.StaticLayout
import android.text.TextPaint
import androidx.annotation.ColorInt
import androidx.annotation.Px
import androidx.annotation.StyleRes
import androidx.core.graphics.withTranslation
import com.google.android.material.resources.TextAppearance
import com.google.android.material.resources.TextAppearanceFontCallback
import org.koitharu.kotatsu.core.util.ext.getThemeColor
class TextDrawable(
val text: CharSequence,
) : Drawable() {
private val paint = TextPaint(Paint.ANTI_ALIAS_FLAG)
private var cachedLayout: StaticLayout? = null
@SuppressLint("RestrictedApi")
constructor(context: Context, text: CharSequence, @StyleRes textAppearanceId: Int) : this(text) {
val ta = TextAppearance(context, textAppearanceId)
paint.color = ta.textColor?.defaultColor ?: context.getThemeColor(android.R.attr.textColorPrimary, Color.BLACK)
paint.typeface = ta.fallbackFont
ta.getFontAsync(
context, paint,
object : TextAppearanceFontCallback() {
override fun onFontRetrieved(typeface: Typeface?, fontResolvedSynchronously: Boolean) = Unit
override fun onFontRetrievalFailed(reason: Int) = Unit
},
)
paint.letterSpacing = ta.letterSpacing
}
var alignment = Layout.Alignment.ALIGN_NORMAL
var lineSpacingMultiplier = 1f
@Px
var lineSpacingExtra = 0f
@get:ColorInt
var textColor: Int
get() = paint.color
set(@ColorInt value) {
paint.color = value
}
override fun draw(canvas: Canvas) {
val b = bounds
if (b.isEmpty) {
return
}
canvas.withTranslation(x = b.left.toFloat(), y = b.top.toFloat()) {
obtainLayout().draw(canvas)
}
}
override fun setAlpha(alpha: Int) {
paint.alpha = alpha
}
override fun setColorFilter(colorFilter: ColorFilter?) {
paint.setColorFilter(colorFilter)
}
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("Deprecated in Java")
override fun getOpacity(): Int = PixelFormat.TRANSLUCENT
private fun obtainLayout(): StaticLayout {
val width = bounds.width()
cachedLayout?.let {
if (it.width == width) {
return it
}
}
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
StaticLayout.Builder.obtain(text, 0, text.length, paint, width)
.setAlignment(alignment)
.setLineSpacing(lineSpacingExtra, lineSpacingMultiplier)
.setIncludePad(true)
.build()
} else {
@Suppress("DEPRECATION")
StaticLayout(text, paint, width, alignment, lineSpacingMultiplier, lineSpacingExtra, true)
}.also { cachedLayout = it }
}
}

@ -1,64 +0,0 @@
package org.koitharu.kotatsu.core.ui.list
import android.os.Bundle
import android.os.Parcelable
import android.util.SparseArray
import androidx.core.os.BundleCompat
import androidx.core.view.doOnNextLayout
import androidx.recyclerview.widget.RecyclerView
import java.util.Collections
import java.util.WeakHashMap
class NestedScrollStateHandle(
savedInstanceState: Bundle?,
private val key: String,
) {
private val storage: SparseArray<Parcelable?> = savedInstanceState?.let {
BundleCompat.getSparseParcelableArray(it, key, Parcelable::class.java)
} ?: SparseArray<Parcelable?>()
private val controllers = Collections.newSetFromMap<Controller>(WeakHashMap())
fun attach(recycler: RecyclerView) = Controller(recycler).also(controllers::add)
fun onSaveInstanceState(outState: Bundle) {
controllers.forEach {
it.saveState()
}
outState.putSparseParcelableArray(key, storage)
}
inner class Controller(
private val recycler: RecyclerView
) {
private var lastPosition: Int = -1
fun onBind(position: Int) {
if (position != lastPosition) {
saveState()
lastPosition = position
storage[position]?.let {
restoreState(it)
}
}
}
fun onRecycled() {
saveState()
lastPosition = -1
}
fun saveState() {
if (lastPosition != -1) {
storage[lastPosition] = recycler.layoutManager?.onSaveInstanceState()
}
}
private fun restoreState(state: Parcelable) {
recycler.doOnNextLayout {
recycler.layoutManager?.onRestoreInstanceState(state)
}
}
}
}

@ -1,237 +1,4 @@
package org.koitharu.kotatsu.core.ui.list
import android.app.Activity
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode
import androidx.collection.ArrayMap
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.RecyclerView
import androidx.savedstate.SavedStateRegistry
import androidx.savedstate.SavedStateRegistryOwner
import kotlinx.coroutines.Dispatchers
import org.koitharu.kotatsu.core.ui.list.decor.AbstractSelectionItemDecoration
import kotlin.coroutines.EmptyCoroutineContext
private const val PROVIDER_NAME = "selection_decoration_sectioned"
class SectionedSelectionController<T : Any>(
private val activity: Activity,
private val owner: SavedStateRegistryOwner,
private val callback: Callback<T>,
) : ActionMode.Callback, SavedStateRegistry.SavedStateProvider {
private var actionMode: ActionMode? = null
private var pendingData: MutableMap<String, Collection<Long>>? = null
private val decorations = ArrayMap<T, AbstractSelectionItemDecoration>()
val count: Int
get() = decorations.values.sumOf { it.checkedItemsCount }
init {
owner.lifecycle.addObserver(StateEventObserver())
}
fun snapshot(): Map<T, Set<Long>> {
return decorations.mapValues { it.value.checkedItemsIds.toSet() }
}
fun peekCheckedIds(): Map<T, Set<Long>> {
return decorations.mapValues { it.value.checkedItemsIds }
}
fun clear() {
decorations.values.forEach {
it.clearSelection()
}
notifySelectionChanged()
}
fun attachToRecyclerView(section: T, recyclerView: RecyclerView) {
val decoration = getDecoration(section)
val pendingIds = pendingData?.remove(section.toString())
if (!pendingIds.isNullOrEmpty()) {
decoration.checkAll(pendingIds)
startActionMode()
notifySelectionChanged()
}
var shouldAddDecoration = true
for (i in (0 until recyclerView.itemDecorationCount).reversed()) {
val decor = recyclerView.getItemDecorationAt(i)
if (decor === decoration) {
shouldAddDecoration = false
break
} else if (decor.javaClass == decoration.javaClass) {
recyclerView.removeItemDecorationAt(i)
}
}
if (shouldAddDecoration) {
recyclerView.addItemDecoration(decoration)
}
if (pendingData?.isEmpty() == true) {
pendingData = null
}
}
override fun saveState(): Bundle {
val bundle = Bundle(decorations.size)
for ((k, v) in decorations) {
bundle.putLongArray(k.toString(), v.checkedItemsIds.toLongArray())
}
return bundle
}
fun onItemClick(section: T, id: Long): Boolean {
val decoration = getDecoration(section)
if (isInSelectionMode()) {
decoration.toggleItemChecked(id)
if (isInSelectionMode()) {
actionMode?.invalidate()
} else {
actionMode?.finish()
}
notifySelectionChanged()
return true
}
return false
}
fun onItemLongClick(section: T, id: Long): Boolean {
val decoration = getDecoration(section)
startActionMode()
return actionMode?.also {
decoration.setItemIsChecked(id, true)
notifySelectionChanged()
} != null
}
fun getSectionCount(section: T): Int {
return decorations[section]?.checkedItemsCount ?: 0
}
fun addToSelection(section: T, ids: Collection<Long>): Boolean {
val decoration = getDecoration(section)
startActionMode()
return actionMode?.also {
decoration.checkAll(ids)
notifySelectionChanged()
} != null
}
fun clearSelection(section: T) {
decorations[section]?.clearSelection() ?: return
notifySelectionChanged()
}
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
return callback.onCreateActionMode(this, mode, menu)
}
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
return callback.onPrepareActionMode(this, mode, menu)
}
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
return callback.onActionItemClicked(this, mode, item)
}
override fun onDestroyActionMode(mode: ActionMode) {
callback.onDestroyActionMode(this, mode)
clear()
actionMode = null
}
private fun startActionMode() {
if (actionMode == null) {
actionMode = (activity as? AppCompatActivity)?.startSupportActionMode(this)
}
}
private fun isInSelectionMode(): Boolean {
return decorations.values.any { x -> x.checkedItemsCount > 0 }
}
private fun notifySelectionChanged() {
val count = this.count
callback.onSelectionChanged(this, count)
if (count == 0) {
actionMode?.finish()
} else {
actionMode?.invalidate()
}
}
private fun restoreState(ids: MutableMap<String, Collection<Long>>) {
if (ids.isEmpty() || isInSelectionMode()) {
return
}
for ((k, v) in decorations) {
val items = ids.remove(k.toString())
if (!items.isNullOrEmpty()) {
v.checkAll(items)
}
}
pendingData = ids
if (isInSelectionMode()) {
startActionMode()
notifySelectionChanged()
}
}
private fun getDecoration(section: T): AbstractSelectionItemDecoration {
return decorations.getOrPut(section) {
callback.onCreateItemDecoration(this, section)
}
}
interface Callback<T : Any> {
fun onSelectionChanged(controller: SectionedSelectionController<T>, count: Int)
fun onCreateActionMode(controller: SectionedSelectionController<T>, mode: ActionMode, menu: Menu): Boolean
fun onPrepareActionMode(controller: SectionedSelectionController<T>, mode: ActionMode, menu: Menu): Boolean {
mode.title = controller.count.toString()
return true
}
fun onDestroyActionMode(controller: SectionedSelectionController<T>, mode: ActionMode) = Unit
fun onActionItemClicked(
controller: SectionedSelectionController<T>,
mode: ActionMode,
item: MenuItem,
): Boolean
fun onCreateItemDecoration(
controller: SectionedSelectionController<T>,
section: T,
): AbstractSelectionItemDecoration
}
private inner class StateEventObserver : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event == Lifecycle.Event.ON_CREATE) {
val registry = owner.savedStateRegistry
registry.registerSavedStateProvider(PROVIDER_NAME, this@SectionedSelectionController)
val state = registry.consumeRestoredStateForKey(PROVIDER_NAME)
if (state != null) {
Dispatchers.Main.dispatch(EmptyCoroutineContext) { // == Handler.post
if (source.lifecycle.currentState.isAtLeast(Lifecycle.State.CREATED)) {
restoreState(
state.keySet()
.associateWithTo(HashMap()) { state.getLongArray(it)?.toList().orEmpty() },
)
}
}
}
}
}
}
}

@ -48,7 +48,7 @@ class ChipsView @JvmOverloads constructor(
if (isInEditMode) {
setChips(
List(5) {
ChipModel(0, "Chip $it", 0, false, false)
ChipModel(0, "Chip $it", 0, isCheckable = false, isChecked = false)
},
)
}

@ -22,7 +22,6 @@ import org.koitharu.kotatsu.core.util.ext.getThemeColorStateList
import org.koitharu.kotatsu.core.util.ext.setTextAndVisible
import org.koitharu.kotatsu.core.util.ext.textAndVisible
import org.koitharu.kotatsu.databinding.ViewTipBinding
import com.google.android.material.R as materialR
class TipView @JvmOverloads constructor(
context: Context,

@ -104,6 +104,7 @@ fun RecyclerView.invalidateNestedItemDecorations() {
val View.parentView: ViewGroup?
get() = parent as? ViewGroup
@Suppress("UnusedReceiverParameter")
fun View.measureDimension(desiredSize: Int, measureSpec: Int): Int {
var result: Int
val specMode = MeasureSpec.getMode(measureSpec)

@ -1,16 +0,0 @@
package org.koitharu.kotatsu.core.util.progress
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
open class ProgressJob<P>(
private val job: Job,
private val progress: StateFlow<P>,
) : Job by job {
val progressValue: P
get() = progress.value
fun progressAsFlow(): Flow<P> = progress
}

@ -19,7 +19,6 @@ import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf
import org.koitharu.kotatsu.databinding.FragmentChaptersBinding
import org.koitharu.kotatsu.details.ui.adapter.ChaptersAdapter
import org.koitharu.kotatsu.details.ui.adapter.ChaptersSelectionDecoration

@ -1,39 +0,0 @@
package org.koitharu.kotatsu.details.ui.adapter
import android.graphics.Color
import android.text.Spannable
import android.text.style.ForegroundColorSpan
import android.text.style.RelativeSizeSpan
import androidx.core.text.buildSpannedString
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.getThemeColor
import org.koitharu.kotatsu.databinding.ItemCheckableNewBinding
import org.koitharu.kotatsu.details.ui.model.MangaBranch
fun branchAD(
clickListener: OnListItemClickListener<MangaBranch>,
) = adapterDelegateViewBinding<MangaBranch, MangaBranch, ItemCheckableNewBinding>(
{ inflater, parent -> ItemCheckableNewBinding.inflate(inflater, parent, false) },
) {
val clickAdapter = AdapterDelegateClickListenerAdapter(this, clickListener)
itemView.setOnClickListener(clickAdapter)
val counterColorSpan = ForegroundColorSpan(context.getThemeColor(android.R.attr.textColorSecondary, Color.LTGRAY))
val counterSizeSpan = RelativeSizeSpan(0.86f)
bind {
binding.root.text = buildSpannedString {
append(item.name ?: getString(R.string.system_default))
append(' ')
append(' ')
val start = length
append(item.count.toString())
setSpan(counterColorSpan, start, length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
setSpan(counterSizeSpan, start, length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
binding.root.isChecked = item.isSelected
}
}

@ -6,7 +6,6 @@ import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.drawableEnd
import org.koitharu.kotatsu.core.util.ext.drawableStart
import org.koitharu.kotatsu.core.util.ext.getThemeColor
import org.koitharu.kotatsu.core.util.ext.textAndVisible

@ -9,12 +9,10 @@ import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.TextView
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.viewModels
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.lifecycle.withCreationCallback
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetBehavior
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetCallback

@ -8,7 +8,6 @@ import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.db.entity.toEntities
import org.koitharu.kotatsu.core.db.entity.toEntity
import org.koitharu.kotatsu.core.db.entity.toManga
import org.koitharu.kotatsu.core.db.entity.toMangaTag

@ -47,7 +47,7 @@ import javax.inject.Inject
@HiltViewModel
class HistoryListViewModel @Inject constructor(
private val repository: HistoryRepository,
private val settings: AppSettings,
settings: AppSettings,
private val extraProvider: ListExtraProvider,
private val localMangaRepository: LocalMangaRepository,
networkState: NetworkState,

@ -17,6 +17,7 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.plus
import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
import org.koitharu.kotatsu.core.os.NetworkState
@ -158,7 +159,9 @@ class PageHolderDelegate(
callback.onLoadingStarted()
yield()
try {
val task = loader.loadPageAsync(data, force)
val task = withContext(Dispatchers.Default) {
loader.loadPageAsync(data, force)
}
uri = coroutineScope {
val progressObserver = observeProgress(this, task.progressAsFlow())
val file = task.await()

@ -1,29 +0,0 @@
package org.koitharu.kotatsu.reader.ui.pager.standard
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import org.koitharu.kotatsu.reader.ui.pager.OnBoundsScrollListener
class PagerPaginationListener(
private val adapter: RecyclerView.Adapter<*>,
private val offset: Int,
private val listener: OnBoundsScrollListener
) : ViewPager2.OnPageChangeCallback() {
private var firstItemId: Long = 0
private var lastItemId: Long = 0
override fun onPageSelected(position: Int) {
val itemCount = adapter.itemCount
if (itemCount == 0) {
return
}
if (position <= offset && adapter.getItemId(0) != firstItemId) {
firstItemId = adapter.getItemId(0)
listener.onScrolledToStart()
} else if (position >= itemCount - offset && adapter.getItemId(itemCount - 1) != lastItemId) {
lastItemId = adapter.getItemId(itemCount - 1)
listener.onScrolledToEnd()
}
}
}

@ -1,32 +0,0 @@
package org.koitharu.kotatsu.reader.ui.pager.webtoon
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import org.koitharu.kotatsu.reader.ui.pager.OnBoundsScrollListener
class ListPaginationListener(
private val offset: Int,
private val listener: OnBoundsScrollListener
) : RecyclerView.OnScrollListener() {
private var firstItemId: Long = 0
private var lastItemId: Long = 0
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
val adapter = recyclerView.adapter ?: return
val layoutManager = (recyclerView.layoutManager as? LinearLayoutManager) ?: return
val firstVisiblePosition = layoutManager.findFirstVisibleItemPosition()
val lastVisiblePosition = layoutManager.findLastVisibleItemPosition()
val itemCount = adapter.itemCount
if (itemCount == 0) {
return
}
if (lastVisiblePosition >= itemCount - offset && adapter.getItemId(itemCount - 1) != lastItemId) {
lastItemId = adapter.getItemId(itemCount - 1)
listener.onScrolledToEnd()
} else if (firstVisiblePosition <= offset && adapter.getItemId(0) != firstItemId) {
firstItemId = adapter.getItemId(0)
listener.onScrolledToStart()
}
}
}

@ -1,41 +0,0 @@
package org.koitharu.kotatsu.reader.ui.thumbnails.adapter
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter
import org.koitharu.kotatsu.reader.ui.thumbnails.PageThumbnail
class TargetScrollObserver(
private val recyclerView: RecyclerView,
) : RecyclerView.AdapterDataObserver() {
private var isScrollToCurrentPending = true
private val layoutManager: LinearLayoutManager
get() = recyclerView.layoutManager as LinearLayoutManager
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
if (isScrollToCurrentPending) {
postScroll()
}
}
private fun postScroll() {
recyclerView.post {
scrollToTarget()
}
}
private fun scrollToTarget() {
val adapter = recyclerView.adapter ?: return
if (recyclerView.computeVerticalScrollRange() == 0) {
return
}
val snapshot = (adapter as? AsyncListDifferDelegationAdapter<*>)?.items ?: return
val target = snapshot.indexOfFirst { it is PageThumbnail && it.isCurrent }
if (target in snapshot.indices) {
layoutManager.scrollToPositionWithOffset(target, 0)
isScrollToCurrentPending = false
}
}
}

@ -5,7 +5,6 @@ import okhttp3.Authenticator
import okhttp3.Request
import okhttp3.Response
import okhttp3.Route
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.network.CommonHeaders
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
import org.koitharu.kotatsu.scrobbling.common.data.ScrobblerStorage

@ -118,7 +118,7 @@ class ScrobblingSelectorViewModel @Inject constructor(
if (!append) {
scrobblerMangaList.value = list
} else if (list.isNotEmpty()) {
scrobblerMangaList.value = scrobblerMangaList.value + list
scrobblerMangaList.value += list
}
hasNextPage.value = list.isNotEmpty()
}.onFailure { error ->

@ -5,7 +5,6 @@ import okhttp3.Authenticator
import okhttp3.Request
import okhttp3.Response
import okhttp3.Route
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.network.CommonHeaders
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
import org.koitharu.kotatsu.scrobbling.common.data.ScrobblerStorage

@ -5,7 +5,6 @@ import okhttp3.Authenticator
import okhttp3.Request
import okhttp3.Response
import okhttp3.Route
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.network.CommonHeaders
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
import org.koitharu.kotatsu.scrobbling.common.data.ScrobblerStorage

@ -95,7 +95,7 @@ class MultiSearchViewModel @Inject constructor(
}
fun retry() {
retryCounter.value = retryCounter.value + 1
retryCounter.value += 1
}
fun download(items: Set<Manga>) {

@ -1,53 +0,0 @@
package org.koitharu.kotatsu.search.ui.widget
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.LinearLayout
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.ViewCompat
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.bottomnavigation.BottomNavigationView
class SearchBehavior(context: Context?, attrs: AttributeSet?) :
CoordinatorLayout.Behavior<SearchToolbar>(context, attrs) {
override fun layoutDependsOn(
parent: CoordinatorLayout,
child: SearchToolbar,
dependency: View,
): Boolean {
return when (dependency) {
is AppBarLayout -> true
is LinearLayout, is BottomNavigationView -> {
dependency.z = child.z + 1
true
}
else -> super.layoutDependsOn(parent, child, dependency)
}
}
override fun onDependentViewChanged(
parent: CoordinatorLayout,
child: SearchToolbar,
dependency: View,
): Boolean {
if (dependency is AppBarLayout) {
child.translationY = dependency.getY()
return true
}
return super.onDependentViewChanged(parent, child, dependency)
}
override fun onStartNestedScroll(
coordinatorLayout: CoordinatorLayout,
child: SearchToolbar,
directTargetChild: View,
target: View,
axes: Int,
type: Int,
): Boolean {
return axes == ViewCompat.SCROLL_AXIS_VERTICAL
}
}

@ -12,11 +12,9 @@ import javax.inject.Inject
@HiltViewModel
class SourcesSettingsViewModel @Inject constructor(
private val sourcesRepository: MangaSourcesRepository,
sourcesRepository: MangaSourcesRepository,
) : BaseViewModel() {
val totalSourcesCount = sourcesRepository.allMangaSources.size
val enabledSourcesCount = sourcesRepository.observeEnabledSourcesCount()
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, -1)

@ -1,18 +0,0 @@
package org.koitharu.kotatsu.settings.utils
import androidx.annotation.StringRes
import androidx.preference.EditTextPreference
import androidx.preference.Preference
class EditTextSummaryProvider(@StringRes private val emptySummaryId: Int) :
Preference.SummaryProvider<EditTextPreference> {
override fun provideSummary(preference: EditTextPreference): CharSequence {
val text = preference.text
return if (text.isNullOrEmpty()) {
preference.context.getString(emptySummaryId)
} else {
text
}
}
}

@ -25,7 +25,7 @@ import javax.inject.Inject
@HiltViewModel
class UpdatesViewModel @Inject constructor(
private val repository: TrackingRepository,
private val settings: AppSettings,
settings: AppSettings,
private val extraProvider: ListExtraProvider,
downloadScheduler: DownloadWorker.Scheduler,
) : MangaListViewModel(settings, downloadScheduler) {

@ -15,8 +15,7 @@
app:elevation="1dp"
app:headerLayout="@layout/navigation_rail_fab"
app:labelVisibilityMode="labeled"
app:layout_constraintStart_toStartOf="parent"
tools:menu="@menu/nav_bottom" />
app:layout_constraintStart_toStartOf="parent" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"

@ -93,7 +93,6 @@
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:clickable="true"
tools:ignore="KeyboardInaccessibleWidget"
tools:menu="@menu/nav_bottom" />
tools:ignore="KeyboardInaccessibleWidget" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

@ -27,6 +27,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/settings"
android:padding="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"

@ -13,6 +13,7 @@
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center_horizontal"
android:contentDescription="@null"
app:tint="?colorPrimary"
tools:src="@drawable/ic_notification" />

Loading…
Cancel
Save