From 62927cb6a8b3508eca166c5b5456215ed407275a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <99822064+revonateB0T@users.noreply.github.com> Date: Thu, 24 Oct 2024 23:38:27 +0800 Subject: [PATCH] Kill Legacy TextView (#1786) * Kill Legacy TextView * Fix textStyle * Fix color * Add breakToTextAndUrl * Impl breakToTextAndUrl * Fix OOB * Update GalleryCommentsScreen.kt * Fix bug * Fix color * Refine regex * Add undeline as well * Refine * Revert * Don't break if not show image --------- Co-authored-by: Dude so hot --- .../ehviewer/ui/legacy/CoilImageGetter.kt | 33 ----- .../ehviewer/ui/legacy/LinkifyTextView.kt | 58 --------- .../hippo/ehviewer/ui/main/GalleryComment.kt | 90 ++++++++------ .../ui/screen/GalleryCommentsScreen.kt | 113 +++++++++++------- .../ui/screen/GalleryDetailContent.kt | 13 +- .../com/hippo/ehviewer/util/ReadableTime.kt | 31 ++--- .../kotlin/com/hippo/ehviewer/util/TextUrl.kt | 39 ------ .../main/kotlin/rikka/core/res/Resources.kt | 13 -- 8 files changed, 141 insertions(+), 249 deletions(-) delete mode 100644 app/src/main/kotlin/com/hippo/ehviewer/ui/legacy/CoilImageGetter.kt delete mode 100644 app/src/main/kotlin/com/hippo/ehviewer/ui/legacy/LinkifyTextView.kt delete mode 100644 app/src/main/kotlin/com/hippo/ehviewer/util/TextUrl.kt delete mode 100644 app/src/main/kotlin/rikka/core/res/Resources.kt diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/legacy/CoilImageGetter.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/legacy/CoilImageGetter.kt deleted file mode 100644 index c894a0931..000000000 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/legacy/CoilImageGetter.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.hippo.ehviewer.ui.legacy - -import android.graphics.drawable.Animatable -import android.graphics.drawable.DrawableWrapper -import android.text.Html -import android.widget.TextView -import coil3.asDrawable -import coil3.imageLoader -import coil3.request.crossfade -import coil3.size.Size -import com.hippo.ehviewer.ktbuilder.imageRequest - -class CoilImageGetter( - private val textView: TextView, -) : Html.ImageGetter { - override fun getDrawable(source: String) = object : DrawableWrapper(null) {}.apply { - with(textView.context) { - imageLoader.enqueue( - imageRequest { - data(source) - crossfade(false) - size(Size.ORIGINAL) - target { drawable -> - setDrawable(drawable.asDrawable(resources)) - if (drawable is Animatable) drawable.start() - setBounds(0, 0, intrinsicWidth, intrinsicHeight) - textView.text = textView.text - } - }, - ) - } - } -} diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/legacy/LinkifyTextView.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/legacy/LinkifyTextView.kt deleted file mode 100644 index 0a8d95806..000000000 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/legacy/LinkifyTextView.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2015 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.hippo.ehviewer.ui.legacy - -import android.content.Context -import android.text.Spanned -import android.text.style.ClickableSpan -import android.util.AttributeSet -import android.view.MotionEvent -import androidx.appcompat.widget.AppCompatTextView - -class LinkifyTextView @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - private val onCurrentSpanUpdate: (ClickableSpan?) -> Unit, -) : AppCompatTextView(context, attrs) { - override fun onTouchEvent(event: MotionEvent): Boolean { - // Let the parent or grandparent of TextView to handles click aciton. - // Otherwise click effect like ripple will not work, and if touch area - // do not contain a url, the TextView will still get MotionEvent. - // onTouchEven must be called with MotionEvent.ACTION_DOWN for each touch - // action on it, so we analyze touched url here. - if (event.action == MotionEvent.ACTION_DOWN) { - onCurrentSpanUpdate(null) - if (text is Spanned) { - var x = event.x.toInt() - var y = event.y.toInt() - x -= totalPaddingLeft - y -= totalPaddingTop - x += scrollX - y += scrollY - val layout = layout - if (null != layout) { - val line = layout.getLineForVertical(y) - val off = layout.getOffsetForHorizontal(line, x.toFloat()) - val spans = (text as Spanned).getSpans(off, off, ClickableSpan::class.java) - if (spans.isNotEmpty()) { - onCurrentSpanUpdate(spans[0]) - } - } - } - } - return super.onTouchEvent(event) - } -} diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/main/GalleryComment.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/main/GalleryComment.kt index 2538185be..7694dfbb3 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/main/GalleryComment.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/main/GalleryComment.kt @@ -1,32 +1,36 @@ package com.hippo.ehviewer.ui.main -import android.text.style.ClickableSpan -import android.text.style.URLSpan import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material3.Card -import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ProvideTextStyle import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.LinkAnnotation +import androidx.compose.ui.text.LinkInteractionListener +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.TextLinkStyles +import androidx.compose.ui.text.fromHtml +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import androidx.compose.ui.viewinterop.AndroidView import androidx.constraintlayout.compose.ConstraintLayout +import arrow.core.Either +import coil3.compose.AsyncImage import com.hippo.ehviewer.R import com.hippo.ehviewer.client.data.GalleryComment -import com.hippo.ehviewer.ui.legacy.LinkifyTextView +import com.hippo.ehviewer.ui.screen.breakToTextAndUrl import com.hippo.ehviewer.util.ReadableTime +typealias TextOrUrl = Either +typealias TextOrUrlList = List + @Composable fun GalleryCommentCard( modifier: Modifier = Modifier, @@ -34,22 +38,14 @@ fun GalleryCommentCard( onCardClick: () -> Unit, onUserClick: () -> Unit, onUrlClick: (String) -> Unit, - update: LinkifyTextView.() -> Unit, -) = comment.run { - var currentSpan by remember(comment) { mutableStateOf(null) } - Card( - onClick = { - val span = currentSpan.apply { currentSpan = null } - if (span is URLSpan) { - onUrlClick(span.url) - } else { - onCardClick() - } - }, - modifier = modifier, - ) { - val keylineMargin = dimensionResource(id = R.dimen.keyline_margin) - ConstraintLayout(modifier = Modifier.padding(horizontal = keylineMargin, vertical = 8.dp).fillMaxWidth()) { + maxLines: Int = Int.MAX_VALUE, + overflow: TextOverflow = TextOverflow.Clip, + showImage: Boolean = false, + processComment: @Composable (GalleryComment, TextLinkStyles, LinkInteractionListener) -> AnnotatedString = { c, s, l -> AnnotatedString.fromHtml(c.comment, s, l) }, +) = with(comment) { + Card(onClick = onCardClick, modifier = modifier) { + val margin = dimensionResource(id = R.dimen.keyline_margin) + ConstraintLayout(modifier = Modifier.padding(horizontal = margin, vertical = 8.dp).fillMaxWidth()) { val (userRef, timeRef, commentRef) = createRefs() ProvideTextStyle(value = MaterialTheme.typography.titleSmall) { val userText = if (uploader) stringResource(id = R.string.comment_user_uploader, user.orEmpty()) else user.orEmpty() @@ -68,21 +64,41 @@ fun GalleryCommentCard( }, ) } - val textColor = LocalContentColor.current.toArgb() - val linkTextColor = MaterialTheme.colorScheme.primary.toArgb() - AndroidView( - factory = { context -> - LinkifyTextView(context) { currentSpan = it }.apply { - setTextColor(textColor) - setLinkTextColor(linkTextColor) - } - }, + Column( modifier = Modifier.constrainAs(commentRef) { start.linkTo(parent.start) top.linkTo(userRef.bottom, margin = 8.dp) }, - update = update, - ) + ) { + ProvideTextStyle(value = MaterialTheme.typography.bodyMedium) { + val linkColor = MaterialTheme.colorScheme.primary + val processed = processComment( + comment, + TextLinkStyles(style = SpanStyle(color = linkColor)), + ) { link -> + check(link is LinkAnnotation.Url) + onUrlClick(link.url) + } + if (showImage) { + val list = breakToTextAndUrl(comment.comment, processed) + list.forEach { + when (it) { + is Either.Left -> AsyncImage( + model = it.value, + contentDescription = null, + ) + is Either.Right -> Text(text = it.value) + } + } + } else { + Text( + text = processed, + maxLines = maxLines, + overflow = overflow, + ) + } + } + } } } } diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryCommentsScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryCommentsScreen.kt index 33df54f6e..387c3eb37 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryCommentsScreen.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryCommentsScreen.kt @@ -1,12 +1,5 @@ package com.hippo.ehviewer.ui.screen -import android.content.Context -import android.graphics.Typeface -import android.text.SpannableStringBuilder -import android.text.style.ForegroundColorSpan -import android.text.style.RelativeSizeSpan -import android.text.style.StyleSpan -import android.widget.TextView import androidx.compose.animation.AnimatedVisibilityScope import androidx.compose.animation.Crossfade import androidx.compose.foundation.layout.Arrangement @@ -67,14 +60,23 @@ import androidx.compose.ui.platform.LocalTextToolbar import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.LinkAnnotation +import androidx.compose.ui.text.LinkInteractionListener +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.TextLinkStyles +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.fromHtml import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.em import androidx.compose.ui.unit.max import androidx.compose.ui.util.lerp -import androidx.core.text.inSpans import androidx.core.text.parseAsHtml +import arrow.core.left +import arrow.core.right import com.hippo.ehviewer.R import com.hippo.ehviewer.Settings import com.hippo.ehviewer.client.EhEngine @@ -87,8 +89,9 @@ import com.hippo.ehviewer.dao.Filter import com.hippo.ehviewer.dao.FilterMode import com.hippo.ehviewer.ui.composing import com.hippo.ehviewer.ui.jumpToReaderByPage -import com.hippo.ehviewer.ui.legacy.CoilImageGetter import com.hippo.ehviewer.ui.main.GalleryCommentCard +import com.hippo.ehviewer.ui.main.TextOrUrl +import com.hippo.ehviewer.ui.main.TextOrUrlList import com.hippo.ehviewer.ui.openBrowser import com.hippo.ehviewer.ui.tools.animateFloatMergePredictiveBackAsState import com.hippo.ehviewer.ui.tools.normalizeSpan @@ -98,7 +101,6 @@ import com.hippo.ehviewer.ui.tools.thenIf import com.hippo.ehviewer.ui.tools.toBBCode import com.hippo.ehviewer.ui.tools.updateSpan import com.hippo.ehviewer.util.ReadableTime -import com.hippo.ehviewer.util.TextUrl import com.hippo.ehviewer.util.addTextToClipboard import com.hippo.ehviewer.util.displayString import com.ramcosta.composedestinations.annotation.Destination @@ -108,41 +110,68 @@ import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.system.logcat import kotlin.math.roundToInt +import kotlin.sequences.forEach import kotlinx.coroutines.launch import moe.tarsin.coroutines.runSuspendCatching -import rikka.core.res.resolveColor -private fun Context.generateComment( - textView: TextView, +private const val IMAGE_OBJ = '' +private val IMAGE_PATTERN = Regex(" { + while (true) { + val index = text.text.indexOf(IMAGE_OBJ, currentOfs) + if (index == -1) break + add(text.subSequence(currentOfs, index).right()) + add(iter.next().groupValues[1].left()) + currentOfs = index + 1 + } + add(text.subSequence(currentOfs, text.length).right()) + } +} + +@Composable +fun processComment( comment: GalleryComment, -): CharSequence { - val sp = comment.comment.parseAsHtml(imageGetter = CoilImageGetter(textView)) - val ssb = SpannableStringBuilder(sp) - if (0L != comment.id && 0 != comment.score) { - val score = comment.score - val scoreString = if (score > 0) "+$score" else score.toString() - ssb.append(" ").inSpans( - RelativeSizeSpan(0.8f), - StyleSpan(Typeface.BOLD), - ForegroundColorSpan(theme.resolveColor(android.R.attr.textColorSecondary)), - ) { - append(scoreString) + linkStyle: TextLinkStyles, + onLinkClick: LinkInteractionListener, +) = AnnotatedString.fromHtml(comment.comment, linkStyle, onLinkClick).let { text -> + buildAnnotatedString { + val onSurfaceVariant = MaterialTheme.colorScheme.onSurfaceVariant + append(text) + URL_PATTERN.findAll(text).forEach { result -> + val start = result.range.first + val end = result.range.last + 1 + if (!text.hasLinkAnnotations(start, end)) { + addLink(LinkAnnotation.Url(result.groupValues[0], linkStyle, onLinkClick), start, end) + } + } + val style = SpanStyle(fontSize = 0.8f.em, fontWeight = FontWeight.Bold, color = onSurfaceVariant) + if (comment.id != 0L && comment.score != 0) { + val score = comment.score + val scoreString = if (score > 0) "+$score" else score.toString() + append(" ") + withStyle(style) { + append(scoreString) + } + } + if (comment.lastEdited != 0L) { + append("\n\n") + withStyle(style) { + append( + stringResource( + R.string.last_edited, + ReadableTime.getTimeAgo(comment.lastEdited), + ), + ) + } } } - if (comment.lastEdited != 0L) { - val str = getString( - R.string.last_edited, - ReadableTime.getTimeAgo(comment.lastEdited), - ) - ssb.append("\n\n").inSpans( - RelativeSizeSpan(0.8f), - StyleSpan(Typeface.BOLD), - ForegroundColorSpan(theme.resolveColor(android.R.attr.textColorSecondary)), - ) { - append(str) - } - } - return TextUrl.handleTextUrl(ssb) } private val MinimumContentPaddingEditText = 88.dp @@ -380,9 +409,9 @@ fun AnimatedVisibilityScope.GalleryCommentsScreen(gid: Long, navigator: Destinat }, onCardClick = { launch { doCommentAction(item) } }, onUrlClick = { if (!jumpToReaderByPage(it, galleryDetail)) if (!navWithUrl(it)) openBrowser(it) }, - ) { - text = generateComment(this, item) - } + processComment = { c, s, l -> processComment(c, s, l) }, + showImage = true, + ) } if (comments.hasMore) { item { diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryDetailContent.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryDetailContent.kt index 811e26ca7..dd0560bca 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryDetailContent.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryDetailContent.kt @@ -3,7 +3,6 @@ package com.hippo.ehviewer.ui.screen import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent -import android.text.TextUtils.TruncateAt.END import androidx.annotation.StringRes import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.MutatorMutex @@ -52,9 +51,9 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.layout.LocalPinnableContainer import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.core.net.toUri -import androidx.core.text.parseAsHtml import androidx.lifecycle.viewModelScope import androidx.paging.Pager import androidx.paging.PagingConfig @@ -101,7 +100,6 @@ import com.hippo.ehviewer.ui.confirmRemoveDownload import com.hippo.ehviewer.ui.destinations.GalleryCommentsScreenDestination import com.hippo.ehviewer.ui.getFavoriteIcon import com.hippo.ehviewer.ui.jumpToReaderByPage -import com.hippo.ehviewer.ui.legacy.CoilImageGetter import com.hippo.ehviewer.ui.main.EhPreviewItem import com.hippo.ehviewer.ui.main.GalleryCommentCard import com.hippo.ehviewer.ui.main.GalleryDetailErrorTip @@ -411,11 +409,10 @@ fun BelowHeader(galleryDetail: GalleryDetail) { onCardClick = ::onNavigateToCommentScene, onUserClick = ::onNavigateToCommentScene, onUrlClick = { if (!jumpToReaderByPage(it, galleryDetail)) if (!navWithUrl(it)) openBrowser(it) }, - ) { - maxLines = 5 - ellipsize = END - text = item.comment.parseAsHtml(imageGetter = CoilImageGetter(this)) - } + maxLines = 5, + overflow = TextOverflow.Ellipsis, + showImage = false, + ) } Box( modifier = Modifier diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/ReadableTime.kt b/app/src/main/kotlin/com/hippo/ehviewer/util/ReadableTime.kt index 62c93cab8..f104c0dbe 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/util/ReadableTime.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/util/ReadableTime.kt @@ -15,6 +15,9 @@ */ package com.hippo.ehviewer.util +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.pluralStringResource +import androidx.compose.ui.res.stringResource import com.hippo.ehviewer.R import java.util.Locale import kotlinx.datetime.Clock @@ -95,38 +98,28 @@ object ReadableTime { } private val resources = appCtx.resources + @Composable fun getTimeAgo(time: Long): String { val nowInstant = Clock.System.now() val now = nowInstant.toEpochMilliseconds() val diff = now - time return when { - (diff < 0 || time <= 0) -> { - resources.getString(R.string.from_the_future) - } - diff < MINUTE_MILLIS -> { - resources.getString(R.string.just_now) - } - diff < 2 * MINUTE_MILLIS -> { - resources.getQuantityString(R.plurals.some_minutes_ago, 1, 1) - } + (diff < 0 || time <= 0) -> stringResource(id = R.string.from_the_future) + diff < MINUTE_MILLIS -> stringResource(id = R.string.just_now) + diff < 2 * MINUTE_MILLIS -> pluralStringResource(R.plurals.some_minutes_ago, 1, 1) diff < 50 * MINUTE_MILLIS -> { val minutes = (diff / MINUTE_MILLIS).toInt() - resources.getQuantityString(R.plurals.some_minutes_ago, minutes, minutes) - } - diff < 90 * MINUTE_MILLIS -> { - resources.getQuantityString(R.plurals.some_hours_ago, 1, 1) + pluralStringResource(R.plurals.some_minutes_ago, minutes, minutes) } + diff < 90 * MINUTE_MILLIS -> pluralStringResource(R.plurals.some_hours_ago, 1, 1) diff < 24 * HOUR_MILLIS -> { val hours = (diff / HOUR_MILLIS).toInt() - resources.getQuantityString(R.plurals.some_hours_ago, hours, hours) + pluralStringResource(R.plurals.some_hours_ago, hours, hours) } diff < 48 * HOUR_MILLIS -> { - resources.getString(R.string.yesterday) - } - diff < WEEK_MILLIS -> { - val days = (diff / DAY_MILLIS).toInt() - resources.getString(R.string.some_days_ago, days) + stringResource(id = R.string.yesterday) } + diff < WEEK_MILLIS -> stringResource(R.string.some_days_ago, (diff / DAY_MILLIS).toInt()) else -> { val timeZone = TimeZone.currentSystemDefault() val nowDate = nowInstant.toLocalDateTime(timeZone).date diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/TextUrl.kt b/app/src/main/kotlin/com/hippo/ehviewer/util/TextUrl.kt deleted file mode 100644 index 7584e1946..000000000 --- a/app/src/main/kotlin/com/hippo/ehviewer/util/TextUrl.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2016 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.hippo.ehviewer.util - -import android.text.Spannable -import android.text.style.URLSpan - -object TextUrl { - private val URL_PATTERN = - Regex("(http|https)://[a-z0-9A-Z%-]+(\\.[a-z0-9A-Z%-]+)+(:\\d{1,5})?(/[a-zA-Z0-9-_~:#@!&',;=%/*.?+$\\[\\]()]+)?/?") - - fun handleTextUrl(content: Spannable): Spannable { - URL_PATTERN.findAll(content).forEach { result -> - val start = result.range.first - val end = result.range.last + 1 - val links = content.getSpans(start, end, URLSpan::class.java) - if (links.isNotEmpty()) { - // There has been URLSpan already, leave it alone - return@forEach - } - val urlSpan = URLSpan(result.groupValues[0]) - content.setSpan(urlSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) - } - return content - } -} diff --git a/app/src/main/kotlin/rikka/core/res/Resources.kt b/app/src/main/kotlin/rikka/core/res/Resources.kt deleted file mode 100644 index 27e839d29..000000000 --- a/app/src/main/kotlin/rikka/core/res/Resources.kt +++ /dev/null @@ -1,13 +0,0 @@ -package rikka.core.res - -import android.content.res.Resources -import androidx.annotation.AttrRes -import androidx.annotation.ColorInt - -@ColorInt -fun Resources.Theme.resolveColor(@AttrRes attrId: Int): Int { - val a = obtainStyledAttributes(intArrayOf(attrId)) - val res = a.getColor(0, 0) - a.recycle() - return res -}