Utilize more KTX extensions (#7348)

This commit is contained in:
Taco 2022-06-20 22:54:42 -04:00 committed by GitHub
parent cd5bcc3673
commit c2520bff12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 89 additions and 98 deletions

View File

@ -29,7 +29,7 @@ class BackupCreatorJob(private val context: Context, workerParams: WorkerParamet
override suspend fun doWork(): Result { override suspend fun doWork(): Result {
val preferences = Injekt.get<PreferencesHelper>() val preferences = Injekt.get<PreferencesHelper>()
val notifier = BackupNotifier(context) val notifier = BackupNotifier(context)
val uri = inputData.getString(LOCATION_URI_KEY)?.let { Uri.parse(it) } val uri = inputData.getString(LOCATION_URI_KEY)?.toUri()
?: preferences.backupsDirectory().get().toUri() ?: preferences.backupsDirectory().get().toUri()
val flags = inputData.getInt(BACKUP_FLAGS_KEY, BackupConst.BACKUP_ALL) val flags = inputData.getInt(BACKUP_FLAGS_KEY, BackupConst.BACKUP_ALL)
val isAutoBackup = inputData.getBoolean(IS_AUTO_BACKUP_KEY, true) val isAutoBackup = inputData.getBoolean(IS_AUTO_BACKUP_KEY, true)

View File

@ -4,6 +4,7 @@ import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import androidx.core.net.toUri
import eu.kanade.tachiyomi.extension.util.ExtensionInstaller import eu.kanade.tachiyomi.extension.util.ExtensionInstaller
import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.MainActivity
@ -53,7 +54,7 @@ object NotificationHandler {
} }
fun openUrl(context: Context, url: String): PendingIntent { fun openUrl(context: Context, url: String): PendingIntent {
val notificationIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) val notificationIntent = Intent(Intent.ACTION_VIEW, url.toUri())
return PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE) return PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE)
} }
} }

View File

@ -1,13 +1,13 @@
package eu.kanade.tachiyomi.data.saver package eu.kanade.tachiyomi.data.saver
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.ContentValues
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Environment import android.os.Environment
import android.provider.MediaStore import android.provider.MediaStore
import androidx.core.content.contentValuesOf
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.storage.cacheImageDir import eu.kanade.tachiyomi.util.storage.cacheImageDir
@ -39,15 +39,13 @@ class ImageSaver(
val pictureDir = val pictureDir =
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val contentValues = ContentValues().apply { val contentValues = contentValuesOf(
put(MediaStore.Images.Media.DISPLAY_NAME, image.name) MediaStore.Images.Media.DISPLAY_NAME to image.name,
put(MediaStore.Images.Media.MIME_TYPE, type.mime) MediaStore.Images.Media.MIME_TYPE to type.mime,
put( MediaStore.Images.Media.RELATIVE_PATH to
MediaStore.Images.Media.RELATIVE_PATH,
"${Environment.DIRECTORY_PICTURES}/${context.getString(R.string.app_name)}/" + "${Environment.DIRECTORY_PICTURES}/${context.getString(R.string.app_name)}/" +
(image.location as Location.Pictures).relativePath, (image.location as Location.Pictures).relativePath,
) )
}
val picture = context.contentResolver.insert( val picture = context.contentResolver.insert(
pictureDir, pictureDir,

View File

@ -2,14 +2,14 @@ package eu.kanade.tachiyomi.ui.base.controller
import android.app.Activity import android.app.Activity
import android.os.Bundle import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.text.style.CharacterStyle import android.text.style.CharacterStyle
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.core.text.getSpans
import androidx.core.widget.doAfterTextChanged
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
@ -59,17 +59,9 @@ abstract class SearchableNucleusController<VB : ViewBinding, P : BasePresenter<*
val searchAutoComplete: SearchView.SearchAutoComplete = searchView.findViewById( val searchAutoComplete: SearchView.SearchAutoComplete = searchView.findViewById(
R.id.search_src_text, R.id.search_src_text,
) )
searchAutoComplete.addTextChangedListener(object : TextWatcher { searchAutoComplete.doAfterTextChanged { editable ->
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} editable?.getSpans<CharacterStyle>()?.forEach { editable.removeSpan(it) }
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(editable: Editable) {
editable.getSpans(0, editable.length, CharacterStyle::class.java)
.forEach { editable.removeSpan(it) }
} }
},
)
searchView.queryTextEvents() searchView.queryTextEvents()
.onEach { .onEach {

View File

@ -19,7 +19,9 @@ import androidx.preference.Preference
import androidx.preference.PreferenceGroupAdapter import androidx.preference.PreferenceGroupAdapter
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.preference.PreferenceScreen import androidx.preference.PreferenceScreen
import androidx.preference.get
import androidx.preference.getOnBindEditTextListener import androidx.preference.getOnBindEditTextListener
import androidx.preference.isNotEmpty
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore
@ -111,8 +113,8 @@ class SourcePreferencesController(bundle: Bundle? = null) :
source.setupPreferenceScreen(newScreen) source.setupPreferenceScreen(newScreen)
// Reparent the preferences // Reparent the preferences
while (newScreen.preferenceCount != 0) { while (newScreen.isNotEmpty()) {
val pref = newScreen.getPreference(0) val pref = newScreen[0]
pref.isIconSpaceReserved = false pref.isIconSpaceReserved = false
pref.order = Int.MAX_VALUE // reset to default order pref.order = Int.MAX_VALUE // reset to default order
@ -143,7 +145,7 @@ class SourcePreferencesController(bundle: Bundle? = null) :
val screen = preference.parent!! val screen = preference.parent!!
lastOpenPreferencePosition = (0 until screen.preferenceCount).indexOfFirst { lastOpenPreferencePosition = (0 until screen.preferenceCount).indexOfFirst {
screen.getPreference(it) === preference screen[it] === preference
} }
val f = when (preference) { val f = when (preference) {
@ -169,7 +171,7 @@ class SourcePreferencesController(bundle: Bundle? = null) :
override fun <T : Preference> findPreference(key: CharSequence): T? { override fun <T : Preference> findPreference(key: CharSequence): T? {
// We track [lastOpenPreferencePosition] when displaying the dialog // We track [lastOpenPreferencePosition] when displaying the dialog
// [key] isn't useful since there may be duplicates // [key] isn't useful since there may be duplicates
return preferenceScreen!!.getPreference(lastOpenPreferencePosition!!) as T return preferenceScreen!![lastOpenPreferencePosition!!] as T
} }
} }

View File

@ -8,6 +8,7 @@ import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.get
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
@ -202,7 +203,7 @@ open class BrowseSourceController(bundle: Bundle) :
numColumnsJob?.cancel() numColumnsJob?.cancel()
var oldPosition = RecyclerView.NO_POSITION var oldPosition = RecyclerView.NO_POSITION
val oldRecycler = binding.catalogueView.getChildAt(1) val oldRecycler = binding.catalogueView[1]
if (oldRecycler is RecyclerView) { if (oldRecycler is RecyclerView) {
oldPosition = (oldRecycler.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() oldPosition = (oldRecycler.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
oldRecycler.adapter = null oldRecycler.adapter = null

View File

@ -6,6 +6,7 @@ import android.util.AttributeSet
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.get
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.databinding.SourceFilterSheetBinding import eu.kanade.tachiyomi.databinding.SourceFilterSheetBinding
@ -55,7 +56,7 @@ class SourceFilterSheet(
init { init {
recycler.adapter = adapter recycler.adapter = adapter
recycler.setHasFixedSize(true) recycler.setHasFixedSize(true)
(binding.root.getChildAt(1) as ViewGroup).addView(recycler) (binding.root[1] as ViewGroup).addView(recycler)
addView(binding.root) addView(binding.root)
binding.filterBtn.setOnClickListener { onFilterClicked() } binding.filterBtn.setOnClickListener { onFilterClicked() }
binding.resetBtn.setOnClickListener { onResetClicked() } binding.resetBtn.setOnClickListener { onResetClicked() }

View File

@ -3,11 +3,11 @@ package eu.kanade.tachiyomi.ui.reader
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.graphics.Color import android.graphics.Color
import android.text.Spannable
import android.text.SpannableString import android.text.SpannableString
import android.text.style.ScaleXSpan import android.text.style.ScaleXSpan
import android.util.AttributeSet import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatTextView import androidx.appcompat.widget.AppCompatTextView
import androidx.core.text.set
import eu.kanade.tachiyomi.widget.OutlineSpan import eu.kanade.tachiyomi.widget.OutlineSpan
/** /**
@ -31,10 +31,10 @@ class PageIndicatorTextView(
// Also add a bit of spacing between each character, as the stroke overlaps them // Also add a bit of spacing between each character, as the stroke overlaps them
val finalText = SpannableString(currText.asIterable().joinToString("\u00A0")).apply { val finalText = SpannableString(currText.asIterable().joinToString("\u00A0")).apply {
// Apply text outline // Apply text outline
setSpan(spanOutline, 1, length - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) set(1, length - 1, spanOutline)
for (i in 1..lastIndex step 2) { for (i in 1..lastIndex step 2) {
setSpan(ScaleXSpan(0.2f), i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) set(i, i + 1, ScaleXSpan(0.2f))
} }
} }

View File

@ -30,7 +30,7 @@ import android.view.animation.AnimationUtils
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.Toast import android.widget.Toast
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
import androidx.core.transition.addListener import androidx.core.transition.doOnEnd
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.WindowInsetsControllerCompat
@ -621,9 +621,9 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>() {
updateCropBordersShortcut() updateCropBordersShortcut()
if (window.sharedElementEnterTransition is MaterialContainerTransform) { if (window.sharedElementEnterTransition is MaterialContainerTransform) {
// Wait until transition is complete to avoid crash on API 26 // Wait until transition is complete to avoid crash on API 26
window.sharedElementEnterTransition.addListener( window.sharedElementEnterTransition.doOnEnd {
onEnd = { setOrientation(presenter.getMangaOrientationType()) }, setOrientation(presenter.getMangaOrientationType())
) }
} else { } else {
setOrientation(presenter.getMangaOrientationType()) setOrientation(presenter.getMangaOrientationType())
} }

View File

@ -8,7 +8,8 @@ import android.util.AttributeSet
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewPropertyAnimator import android.view.ViewPropertyAnimator
import androidx.core.graphics.withSave import androidx.core.graphics.withScale
import androidx.core.graphics.withTranslation
import androidx.core.view.isVisible import androidx.core.view.isVisible
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.DisabledNavigation import eu.kanade.tachiyomi.ui.reader.viewer.navigation.DisabledNavigation
@ -63,17 +64,15 @@ class ReaderNavigationOverlayView(context: Context, attributeSet: AttributeSet)
navigation?.regions?.forEach { region -> navigation?.regions?.forEach { region ->
val rect = region.rectF val rect = region.rectF
canvas?.withSave {
// Scale rect from 1f,1f to screen width and height // Scale rect from 1f,1f to screen width and height
scale(width.toFloat(), height.toFloat()) canvas?.withScale(width.toFloat(), height.toFloat()) {
regionPaint.color = context.getColor(region.type.colorRes) regionPaint.color = context.getColor(region.type.colorRes)
drawRect(rect, regionPaint) drawRect(rect, regionPaint)
} }
// Don't want scale anymore because it messes with drawText
canvas?.withSave {
// Translate origin to rect start (left, top)
translate((width * rect.left), (height * rect.top))
// Don't want scale anymore because it messes with drawText
// Translate origin to rect start (left, top)
canvas?.withTranslation(x = (width * rect.left), y = (height * rect.top)) {
// Calculate center of rect width on screen // Calculate center of rect width on screen
val x = width * (abs(rect.left - rect.right) / 2) val x = width * (abs(rect.left - rect.right) / 2)

View File

@ -16,6 +16,7 @@ import androidx.annotation.AttrRes
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import androidx.annotation.StyleRes import androidx.annotation.StyleRes
import androidx.appcompat.widget.AppCompatImageView import androidx.appcompat.widget.AppCompatImageView
import androidx.core.os.postDelayed
import androidx.core.view.isVisible import androidx.core.view.isVisible
import coil.dispose import coil.dispose
import coil.imageLoader import coil.imageLoader
@ -110,7 +111,7 @@ open class ReaderPageImageView @JvmOverloads constructor(
private fun SubsamplingScaleImageView.landscapeZoom(forward: Boolean) { private fun SubsamplingScaleImageView.landscapeZoom(forward: Boolean) {
if (config != null && config!!.landscapeZoom && config!!.minimumScaleType == SCALE_TYPE_CENTER_INSIDE && sWidth > sHeight && scale == minScale) { if (config != null && config!!.landscapeZoom && config!!.minimumScaleType == SCALE_TYPE_CENTER_INSIDE && sWidth > sHeight && scale == minScale) {
handler?.postDelayed({ handler?.postDelayed(500) {
val point = when (config!!.zoomStartPosition) { val point = when (config!!.zoomStartPosition) {
ZoomStartPosition.LEFT -> if (forward) PointF(0F, 0F) else PointF(sWidth.toFloat(), 0F) ZoomStartPosition.LEFT -> if (forward) PointF(0F, 0F) else PointF(sWidth.toFloat(), 0F)
ZoomStartPosition.RIGHT -> if (forward) PointF(sWidth.toFloat(), 0F) else PointF(0F, 0F) ZoomStartPosition.RIGHT -> if (forward) PointF(sWidth.toFloat(), 0F) else PointF(0F, 0F)
@ -123,7 +124,7 @@ open class ReaderPageImageView @JvmOverloads constructor(
.withEasing(EASE_IN_OUT_QUAD) .withEasing(EASE_IN_OUT_QUAD)
.withInterruptible(true) .withInterruptible(true)
.start() .start()
}, 500,) }
} }
} }

View File

@ -9,6 +9,7 @@ import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.appcompat.widget.AppCompatTextView import androidx.appcompat.widget.AppCompatTextView
import androidx.core.view.updatePadding
import com.google.android.material.progressindicator.CircularProgressIndicator import com.google.android.material.progressindicator.CircularProgressIndicator
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
@ -55,7 +56,7 @@ class PagerTransitionHolder(
orientation = VERTICAL orientation = VERTICAL
gravity = Gravity.CENTER gravity = Gravity.CENTER
val sidePadding = 64.dpToPx val sidePadding = 64.dpToPx
setPadding(sidePadding, 0, sidePadding, 0) updatePadding(left = sidePadding, right = sidePadding)
val transitionView = ReaderTransitionView(context) val transitionView = ReaderTransitionView(context)
addView(transitionView) addView(transitionView)

View File

@ -7,6 +7,8 @@ import androidx.preference.Preference
import androidx.preference.PreferenceCategory import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceGroup import androidx.preference.PreferenceGroup
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.preference.forEach
import androidx.preference.get
import eu.kanade.tachiyomi.ui.setting.SettingsAdvancedController import eu.kanade.tachiyomi.ui.setting.SettingsAdvancedController
import eu.kanade.tachiyomi.ui.setting.SettingsAppearanceController import eu.kanade.tachiyomi.ui.setting.SettingsAppearanceController
import eu.kanade.tachiyomi.ui.setting.SettingsBackupController import eu.kanade.tachiyomi.ui.setting.SettingsBackupController
@ -56,7 +58,7 @@ object SettingsSearchHelper {
val settingsPrefScreen = ctrl.setupPreferenceScreen(preferenceManager.createPreferenceScreen(context)) val settingsPrefScreen = ctrl.setupPreferenceScreen(preferenceManager.createPreferenceScreen(context))
val prefCount = settingsPrefScreen.preferenceCount val prefCount = settingsPrefScreen.preferenceCount
for (i in 0 until prefCount) { for (i in 0 until prefCount) {
val rootPref = settingsPrefScreen.getPreference(i) val rootPref = settingsPrefScreen[i]
if (rootPref.title == null) continue // no title, not a preference. (note: only info notes appear to not have titles) if (rootPref.title == null) continue // no title, not a preference. (note: only info notes appear to not have titles)
getSettingSearchResult(ctrl, rootPref, "${settingsPrefScreen.title}") getSettingSearchResult(ctrl, rootPref, "${settingsPrefScreen.title}")
} }
@ -86,18 +88,14 @@ object SettingsSearchHelper {
when { when {
pref is PreferenceGroup -> { pref is PreferenceGroup -> {
val breadcrumbsStr = addLocalizedBreadcrumb(breadcrumbs, "${pref.title}") val breadcrumbsStr = addLocalizedBreadcrumb(breadcrumbs, "${pref.title}")
pref.forEach {
for (x in 0 until pref.preferenceCount) { getSettingSearchResult(ctrl, it, breadcrumbsStr) // recursion
val subPref = pref.getPreference(x)
getSettingSearchResult(ctrl, subPref, breadcrumbsStr) // recursion
} }
} }
pref is PreferenceCategory -> { pref is PreferenceCategory -> {
val breadcrumbsStr = addLocalizedBreadcrumb(breadcrumbs, "${pref.title}") val breadcrumbsStr = addLocalizedBreadcrumb(breadcrumbs, "${pref.title}")
pref.forEach {
for (x in 0 until pref.preferenceCount) { getSettingSearchResult(ctrl, it, breadcrumbsStr) // recursion
val subPref = pref.getPreference(x)
getSettingSearchResult(ctrl, subPref, breadcrumbsStr) // recursion
} }
} }
(pref.title != null && pref.isVisible) -> { (pref.title != null && pref.isVisible) -> {

View File

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.util.lang package eu.kanade.tachiyomi.util.lang
import android.os.Build import androidx.core.text.parseAsHtml
import android.text.Html
import net.greypanther.natsort.CaseInsensitiveSimpleNaturalComparator import net.greypanther.natsort.CaseInsensitiveSimpleNaturalComparator
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import kotlin.math.floor import kotlin.math.floor
@ -64,9 +63,5 @@ fun String.takeBytes(n: Int): String {
* HTML-decode the string * HTML-decode the string
*/ */
fun String.htmlDecode(): String { fun String.htmlDecode(): String {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return this.parseAsHtml().toString()
Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY).toString()
} else {
Html.fromHtml(this).toString()
}
} }

View File

@ -262,7 +262,7 @@ fun Context.openInBrowser(uri: Uri, forceDefaultBrowser: Boolean = false) {
} }
fun Context.defaultBrowserPackageName(): String? { fun Context.defaultBrowserPackageName(): String? {
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse("http://")) val browserIntent = Intent(Intent.ACTION_VIEW, "http://".toUri())
return packageManager.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY) return packageManager.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY)
?.activityInfo?.packageName ?.activityInfo?.packageName
?.takeUnless { it in DeviceUtil.invalidDefaultBrowsers } ?.takeUnless { it in DeviceUtil.invalidDefaultBrowsers }

View File

@ -16,6 +16,7 @@ import androidx.core.graphics.alpha
import androidx.core.graphics.applyCanvas import androidx.core.graphics.applyCanvas
import androidx.core.graphics.blue import androidx.core.graphics.blue
import androidx.core.graphics.createBitmap import androidx.core.graphics.createBitmap
import androidx.core.graphics.get
import androidx.core.graphics.green import androidx.core.graphics.green
import androidx.core.graphics.red import androidx.core.graphics.red
import com.hippo.unifile.UniFile import com.hippo.unifile.UniFile
@ -273,14 +274,14 @@ object ImageUtil {
val leftOffsetX = left - offsetX val leftOffsetX = left - offsetX
val rightOffsetX = right + offsetX val rightOffsetX = right + offsetX
val topLeftPixel = image.getPixel(left, top) val topLeftPixel = image[left, top]
val topRightPixel = image.getPixel(right, top) val topRightPixel = image[right, top]
val midLeftPixel = image.getPixel(left, midY) val midLeftPixel = image[left, midY]
val midRightPixel = image.getPixel(right, midY) val midRightPixel = image[right, midY]
val topCenterPixel = image.getPixel(midX, top) val topCenterPixel = image[midX, top]
val botLeftPixel = image.getPixel(left, bot) val botLeftPixel = image[left, bot]
val bottomCenterPixel = image.getPixel(midX, bot) val bottomCenterPixel = image[midX, bot]
val botRightPixel = image.getPixel(right, bot) val botRightPixel = image[right, bot]
val topLeftIsDark = topLeftPixel.isDark() val topLeftIsDark = topLeftPixel.isDark()
val topRightIsDark = topRightPixel.isDark() val topRightIsDark = topRightPixel.isDark()
@ -333,8 +334,8 @@ object ImageUtil {
var whiteStreak = false var whiteStreak = false
val notOffset = x == left || x == right val notOffset = x == left || x == right
inner@ for ((index, y) in (0 until image.height step image.height / 25).withIndex()) { inner@ for ((index, y) in (0 until image.height step image.height / 25).withIndex()) {
val pixel = image.getPixel(x, y) val pixel = image[x, y]
val pixelOff = image.getPixel(x + (if (x < image.width / 2) -offsetX else offsetX), y) val pixelOff = image[x + (if (x < image.width / 2) -offsetX else offsetX), y]
if (pixel.isWhite()) { if (pixel.isWhite()) {
whitePixelsStreak++ whitePixelsStreak++
whitePixels++ whitePixels++
@ -425,8 +426,8 @@ object ImageUtil {
val topCornersIsDark = topLeftIsDark && topRightIsDark val topCornersIsDark = topLeftIsDark && topRightIsDark
val botCornersIsDark = botLeftIsDark && botRightIsDark val botCornersIsDark = botLeftIsDark && botRightIsDark
val topOffsetCornersIsDark = image.getPixel(leftOffsetX, top).isDark() && image.getPixel(rightOffsetX, top).isDark() val topOffsetCornersIsDark = image[leftOffsetX, top].isDark() && image[rightOffsetX, top].isDark()
val botOffsetCornersIsDark = image.getPixel(leftOffsetX, bot).isDark() && image.getPixel(rightOffsetX, bot).isDark() val botOffsetCornersIsDark = image[leftOffsetX, bot].isDark() && image[rightOffsetX, bot].isDark()
val gradient = when { val gradient = when {
darkBG && botCornersIsWhite -> { darkBG && botCornersIsWhite -> {

View File

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.widget
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import androidx.core.content.withStyledAttributes
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlin.math.max import kotlin.math.max
@ -27,9 +28,9 @@ class AutofitRecyclerView @JvmOverloads constructor(context: Context, attrs: Att
init { init {
if (attrs != null) { if (attrs != null) {
val attrsArray = intArrayOf(android.R.attr.columnWidth) val attrsArray = intArrayOf(android.R.attr.columnWidth)
val array = context.obtainStyledAttributes(attrs, attrsArray) context.withStyledAttributes(attrs, attrsArray) {
columnWidth = array.getDimensionPixelSize(0, -1) columnWidth = getDimensionPixelSize(0, -1)
array.recycle() }
} }
layoutManager = manager layoutManager = manager

View File

@ -9,6 +9,7 @@ import androidx.annotation.AttrRes
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.content.res.AppCompatResources
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.getResourceColor
@ -230,7 +231,7 @@ open class ExtendedNavigationView @JvmOverloads constructor(
is SeparatorHolder -> { is SeparatorHolder -> {
val view = holder.itemView val view = holder.itemView
val item = items[position] as Item.Separator val item = items[position] as Item.Separator
view.setPadding(0, item.paddingTop, 0, item.paddingBottom) view.updatePadding(top = item.paddingTop, bottom = item.paddingBottom)
} }
is RadioHolder -> { is RadioHolder -> {
val item = items[position] as Item.Radio val item = items[position] as Item.Radio

View File

@ -11,6 +11,7 @@ import androidx.annotation.ArrayRes
import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.content.res.AppCompatResources
import androidx.appcompat.view.menu.MenuBuilder import androidx.appcompat.view.menu.MenuBuilder
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.content.withStyledAttributes
import androidx.core.view.forEach import androidx.core.view.forEach
import androidx.core.view.get import androidx.core.view.get
import com.fredporciuncula.flow.preferences.Preference import com.fredporciuncula.flow.preferences.Preference
@ -51,16 +52,15 @@ class MaterialSpinnerView @JvmOverloads constructor(context: Context, attrs: Att
init { init {
addView(binding.root) addView(binding.root)
val attr = context.obtainStyledAttributes(attrs, R.styleable.MaterialSpinnerView) context.withStyledAttributes(set = attrs, attrs = R.styleable.MaterialSpinnerView) {
val title = getString(R.styleable.MaterialSpinnerView_title).orEmpty()
val title = attr.getString(R.styleable.MaterialSpinnerView_title).orEmpty()
binding.title.text = title binding.title.text = title
val entries = (attr.getTextArray(R.styleable.MaterialSpinnerView_android_entries) ?: emptyArray()).map { it.toString() } val viewEntries = (getTextArray(R.styleable.MaterialSpinnerView_android_entries)
this.entries = entries ?: emptyArray()).map { it.toString() }
binding.details.text = entries.firstOrNull().orEmpty() entries = viewEntries
binding.details.text = viewEntries.firstOrNull().orEmpty()
attr.recycle() }
} }
fun setSelection(selection: Int) { fun setSelection(selection: Int) {
@ -152,9 +152,7 @@ class MaterialSpinnerView @JvmOverloads constructor(context: Context, attrs: Att
popup.menu.forEach { popup.menu.forEach {
it.icon = emptyIcon it.icon = emptyIcon
} }
popup.menu.getItem(selectedPosition)?.let { popup.menu[selectedPosition].icon = checkmarkIcon
it.icon = checkmarkIcon
}
popup.setOnMenuItemClickListener { menuItem -> popup.setOnMenuItemClickListener { menuItem ->
val pos = menuClicked(menuItem) val pos = menuClicked(menuItem)
onItemClick(pos) onItemClick(pos)

View File

@ -12,6 +12,8 @@ import android.util.AttributeSet
import android.view.animation.LinearInterpolator import android.view.animation.LinearInterpolator
import android.widget.TextView import android.widget.TextView
import androidx.annotation.FloatRange import androidx.annotation.FloatRange
import androidx.core.graphics.drawable.updateBounds
import androidx.core.graphics.withTranslation
import androidx.lifecycle.coroutineScope import androidx.lifecycle.coroutineScope
import androidx.lifecycle.findViewTreeLifecycleOwner import androidx.lifecycle.findViewTreeLifecycleOwner
import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.shape.MaterialShapeDrawable
@ -84,15 +86,14 @@ class TachiyomiAppBarLayout @JvmOverloads constructor(
override fun draw(canvas: Canvas) { override fun draw(canvas: Canvas) {
super.draw(canvas) super.draw(canvas)
val saveCount = canvas.save() canvas.withTranslation(y = -currentOffset.toFloat()) {
canvas.translate(0f, -currentOffset.toFloat()) statusBarForeground?.draw(this)
statusBarForeground?.draw(canvas) }
canvas.restoreToCount(saveCount)
} }
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, l, t, r, b) super.onLayout(changed, l, t, r, b)
statusBarForeground?.setBounds(0, 0, width, paddingTop) statusBarForeground?.updateBounds(right = width, bottom = paddingTop)
} }
override fun onOffsetChanged(offset: Int) { override fun onOffsetChanged(offset: Int) {