Improve drawable and views state management

master
Koitharu 1 year ago
parent 14973298a0
commit dc2e603356
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -14,7 +14,6 @@ import com.google.android.material.animation.ArgbEvaluatorCompat
import com.google.android.material.color.MaterialColors import com.google.android.material.color.MaterialColors
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.getTitle import org.koitharu.kotatsu.core.model.getTitle
import org.koitharu.kotatsu.core.util.KotatsuColors
import org.koitharu.kotatsu.core.util.ext.getAnimationDuration import org.koitharu.kotatsu.core.util.ext.getAnimationDuration
import org.koitharu.kotatsu.core.util.ext.mangaSourceKey import org.koitharu.kotatsu.core.util.ext.mangaSourceKey
import kotlin.math.abs import kotlin.math.abs
@ -29,8 +28,8 @@ class AnimatedFaviconDrawable(
private val period = context.getAnimationDuration(R.integer.config_longAnimTime) * 2 private val period = context.getAnimationDuration(R.integer.config_longAnimTime) * 2
private val timeAnimator = TimeAnimator() private val timeAnimator = TimeAnimator()
private val colorHigh = MaterialColors.harmonize(KotatsuColors.random(name), colorBackground) private var colorHigh = MaterialColors.harmonize(colorForeground, currentBackgroundColor)
private val colorLow = ArgbEvaluatorCompat.getInstance().evaluate(0.3f, colorHigh, colorBackground) private var colorLow = ArgbEvaluatorCompat.getInstance().evaluate(0.3f, colorHigh, currentBackgroundColor)
init { init {
timeAnimator.setTimeListener(this) timeAnimator.setTimeListener(this)
@ -49,6 +48,8 @@ class AnimatedFaviconDrawable(
override fun getAlpha(): Int = 255 override fun getAlpha(): Int = 255
override fun isOpaque(): Boolean = false
override fun onTimeUpdate(animation: TimeAnimator?, totalTime: Long, deltaTime: Long) { override fun onTimeUpdate(animation: TimeAnimator?, totalTime: Long, deltaTime: Long) {
callback?.also { callback?.also {
updateColor() updateColor()
@ -66,13 +67,21 @@ class AnimatedFaviconDrawable(
override fun isRunning(): Boolean = timeAnimator.isStarted override fun isRunning(): Boolean = timeAnimator.isStarted
override fun onStateChange(state: IntArray): Boolean {
val res = super.onStateChange(state)
colorHigh = MaterialColors.harmonize(currentForegroundColor, currentBackgroundColor)
colorLow = ArgbEvaluatorCompat.getInstance().evaluate(0.3f, colorHigh, currentBackgroundColor)
updateColor()
return res
}
private fun updateColor() { private fun updateColor() {
if (period <= 0f) { if (period <= 0f) {
return return
} }
val ph = period / 2 val ph = period / 2
val fraction = abs((System.currentTimeMillis() % period) - ph) / ph.toFloat() val fraction = abs((System.currentTimeMillis() % period) - ph) / ph.toFloat()
colorForeground = ArgbEvaluatorCompat.getInstance() currentForegroundColor = ArgbEvaluatorCompat.getInstance()
.evaluate(interpolator.getInterpolation(fraction), colorLow, colorHigh) .evaluate(interpolator.getInterpolation(fraction), colorLow, colorHigh)
} }

@ -41,14 +41,14 @@ class AnimatedPlaceholderDrawable(context: Context) : Drawable(), Animatable, Ti
// this.alpha = alpha FIXME coil's crossfade // this.alpha = alpha FIXME coil's crossfade
} }
override fun setColorFilter(colorFilter: ColorFilter?) = Unit
@Suppress("DeprecatedCallableAddReplaceWith") @Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("Deprecated in Java") @Deprecated("Deprecated in Java")
override fun getOpacity(): Int = PixelFormat.OPAQUE override fun getOpacity(): Int = PixelFormat.TRANSLUCENT
override fun getAlpha(): Int = 255 override fun getAlpha(): Int = 255
override fun setColorFilter(colorFilter: ColorFilter?) = Unit
override fun onTimeUpdate(animation: TimeAnimator?, totalTime: Long, deltaTime: Long) { override fun onTimeUpdate(animation: TimeAnimator?, totalTime: Long, deltaTime: Long) {
callback?.also { callback?.also {
updateColor() updateColor()

@ -1,15 +1,15 @@
package org.koitharu.kotatsu.core.ui.image package org.koitharu.kotatsu.core.ui.image
import android.content.Context import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Color import android.graphics.Color
import android.graphics.ColorFilter
import android.graphics.Paint import android.graphics.Paint
import android.graphics.Path import android.graphics.Path
import android.graphics.PixelFormat
import android.graphics.Rect import android.graphics.Rect
import android.graphics.RectF import android.graphics.RectF
import android.graphics.drawable.Drawable import android.os.Build
import androidx.annotation.RequiresApi
import androidx.annotation.StyleRes import androidx.annotation.StyleRes
import androidx.core.content.withStyledAttributes import androidx.core.content.withStyledAttributes
import androidx.core.graphics.withClip import androidx.core.graphics.withClip
@ -21,18 +21,24 @@ import com.google.android.material.color.MaterialColors
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.getTitle import org.koitharu.kotatsu.core.model.getTitle
import org.koitharu.kotatsu.core.util.KotatsuColors import org.koitharu.kotatsu.core.util.KotatsuColors
import org.koitharu.kotatsu.core.util.ext.hasFocusStateSpecified
import org.koitharu.kotatsu.core.util.ext.mangaSourceKey import org.koitharu.kotatsu.core.util.ext.mangaSourceKey
open class FaviconDrawable( open class FaviconDrawable(
context: Context, context: Context,
@StyleRes styleResId: Int, @StyleRes styleResId: Int,
name: String, name: String,
) : Drawable() { ) : PaintDrawable() {
private val paint = Paint(Paint.ANTI_ALIAS_FLAG) override val paint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.SUBPIXEL_TEXT_FLAG)
protected var colorBackground = Color.WHITE protected var currentBackgroundColor = Color.WHITE
private set
private var colorBackground: ColorStateList = ColorStateList.valueOf(currentBackgroundColor)
protected var colorForeground = Color.DKGRAY protected var colorForeground = Color.DKGRAY
private var colorStroke = Color.LTGRAY protected var currentForegroundColor = Color.DKGRAY
protected var currentStrokeColor = Color.LTGRAY
private set
private var colorStroke: ColorStateList = ColorStateList.valueOf(currentStrokeColor)
private val letter = name.take(1).uppercase() private val letter = name.take(1).uppercase()
private var cornerSize = 0f private var cornerSize = 0f
private var intrinsicSize = -1 private var intrinsicSize = -1
@ -43,15 +49,16 @@ open class FaviconDrawable(
init { init {
context.withStyledAttributes(styleResId, R.styleable.FaviconFallbackDrawable) { context.withStyledAttributes(styleResId, R.styleable.FaviconFallbackDrawable) {
colorBackground = getColor(R.styleable.FaviconFallbackDrawable_backgroundColor, colorBackground) colorBackground = getColorStateList(R.styleable.FaviconFallbackDrawable_backgroundColor) ?: colorBackground
colorStroke = getColor(R.styleable.FaviconFallbackDrawable_strokeColor, colorStroke) colorStroke = getColorStateList(R.styleable.FaviconFallbackDrawable_strokeColor) ?: colorStroke
cornerSize = getDimension(R.styleable.FaviconFallbackDrawable_cornerSize, cornerSize) cornerSize = getDimension(R.styleable.FaviconFallbackDrawable_cornerSize, cornerSize)
paint.strokeWidth = getDimension(R.styleable.FaviconFallbackDrawable_strokeWidth, 0f) * 2f paint.strokeWidth = getDimension(R.styleable.FaviconFallbackDrawable_strokeWidth, 0f) * 2f
intrinsicSize = getDimensionPixelSize(R.styleable.FaviconFallbackDrawable_drawableSize, intrinsicSize) intrinsicSize = getDimensionPixelSize(R.styleable.FaviconFallbackDrawable_drawableSize, intrinsicSize)
} }
paint.textAlign = Paint.Align.CENTER paint.textAlign = Paint.Align.CENTER
paint.isFakeBoldText = true paint.isFakeBoldText = true
colorForeground = MaterialColors.harmonize(KotatsuColors.random(name), colorBackground) colorForeground = KotatsuColors.random(name)
currentForegroundColor = MaterialColors.harmonize(colorForeground, colorBackground.defaultColor)
} }
override fun draw(canvas: Canvas) { override fun draw(canvas: Canvas) {
@ -75,35 +82,42 @@ open class FaviconDrawable(
clipPath.close() clipPath.close()
} }
override fun setAlpha(alpha: Int) {
paint.alpha = alpha
}
override fun setColorFilter(colorFilter: ColorFilter?) {
paint.colorFilter = colorFilter
}
override fun getIntrinsicWidth(): Int = intrinsicSize override fun getIntrinsicWidth(): Int = intrinsicSize
override fun getIntrinsicHeight(): Int = intrinsicSize override fun getIntrinsicHeight(): Int = intrinsicSize
@Suppress("DeprecatedCallableAddReplaceWith") override fun isOpaque(): Boolean = cornerSize == 0f && colorBackground.isOpaque
@Deprecated("Deprecated in Java")
override fun getOpacity() = PixelFormat.TRANSPARENT override fun isStateful(): Boolean = colorStroke.isStateful || colorBackground.isStateful
@RequiresApi(Build.VERSION_CODES.S)
override fun hasFocusStateSpecified(): Boolean =
colorBackground.hasFocusStateSpecified() || colorStroke.hasFocusStateSpecified()
override fun onStateChange(state: IntArray): Boolean {
val prevStrokeColor = currentStrokeColor
val prevBackgroundColor = currentBackgroundColor
currentStrokeColor = colorStroke.getColorForState(state, colorStroke.defaultColor)
currentBackgroundColor = colorBackground.getColorForState(state, colorBackground.defaultColor)
if (currentBackgroundColor != prevBackgroundColor) {
currentForegroundColor = MaterialColors.harmonize(colorForeground, currentBackgroundColor)
}
return prevBackgroundColor != currentBackgroundColor || prevStrokeColor != currentStrokeColor
}
private fun doDraw(canvas: Canvas) { private fun doDraw(canvas: Canvas) {
// background // background
paint.color = colorBackground paint.color = currentBackgroundColor
paint.style = Paint.Style.FILL paint.style = Paint.Style.FILL
canvas.drawPaint(paint) canvas.drawPaint(paint)
// letter // letter
paint.color = colorForeground paint.color = currentForegroundColor
val cx = (boundsF.left + boundsF.right) * 0.6f val cx = (boundsF.left + boundsF.right) * 0.6f
val ty = boundsF.bottom * 0.7f + textBounds.height() * 0.5f - textBounds.bottom val ty = boundsF.bottom * 0.7f + textBounds.height() * 0.5f - textBounds.bottom
canvas.drawText(letter, cx, ty, paint) canvas.drawText(letter, cx, ty, paint)
if (paint.strokeWidth > 0f) { if (paint.strokeWidth > 0f) {
// stroke // stroke
paint.color = colorStroke paint.color = currentStrokeColor
paint.style = Paint.Style.STROKE paint.style = Paint.Style.STROKE
canvas.drawPath(clipPath, paint) canvas.drawPath(clipPath, paint)
} }

@ -0,0 +1,53 @@
package org.koitharu.kotatsu.core.ui.image
import android.graphics.ColorFilter
import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.drawable.Drawable
@Suppress("OVERRIDE_DEPRECATION")
abstract class PaintDrawable : Drawable() {
protected abstract val paint: Paint
override fun setAlpha(alpha: Int) {
paint.alpha = alpha
}
override fun getAlpha(): Int {
return paint.alpha
}
override fun setColorFilter(colorFilter: ColorFilter?) {
paint.colorFilter = colorFilter
}
override fun getColorFilter(): ColorFilter? {
return paint.colorFilter
}
override fun setDither(dither: Boolean) {
paint.isDither = dither
}
override fun setFilterBitmap(filter: Boolean) {
paint.isFilterBitmap = filter
}
override fun isFilterBitmap(): Boolean {
return paint.isFilterBitmap
}
override fun getOpacity(): Int {
if (paint.colorFilter != null) {
return PixelFormat.TRANSLUCENT
}
return when (paint.alpha) {
0 -> PixelFormat.TRANSPARENT
255 -> if (isOpaque()) PixelFormat.OPAQUE else PixelFormat.TRANSLUCENT
else -> PixelFormat.TRANSLUCENT
}
}
protected open fun isOpaque() = false
}

@ -3,20 +3,20 @@ package org.koitharu.kotatsu.core.ui.image
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Color import android.graphics.Color
import android.graphics.ColorFilter
import android.graphics.Paint import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.PointF import android.graphics.PointF
import android.graphics.Rect import android.graphics.Rect
import android.graphics.drawable.Drawable import android.os.Build
import android.widget.TextView import android.widget.TextView
import androidx.annotation.RequiresApi
import androidx.core.graphics.PaintCompat import androidx.core.graphics.PaintCompat
import org.koitharu.kotatsu.core.util.ext.hasFocusStateSpecified
class TextDrawable( class TextDrawable(
val text: String, val text: String,
) : Drawable() { ) : PaintDrawable() {
private val paint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.SUBPIXEL_TEXT_FLAG) override val paint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.SUBPIXEL_TEXT_FLAG)
private val textBounds = Rect() private val textBounds = Rect()
private val textPoint = PointF() private val textPoint = PointF()
@ -41,20 +41,6 @@ class TextDrawable(
canvas.drawText(text, textPoint.x, textPoint.y, paint) canvas.drawText(text, textPoint.x, textPoint.y, paint)
} }
override fun setAlpha(alpha: Int) {
paint.alpha = alpha
}
override fun setColorFilter(colorFilter: ColorFilter?) {
paint.setColorFilter(colorFilter)
}
override fun getOpacity(): Int = when (paint.alpha) {
0 -> PixelFormat.TRANSPARENT
255 -> PixelFormat.OPAQUE
else -> PixelFormat.TRANSLUCENT
}
override fun onBoundsChange(bounds: Rect) { override fun onBoundsChange(bounds: Rect) {
textPoint.set( textPoint.set(
bounds.exactCenterX() - textBounds.exactCenterX(), bounds.exactCenterX() - textBounds.exactCenterX(),
@ -66,16 +52,10 @@ class TextDrawable(
override fun getIntrinsicHeight(): Int = textBounds.height() override fun getIntrinsicHeight(): Int = textBounds.height()
override fun setDither(dither: Boolean) {
paint.isDither = dither
}
override fun isStateful(): Boolean = textColor.isStateful override fun isStateful(): Boolean = textColor.isStateful
override fun hasFocusStateSpecified(): Boolean = textColor.getColorForState( @RequiresApi(Build.VERSION_CODES.S)
intArrayOf(android.R.attr.state_focused), override fun hasFocusStateSpecified(): Boolean = textColor.hasFocusStateSpecified()
textColor.defaultColor,
) != textColor.defaultColor
override fun onStateChange(state: IntArray): Boolean { override fun onStateChange(state: IntArray): Boolean {
val prevColor = paint.color val prevColor = paint.color

@ -1,6 +1,7 @@
package org.koitharu.kotatsu.core.ui.widgets package org.koitharu.kotatsu.core.ui.widgets
import android.content.Context import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Color import android.graphics.Color
import android.graphics.Paint import android.graphics.Paint
@ -11,7 +12,7 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver
import androidx.viewpager2.widget.ViewPager2 import androidx.viewpager2.widget.ViewPager2
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.getThemeColor import org.koitharu.kotatsu.core.util.ext.getThemeColorStateList
import org.koitharu.kotatsu.core.util.ext.measureDimension import org.koitharu.kotatsu.core.util.ext.measureDimension
import org.koitharu.kotatsu.core.util.ext.resolveDp import org.koitharu.kotatsu.core.util.ext.resolveDp
import org.koitharu.kotatsu.parsers.util.toIntUp import org.koitharu.kotatsu.parsers.util.toIntUp
@ -30,6 +31,7 @@ class DotsIndicator @JvmOverloads constructor(
private var smallDotAlpha = 0.6f private var smallDotAlpha = 0.6f
private var positionOffset: Float = 0f private var positionOffset: Float = 0f
private var position: Int = 0 private var position: Int = 0
private var dotsColor: ColorStateList = ColorStateList.valueOf(Color.DKGRAY)
private val inset = context.resources.resolveDp(1f) private val inset = context.resources.resolveDp(1f)
var max: Int = 6 var max: Int = 6
@ -52,10 +54,10 @@ class DotsIndicator @JvmOverloads constructor(
init { init {
paint.style = Paint.Style.FILL paint.style = Paint.Style.FILL
context.withStyledAttributes(attrs, R.styleable.DotsIndicator, defStyleAttr) { context.withStyledAttributes(attrs, R.styleable.DotsIndicator, defStyleAttr) {
paint.color = getColor( dotsColor = getColorStateList(R.styleable.DotsIndicator_dotColor)
R.styleable.DotsIndicator_dotColor, ?: context.getThemeColorStateList(materialR.attr.colorOnBackground)
context.getThemeColor(materialR.attr.colorOnBackground, Color.DKGRAY), ?: dotsColor
) paint.color = dotsColor.defaultColor
indicatorSize = getDimension(R.styleable.DotsIndicator_dotSize, indicatorSize) indicatorSize = getDimension(R.styleable.DotsIndicator_dotSize, indicatorSize)
dotSpacing = getDimension(R.styleable.DotsIndicator_dotSpacing, dotSpacing) dotSpacing = getDimension(R.styleable.DotsIndicator_dotSpacing, dotSpacing)
smallDotScale = getFloat(R.styleable.DotsIndicator_dotScale, smallDotScale).coerceIn(0f, 1f) smallDotScale = getFloat(R.styleable.DotsIndicator_dotScale, smallDotScale).coerceIn(0f, 1f)
@ -89,6 +91,13 @@ class DotsIndicator @JvmOverloads constructor(
} }
} }
override fun drawableStateChanged() {
if (dotsColor.isStateful) {
paint.color = dotsColor.getColorForState(drawableState, dotsColor.defaultColor)
}
super.drawableStateChanged()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val dotSize = getDotSize() val dotSize = getDotSize()
val desiredHeight = (dotSize + paddingTop + paddingBottom).toIntUp() val desiredHeight = (dotSize + paddingTop + paddingBottom).toIntUp()

@ -28,6 +28,7 @@ import org.koitharu.kotatsu.core.util.ext.setTextAndVisible
import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.core.util.ext.textAndVisible
import com.google.android.material.R as materialR import com.google.android.material.R as materialR
@Deprecated("")
class ProgressButton @JvmOverloads constructor( class ProgressButton @JvmOverloads constructor(
context: Context, context: Context,
attrs: AttributeSet? = null, attrs: AttributeSet? = null,

@ -2,13 +2,13 @@ package org.koitharu.kotatsu.core.util
import android.content.Context import android.content.Context
import android.text.Editable import android.text.Editable
import android.text.TextWatcher
import android.widget.EditText import android.widget.EditText
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
abstract class EditTextValidator : TextWatcher { abstract class EditTextValidator : DefaultTextWatcher {
private var editTextRef: WeakReference<EditText>? = null private var editTextRef: WeakReference<EditText>? = null
@ -17,10 +17,6 @@ abstract class EditTextValidator : TextWatcher {
"EditTextValidator is not attached to EditText" "EditTextValidator is not attached to EditText"
} }
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit
@CallSuper @CallSuper
override fun afterTextChanged(s: Editable?) { override fun afterTextChanged(s: Editable?) {
val editText = editTextRef?.get() ?: return val editText = editTextRef?.get() ?: return

@ -1,5 +1,6 @@
package org.koitharu.kotatsu.core.util.ext package org.koitharu.kotatsu.core.util.ext
import android.content.res.ColorStateList
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Rect import android.graphics.Rect
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -18,3 +19,7 @@ inline fun <R> Bitmap.use(block: (Bitmap) -> R) = try {
} finally { } finally {
recycle() recycle()
} }
fun ColorStateList.hasFocusStateSpecified(): Boolean {
return getColorForState(intArrayOf(android.R.attr.state_focused), defaultColor) != defaultColor
}

@ -2,7 +2,6 @@ package org.koitharu.kotatsu.filter.ui.tags
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.TextWatcher
import android.view.KeyEvent import android.view.KeyEvent
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -17,14 +16,19 @@ import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetBehavior import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetBehavior
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetCallback import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetCallback
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.databinding.SheetTagsBinding import org.koitharu.kotatsu.databinding.SheetTagsBinding
import org.koitharu.kotatsu.filter.ui.FilterCoordinator import org.koitharu.kotatsu.filter.ui.FilterCoordinator
import org.koitharu.kotatsu.filter.ui.model.TagCatalogItem import org.koitharu.kotatsu.filter.ui.model.TagCatalogItem
@AndroidEntryPoint @AndroidEntryPoint
class TagsCatalogSheet : BaseAdaptiveSheet<SheetTagsBinding>(), OnListItemClickListener<TagCatalogItem>, TextWatcher, class TagsCatalogSheet : BaseAdaptiveSheet<SheetTagsBinding>(),
AdaptiveSheetCallback, View.OnFocusChangeListener, TextView.OnEditorActionListener { OnListItemClickListener<TagCatalogItem>,
DefaultTextWatcher,
AdaptiveSheetCallback,
View.OnFocusChangeListener,
TextView.OnEditorActionListener {
private val viewModel by viewModels<TagsCatalogViewModel>( private val viewModel by viewModels<TagsCatalogViewModel>(
extrasProducer = { extrasProducer = {
@ -75,10 +79,6 @@ class TagsCatalogSheet : BaseAdaptiveSheet<SheetTagsBinding>(), OnListItemClickL
} }
} }
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit
override fun afterTextChanged(s: Editable?) { override fun afterTextChanged(s: Editable?) {
val q = s?.toString().orEmpty() val q = s?.toString().orEmpty()
viewModel.searchQuery.value = q viewModel.searchQuery.value = q

@ -1,17 +1,18 @@
package org.koitharu.kotatsu.history.ui.util package org.koitharu.kotatsu.history.ui.util
import android.content.Context import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Color import android.graphics.Color
import android.graphics.ColorFilter
import android.graphics.Paint import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.Rect import android.graphics.Rect
import android.graphics.drawable.Drawable import android.os.Build
import androidx.annotation.RequiresApi
import androidx.annotation.StyleRes import androidx.annotation.StyleRes
import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.content.res.AppCompatResources
import androidx.core.graphics.ColorUtils
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.image.PaintDrawable
import org.koitharu.kotatsu.core.util.ext.hasFocusStateSpecified
import org.koitharu.kotatsu.core.util.ext.scale import org.koitharu.kotatsu.core.util.ext.scale
import org.koitharu.kotatsu.list.domain.ReadingProgress import org.koitharu.kotatsu.list.domain.ReadingProgress
import org.koitharu.kotatsu.list.domain.ReadingProgress.Companion.PROGRESS_NONE import org.koitharu.kotatsu.list.domain.ReadingProgress.Companion.PROGRESS_NONE
@ -19,23 +20,29 @@ import org.koitharu.kotatsu.list.domain.ReadingProgress.Companion.PROGRESS_NONE
class ReadingProgressDrawable( class ReadingProgressDrawable(
context: Context, context: Context,
@StyleRes styleResId: Int, @StyleRes styleResId: Int,
) : Drawable() { ) : PaintDrawable() {
private val paint = Paint(Paint.ANTI_ALIAS_FLAG) override val paint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.SUBPIXEL_TEXT_FLAG)
private val checkDrawable = AppCompatResources.getDrawable(context, R.drawable.ic_check) private val checkDrawable = AppCompatResources.getDrawable(context, R.drawable.ic_check)
private val lineColor: Int private val lineColor: ColorStateList
private val outlineColor: Int private val outlineColor: ColorStateList
private val backgroundColor: Int private val backgroundColor: ColorStateList
private val textColor: Int private val textColor: ColorStateList
private val textBounds = Rect() private val textBounds = Rect()
private val tempRect = Rect() private val tempRect = Rect()
private val hasBackground: Boolean
private val hasOutline: Boolean
private val hasText: Boolean
private val desiredHeight: Int private val desiredHeight: Int
private val desiredWidth: Int private val desiredWidth: Int
private val autoFitTextSize: Boolean private val autoFitTextSize: Boolean
private var currentLineColor: Int = Color.TRANSPARENT
private var currentOutlineColor: Int = Color.TRANSPARENT
private var currentBackgroundColor: Int = Color.TRANSPARENT
private var currentTextColor: Int = Color.TRANSPARENT
private var hasBackground: Boolean = false
private var hasOutline: Boolean = false
private var hasText: Boolean = false
var percent: Float = PROGRESS_NONE var percent: Float = PROGRESS_NONE
set(value) { set(value) {
field = value field = value
@ -54,22 +61,21 @@ class ReadingProgressDrawable(
desiredHeight = ta.getDimensionPixelSize(R.styleable.ProgressDrawable_android_height, -1) desiredHeight = ta.getDimensionPixelSize(R.styleable.ProgressDrawable_android_height, -1)
desiredWidth = ta.getDimensionPixelSize(R.styleable.ProgressDrawable_android_width, -1) desiredWidth = ta.getDimensionPixelSize(R.styleable.ProgressDrawable_android_width, -1)
autoFitTextSize = ta.getBoolean(R.styleable.ProgressDrawable_autoFitTextSize, false) autoFitTextSize = ta.getBoolean(R.styleable.ProgressDrawable_autoFitTextSize, false)
lineColor = ta.getColor(R.styleable.ProgressDrawable_android_strokeColor, Color.BLACK) lineColor = ta.getColorStateList(R.styleable.ProgressDrawable_android_strokeColor) ?: ColorStateList.valueOf(
outlineColor = ta.getColor(R.styleable.ProgressDrawable_outlineColor, Color.TRANSPARENT) Color.BLACK,
backgroundColor = ColorUtils.setAlphaComponent(
ta.getColor(R.styleable.ProgressDrawable_android_fillColor, Color.TRANSPARENT),
(255 * ta.getFloat(R.styleable.ProgressDrawable_android_fillAlpha, 0f)).toInt(),
) )
textColor = ta.getColor(R.styleable.ProgressDrawable_android_textColor, lineColor) outlineColor =
ta.getColorStateList(R.styleable.ProgressDrawable_outlineColor) ?: ColorStateList.valueOf(Color.TRANSPARENT)
backgroundColor = ta.getColorStateList(R.styleable.ProgressDrawable_android_fillColor)?.withAlpha(
(255 * ta.getFloat(R.styleable.ProgressDrawable_android_fillAlpha, 0f)).toInt(),
) ?: ColorStateList.valueOf(Color.TRANSPARENT)
textColor = ta.getColorStateList(R.styleable.ProgressDrawable_android_textColor) ?: lineColor
paint.strokeCap = Paint.Cap.ROUND paint.strokeCap = Paint.Cap.ROUND
paint.textAlign = Paint.Align.CENTER paint.textAlign = Paint.Align.CENTER
paint.textSize = ta.getDimension(R.styleable.ProgressDrawable_android_textSize, paint.textSize) paint.textSize = ta.getDimension(R.styleable.ProgressDrawable_android_textSize, paint.textSize)
paint.strokeWidth = ta.getDimension(R.styleable.ProgressDrawable_strokeWidth, 1f) paint.strokeWidth = ta.getDimension(R.styleable.ProgressDrawable_strokeWidth, 1f)
ta.recycle() ta.recycle()
hasBackground = Color.alpha(backgroundColor) != 0 checkDrawable?.setTintList(textColor)
hasOutline = Color.alpha(outlineColor) != 0
hasText = Color.alpha(textColor) != 0 && paint.textSize > 0
checkDrawable?.setTint(textColor)
} }
override fun onBoundsChange(bounds: Rect) { override fun onBoundsChange(bounds: Rect) {
@ -91,16 +97,16 @@ class ReadingProgressDrawable(
val radius = minOf(bounds.width(), bounds.height()) / 2f val radius = minOf(bounds.width(), bounds.height()) / 2f
if (hasBackground) { if (hasBackground) {
paint.style = Paint.Style.FILL paint.style = Paint.Style.FILL
paint.color = backgroundColor paint.color = currentBackgroundColor
canvas.drawCircle(cx, cy, radius, paint) canvas.drawCircle(cx, cy, radius, paint)
} }
val innerRadius = radius - paint.strokeWidth / 2f val innerRadius = radius - paint.strokeWidth / 2f
paint.style = Paint.Style.STROKE paint.style = Paint.Style.STROKE
if (hasOutline) { if (hasOutline) {
paint.color = outlineColor paint.color = currentOutlineColor
canvas.drawCircle(cx, cy, innerRadius, paint) canvas.drawCircle(cx, cy, innerRadius, paint)
} }
paint.color = lineColor paint.color = currentLineColor
canvas.drawArc( canvas.drawArc(
cx - innerRadius, cx - innerRadius,
cy - innerRadius, cy - innerRadius,
@ -119,28 +125,48 @@ class ReadingProgressDrawable(
checkDrawable.draw(canvas) checkDrawable.draw(canvas)
} else { } else {
paint.style = Paint.Style.FILL paint.style = Paint.Style.FILL
paint.color = textColor paint.color = currentTextColor
val ty = bounds.height() / 2f + textBounds.height() / 2f - textBounds.bottom val ty = bounds.height() / 2f + textBounds.height() / 2f - textBounds.bottom
canvas.drawText(text, cx, ty, paint) canvas.drawText(text, cx, ty, paint)
} }
} }
} }
override fun setAlpha(alpha: Int) { override fun getIntrinsicHeight() = desiredHeight
paint.alpha = alpha
}
override fun setColorFilter(colorFilter: ColorFilter?) { override fun getIntrinsicWidth() = desiredWidth
paint.colorFilter = colorFilter
}
@Suppress("DeprecatedCallableAddReplaceWith") override fun isStateful(): Boolean = lineColor.isStateful ||
@Deprecated("Deprecated in Java") outlineColor.isStateful ||
override fun getOpacity() = PixelFormat.TRANSLUCENT backgroundColor.isStateful ||
textColor.isStateful ||
checkDrawable?.isStateful == true
override fun getIntrinsicHeight() = desiredHeight @RequiresApi(Build.VERSION_CODES.S)
override fun hasFocusStateSpecified(): Boolean = lineColor.hasFocusStateSpecified() ||
outlineColor.hasFocusStateSpecified() ||
backgroundColor.hasFocusStateSpecified() ||
textColor.hasFocusStateSpecified() ||
checkDrawable?.hasFocusStateSpecified() == true
override fun getIntrinsicWidth() = desiredWidth override fun onStateChange(state: IntArray): Boolean {
val prevLineColor = currentLineColor
currentLineColor = lineColor.getColorForState(state, lineColor.defaultColor)
val prevOutlineColor = currentOutlineColor
currentOutlineColor = outlineColor.getColorForState(state, outlineColor.defaultColor)
val prevBackgroundColor = currentBackgroundColor
currentBackgroundColor = backgroundColor.getColorForState(state, backgroundColor.defaultColor)
val prevTextColor = currentTextColor
currentTextColor = textColor.getColorForState(state, textColor.defaultColor)
hasBackground = Color.alpha(currentBackgroundColor) != 0
hasOutline = Color.alpha(currentOutlineColor) != 0
hasText = Color.alpha(currentTextColor) != 0 && paint.textSize > 0
return checkDrawable?.setState(state) == true ||
prevLineColor != currentLineColor ||
prevOutlineColor != currentOutlineColor ||
prevBackgroundColor != currentBackgroundColor ||
prevTextColor != currentTextColor
}
private fun getTextSizeForWidth(width: Float, text: String): Float { private fun getTextSizeForWidth(width: Float, text: String): Float {
val testTextSize = 48f val testTextSize = 48f

@ -4,7 +4,6 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.TextWatcher
import android.view.KeyEvent import android.view.KeyEvent
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
@ -21,6 +20,7 @@ import com.google.android.material.textfield.TextInputLayout
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.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
@ -32,7 +32,7 @@ import com.google.android.material.R as materialR
class ProtectActivity : class ProtectActivity :
BaseActivity<ActivityProtectBinding>(), BaseActivity<ActivityProtectBinding>(),
TextView.OnEditorActionListener, TextView.OnEditorActionListener,
TextWatcher, DefaultTextWatcher,
View.OnClickListener { View.OnClickListener {
private val viewModel by viewModels<ProtectViewModel>() private val viewModel by viewModels<ProtectViewModel>()
@ -98,10 +98,6 @@ class ProtectActivity :
} }
} }
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit
override fun afterTextChanged(s: Editable?) { override fun afterTextChanged(s: Editable?) {
viewBinding.layoutPassword.error = null viewBinding.layoutPassword.error = null
viewBinding.buttonNext.isEnabled = !s.isNullOrEmpty() viewBinding.buttonNext.isEnabled = !s.isNullOrEmpty()

@ -5,6 +5,7 @@ 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.content.res.ColorStateList
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Color import android.graphics.Color
import android.graphics.Paint import android.graphics.Paint
@ -19,12 +20,11 @@ import android.view.WindowInsets
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.withStyledAttributes import androidx.core.content.withStyledAttributes
import androidx.core.graphics.ColorUtils
import androidx.core.graphics.withScale import androidx.core.graphics.withScale
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.getThemeColor import org.koitharu.kotatsu.core.util.ext.getThemeColorStateList
import org.koitharu.kotatsu.core.util.ext.measureDimension import org.koitharu.kotatsu.core.util.ext.measureDimension
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
import org.koitharu.kotatsu.parsers.util.format import org.koitharu.kotatsu.parsers.util.format
@ -41,7 +41,7 @@ class ReaderInfoBarView @JvmOverloads constructor(
@AttrRes defStyleAttr: Int = 0, @AttrRes defStyleAttr: Int = 0,
) : View(context, attrs, defStyleAttr) { ) : View(context, attrs, defStyleAttr) {
private val paint = Paint(Paint.ANTI_ALIAS_FLAG) private val paint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.SUBPIXEL_TEXT_FLAG)
private val textBounds = Rect() private val textBounds = Rect()
private val timeFormat = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT) private val timeFormat = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
private val systemStateReceiver = SystemStateReceiver() private val systemStateReceiver = SystemStateReceiver()
@ -52,16 +52,16 @@ class ReaderInfoBarView @JvmOverloads constructor(
private val insetRightFallback: Int private val insetRightFallback: Int
private val insetTopFallback: Int private val insetTopFallback: Int
private val insetCornerFallback = getSystemUiDimensionOffset("rounded_corner_content_padding") private val insetCornerFallback = getSystemUiDimensionOffset("rounded_corner_content_padding")
private val colorText = ColorUtils.setAlphaComponent( private val colorText =
context.getThemeColor(materialR.attr.colorOnSurface, Color.BLACK), (context.getThemeColorStateList(materialR.attr.colorOnSurface)
200, ?: ColorStateList.valueOf(Color.BLACK)).withAlpha(200)
) private val colorOutline =
private val colorOutline = ColorUtils.setAlphaComponent( (context.getThemeColorStateList(materialR.attr.colorSurface)
context.getThemeColor(materialR.attr.colorSurface, Color.WHITE), ?: ColorStateList.valueOf(Color.WHITE)).withAlpha(200)
200,
)
private val batteryIcon = ContextCompat.getDrawable(context, R.drawable.ic_battery_outline) private val batteryIcon = ContextCompat.getDrawable(context, R.drawable.ic_battery_outline)
private var currentTextColor: Int = Color.TRANSPARENT
private var currentOutlineColor: Int = Color.TRANSPARENT
private var timeText = timeFormat.format(LocalTime.now()) private var timeText = timeFormat.format(LocalTime.now())
private var batteryText = "" private var batteryText = ""
private var text: String = "" private var text: String = ""
@ -169,6 +169,29 @@ class ReaderInfoBarView @JvmOverloads constructor(
context.unregisterReceiver(systemStateReceiver) context.unregisterReceiver(systemStateReceiver)
} }
override fun verifyDrawable(who: Drawable): Boolean {
return who == batteryIcon || super.verifyDrawable(who)
}
override fun jumpDrawablesToCurrentState() {
super.jumpDrawablesToCurrentState()
batteryIcon?.jumpToCurrentState()
}
override fun onCreateDrawableState(extraSpace: Int): IntArray? {
val iconState = batteryIcon?.state ?: return super.onCreateDrawableState(extraSpace)
return mergeDrawableStates(super.onCreateDrawableState(extraSpace + iconState.size), iconState)
}
override fun drawableStateChanged() {
currentTextColor = colorText.getColorForState(drawableState, colorText.defaultColor)
currentOutlineColor = colorOutline.getColorForState(drawableState, colorOutline.defaultColor)
super.drawableStateChanged()
if (batteryIcon != null && batteryIcon.isStateful && batteryIcon.setState(drawableState)) {
invalidateDrawable(batteryIcon)
}
}
fun update(state: ReaderUiState?) { fun update(state: ReaderUiState?) {
text = if (state != null) { text = if (state != null) {
context.getString( context.getString(
@ -200,17 +223,17 @@ class ReaderInfoBarView @JvmOverloads constructor(
} }
private fun Canvas.drawTextOutline(text: String, x: Float, y: Float) { private fun Canvas.drawTextOutline(text: String, x: Float, y: Float) {
paint.color = colorOutline paint.color = currentOutlineColor
paint.style = Paint.Style.STROKE paint.style = Paint.Style.STROKE
drawText(text, x, y, paint) drawText(text, x, y, paint)
paint.color = colorText paint.color = currentTextColor
paint.style = Paint.Style.FILL paint.style = Paint.Style.FILL
drawText(text, x, y, paint) drawText(text, x, y, paint)
} }
private fun Drawable.drawWithOutline(canvas: Canvas) { private fun Drawable.drawWithOutline(canvas: Canvas) {
var requiredScale = (bounds.width() + paint.strokeWidth * 2f) / bounds.width().toFloat() var requiredScale = (bounds.width() + paint.strokeWidth * 2f) / bounds.width().toFloat()
setTint(colorOutline) setTint(currentOutlineColor)
canvas.withScale(requiredScale, requiredScale, bounds.exactCenterX(), bounds.exactCenterY()) { canvas.withScale(requiredScale, requiredScale, bounds.exactCenterX(), bounds.exactCenterY()) {
draw(canvas) draw(canvas)
} }
@ -218,7 +241,7 @@ class ReaderInfoBarView @JvmOverloads constructor(
canvas.withScale(requiredScale, requiredScale, bounds.exactCenterX(), bounds.exactCenterY()) { canvas.withScale(requiredScale, requiredScale, bounds.exactCenterX(), bounds.exactCenterY()) {
draw(canvas) draw(canvas)
} }
setTint(colorText) setTint(currentTextColor)
draw(canvas) draw(canvas)
} }

@ -4,16 +4,16 @@ import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.TextWatcher
import android.view.View import android.view.View
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
import androidx.core.net.toUri import androidx.core.net.toUri
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.databinding.ActivityKitsuAuthBinding import org.koitharu.kotatsu.databinding.ActivityKitsuAuthBinding
import org.koitharu.kotatsu.parsers.util.urlEncoded import org.koitharu.kotatsu.parsers.util.urlEncoded
class KitsuAuthActivity : BaseActivity<ActivityKitsuAuthBinding>(), View.OnClickListener, TextWatcher { class KitsuAuthActivity : BaseActivity<ActivityKitsuAuthBinding>(), View.OnClickListener, DefaultTextWatcher {
private val regexEmail = Regex("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", RegexOption.IGNORE_CASE) private val regexEmail = Regex("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", RegexOption.IGNORE_CASE)
@ -43,10 +43,6 @@ class KitsuAuthActivity : BaseActivity<ActivityKitsuAuthBinding>(), View.OnClick
} }
} }
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit
override fun afterTextChanged(s: Editable?) { override fun afterTextChanged(s: Editable?) {
val email = viewBinding.editEmail.text?.toString()?.trim() val email = viewBinding.editEmail.text?.toString()?.trim()
val password = viewBinding.editPassword.text?.toString()?.trim() val password = viewBinding.editPassword.text?.toString()?.trim()

@ -4,7 +4,6 @@ import android.content.pm.PackageManager
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.TextWatcher
import android.view.KeyEvent import android.view.KeyEvent
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
@ -18,6 +17,7 @@ import androidx.core.view.isVisible
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.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
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.ActivitySetupProtectBinding import org.koitharu.kotatsu.databinding.ActivitySetupProtectBinding
@ -27,7 +27,7 @@ private const val MIN_PASSWORD_LENGTH = 4
@AndroidEntryPoint @AndroidEntryPoint
class ProtectSetupActivity : class ProtectSetupActivity :
BaseActivity<ActivitySetupProtectBinding>(), BaseActivity<ActivitySetupProtectBinding>(),
TextWatcher, DefaultTextWatcher,
View.OnClickListener, View.OnClickListener,
TextView.OnEditorActionListener, TextView.OnEditorActionListener,
CompoundButton.OnCheckedChangeListener { CompoundButton.OnCheckedChangeListener {
@ -90,10 +90,6 @@ class ProtectSetupActivity :
} }
} }
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit
override fun afterTextChanged(s: Editable?) { override fun afterTextChanged(s: Editable?) {
viewBinding.editPassword.error = null viewBinding.editPassword.error = null
val isEnoughLength = (s?.length ?: 0) >= MIN_PASSWORD_LENGTH val isEnoughLength = (s?.length ?: 0) >= MIN_PASSWORD_LENGTH

@ -20,6 +20,7 @@ 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
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
@ -187,11 +188,7 @@ class SyncAuthActivity : BaseActivity<ActivitySyncAuthBinding>(), View.OnClickLi
private class PasswordTextWatcher( private class PasswordTextWatcher(
private val button: Button, private val button: Button,
) : TextWatcher { ) : DefaultTextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit
override fun afterTextChanged(s: Editable?) { override fun afterTextChanged(s: Editable?) {
val text = s?.toString() val text = s?.toString()

Loading…
Cancel
Save