Fix some warnings and remove unused code
parent
0d62408918
commit
b2e53d4938
@ -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,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,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
|
|
||||||
}
|
|
||||||
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue