mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-05 19:28:25 +00:00
fix: clear the mechanical Android Lint warnings
Lint reports 874 warnings / 0 errors per amethyst variant. 512 of those are in Crowdin-managed values-*/strings.xml (mostly MissingQuantity — a translator's plural missing a quantity) and are not ours to hand-edit; this takes the ones that are mechanical and behaviour-preserving: - EmptySuperCall (24 in amethyst, plus 2 in commons the amethyst run cannot see): ViewModel.onCleared is documented empty, so drop the super calls. - UseKtx (2): Canvas.withTranslation for the LaTeX drawable, and Bitmap.toDrawable for the map pin — the KTX form CLAUDE.md asks for, and both compile to the same calls. - ConstantLocale (1): CalendarEventListCard held its "MMM" formatter in a file-level val, which captures Locale.getDefault() once — month abbreviations stayed in whatever language was active at class init. The formatter is now cached per locale, which keeps the property the original comment was protecting (a formatter per recompose was 500 allocations while scrolling), and the locale comes from LocalLocale.current.platformLocale so the read is observable: Locale.getDefault() inside a composable is not, and Compose's own NonObservableLocale check rates that an error. - UnusedResources (6): the Android Studio new-project wizard's leftover colors (purple_200, teal_200, teal_700, black, white, transparent), each verified unreferenced from Kotlin and XML. purple_500/700 are in use and stay. - UseTomlInstead (3): the debug-only Compose/Perfetto tracing dependencies move into the version catalog. Same coordinates and versions; the catalog already carries BOM-managed versionless entries. playDebug goes from 874 warnings to 838, still 0 errors. Deliberately left, because each is a decision rather than a cleanup: AppLinkWarning (autoVerify only works if the domains serve a matching assetlinks.json), the 126 unused source strings and 10 PluralsCandidate (both churn the translation surface), GradleDependency / NewerVersionAvailable (dependency bumps need the license check), VectorRaster / VectorPath / IconDensities / IconXmlAndPng (redrawing assets), BatteryLife (the battery-optimization helper working as designed), and InlinedApi / ClickableViewAccessibility / DiscouragedApi / InsecureBaseConfiguration (each needs its surrounding intent read first). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0123kXtseu4X18hL3GMDcdER
This commit is contained in:
@@ -399,9 +399,9 @@ dependencies {
|
||||
// Usage: runtime-enable, then capture a Perfetto trace with the `track_event` data source:
|
||||
// adb shell am broadcast -a androidx.tracing.perfetto.action.ENABLE_TRACING \
|
||||
// -n com.vitorpamplona.amethyst.debug/androidx.tracing.perfetto.TracingReceiver
|
||||
debugImplementation("androidx.compose.runtime:runtime-tracing")
|
||||
debugImplementation("androidx.tracing:tracing-perfetto:1.0.1")
|
||||
debugImplementation("androidx.tracing:tracing-perfetto-binary:1.0.1")
|
||||
debugImplementation(libs.androidx.compose.runtime.tracing)
|
||||
debugImplementation(libs.androidx.tracing.perfetto)
|
||||
debugImplementation(libs.androidx.tracing.perfetto.binary)
|
||||
|
||||
implementation(project(":quartz"))
|
||||
implementation(project(":commons"))
|
||||
|
||||
@@ -40,6 +40,7 @@ import androidx.compose.ui.text.rememberTextMeasurer
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import androidx.compose.ui.unit.TextUnitType
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.graphics.withTranslation
|
||||
import com.vitorpamplona.amethyst.commons.richtext.MathParser
|
||||
import ru.noties.jlatexmath.JLatexMathDrawable
|
||||
|
||||
@@ -130,12 +131,11 @@ fun LatexEquation(
|
||||
Canvas(modifier = equationModifier) {
|
||||
drawIntoCanvas { canvas ->
|
||||
val native = canvas.nativeCanvas
|
||||
val checkpoint = native.save()
|
||||
// Position the icon's baseline on the text baseline within the padded box.
|
||||
native.translate(0f, drawTopPx)
|
||||
drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight)
|
||||
drawable.draw(native)
|
||||
native.restoreToCount(checkpoint)
|
||||
native.withTranslation(y = drawTopPx) {
|
||||
drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight)
|
||||
drawable.draw(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (trailing.isNotEmpty()) {
|
||||
|
||||
+2
-2
@@ -23,7 +23,6 @@ package com.vitorpamplona.amethyst.ui.note.creators.location
|
||||
import android.graphics.ColorFilter
|
||||
import android.graphics.ColorMatrix
|
||||
import android.graphics.ColorMatrixColorFilter
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.view.MotionEvent
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
@@ -36,6 +35,7 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.graphics.drawable.toDrawable
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||
@@ -159,7 +159,7 @@ fun LocationPreviewMap(
|
||||
remember(pinColor, pinEmoji) {
|
||||
if (pinColor != null && pinEmoji != null) {
|
||||
val bitmap = roadEventPinBitmap(pinEmoji, pinColor.toArgb(), context.resources.displayMetrics.density)
|
||||
BitmapDrawable(context.resources, bitmap)
|
||||
bitmap.toDrawable(context.resources)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
@@ -118,6 +118,5 @@ open class UserFeedViewModel(
|
||||
override fun onCleared() {
|
||||
Log.d("Init") { "OnCleared: ${this.javaClass.simpleName}" }
|
||||
bundler.cancel()
|
||||
super.onCleared()
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -2647,7 +2647,6 @@ class AccountViewModel(
|
||||
com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room.activity.NestBridge
|
||||
.clear()
|
||||
feedStates.destroy()
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
fun loadMentions(
|
||||
|
||||
-1
@@ -310,7 +310,6 @@ class AgentConsoleViewModel : ViewModel() {
|
||||
override fun onCleared() {
|
||||
stopObserving()
|
||||
stopWatching()
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
/** One decrypted observer telemetry frame rendered on the Observer tab. */
|
||||
|
||||
-1
@@ -218,7 +218,6 @@ class AgentWorkBoardViewModel : ViewModel() {
|
||||
|
||||
override fun onCleared() {
|
||||
stopWatching()
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
-1
@@ -360,6 +360,5 @@ class BuzzDmListViewModel : ViewModel() {
|
||||
override fun onCleared() {
|
||||
liveJob?.cancel()
|
||||
liveJob = null
|
||||
super.onCleared()
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -137,7 +137,6 @@ class JobBoardViewModel : ViewModel() {
|
||||
|
||||
override fun onCleared() {
|
||||
stopWatching()
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
-1
@@ -258,7 +258,6 @@ class WorkflowRunBoardViewModel : ViewModel() {
|
||||
|
||||
override fun onCleared() {
|
||||
stopWatching()
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+11
-3
@@ -41,6 +41,7 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLocale
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -58,11 +59,15 @@ import java.time.Instant
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
// Thread-safe and hoisted: previously each CalendarDateBadge recompose allocated a new
|
||||
// SimpleDateFormat, which (a) is not thread-safe and (b) created 500 allocations while scrolling.
|
||||
private val MonthShortFormatter: DateTimeFormatter =
|
||||
DateTimeFormatter.ofPattern("MMM", Locale.getDefault())
|
||||
// Cached per locale rather than in a single val that captures the locale once: the month
|
||||
// names have to follow a language the user changes while the app is running.
|
||||
private val monthShortFormatters = ConcurrentHashMap<Locale, DateTimeFormatter>()
|
||||
|
||||
private fun monthShortFormatter(locale: Locale): DateTimeFormatter = monthShortFormatters.getOrPut(locale) { DateTimeFormatter.ofPattern("MMM", locale) }
|
||||
|
||||
@Composable
|
||||
fun CalendarEventListCard(
|
||||
@@ -214,7 +219,10 @@ private fun CalendarDateBadge(startSeconds: Long?) {
|
||||
Instant.ofEpochSecond(startSeconds).atZone(ZoneId.systemDefault()).toLocalDate()
|
||||
}
|
||||
val day = localDate.dayOfMonth.toString()
|
||||
val month = remember(localDate) { MonthShortFormatter.format(localDate).uppercase() }
|
||||
// LocalLocale rather than Locale.getDefault(): the latter is not observable, so a
|
||||
// locale change while the app runs would leave the month name in the old language.
|
||||
val locale = LocalLocale.current.platformLocale
|
||||
val month = remember(localDate, locale) { monthShortFormatter(locale).format(localDate).uppercase() }
|
||||
|
||||
Column(
|
||||
modifier = Modifier.size(width = 52.dp, height = 60.dp),
|
||||
|
||||
-1
@@ -109,7 +109,6 @@ class NewCalendarCollectionViewModel : ViewModel() {
|
||||
|
||||
override fun onCleared() {
|
||||
liveScanJob?.cancel()
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
fun toggle(address: Address) {
|
||||
|
||||
-1
@@ -801,7 +801,6 @@ class ChatNewMessageViewModel :
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
Log.d("Init") { "OnCleared: ${this.javaClass.simpleName}" }
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -1027,7 +1027,6 @@ open class ChannelNewMessageViewModel :
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
Log.d("Init") { "OnCleared: ${this.javaClass.simpleName}" }
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -132,7 +132,6 @@ class ChessViewModelNew(
|
||||
fun clearFocusedGame() = logic.clearFocusedGame()
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
logic.stopPolling()
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -739,7 +739,6 @@ class LongFormPostViewModel :
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
Log.d("Init") { "OnCleared: ${this.javaClass.simpleName}" }
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -612,7 +612,6 @@ open class NewProductViewModel :
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
Log.d("Init") { "OnCleared: ${this.javaClass.simpleName}" }
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -1977,7 +1977,6 @@ open class ShortNotePostViewModel :
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
writingAssistant?.close()
|
||||
writingAssistant = null
|
||||
Log.d("Init") { "OnCleared: ${this.javaClass.simpleName}" }
|
||||
|
||||
-1
@@ -320,7 +320,6 @@ class VoiceReplyViewModel : ViewModel() {
|
||||
|
||||
override fun onCleared() {
|
||||
cancel()
|
||||
super.onCleared()
|
||||
Log.d("Init") { "OnCleared: ${this.javaClass.simpleName}" }
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -102,7 +102,6 @@ class AddToMusicPlaylistViewModel : ViewModel() {
|
||||
|
||||
override fun onCleared() {
|
||||
liveScanJob?.cancel()
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
private suspend fun rescan() {
|
||||
|
||||
-1
@@ -597,7 +597,6 @@ open class NestNewMessageViewModel :
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
Log.d("Init") { "OnCleared: ${this.javaClass.simpleName}" }
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -660,7 +660,6 @@ class NewPublicMessageViewModel :
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
Log.d("Init") { "OnCleared: ${this.javaClass.simpleName}" }
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -196,6 +196,5 @@ class RelayFeedViewModel :
|
||||
|
||||
override fun onCleared() {
|
||||
Log.d("Init") { "OnCleared: ${this.javaClass.simpleName}" }
|
||||
super.onCleared()
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -116,6 +116,5 @@ open class StringFeedViewModel(
|
||||
override fun onCleared() {
|
||||
Log.d("Init") { "OnCleared: ${this.javaClass.simpleName}" }
|
||||
bundler.cancel()
|
||||
super.onCleared()
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -180,7 +180,6 @@ open class NewHlsVideoViewModel : ViewModel() {
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
currentJob?.cancel()
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -459,7 +459,6 @@ class ReloadMintViewModel : ViewModel() {
|
||||
// The pipeline runs on the AccountViewModel scope, not this VM's, so it would
|
||||
// outlive the screen — cancel it when the screen goes away.
|
||||
job?.cancel()
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
-1
@@ -267,7 +267,6 @@ class TopUpMintViewModel : ViewModel() {
|
||||
// The pipeline runs on the AccountViewModel scope, not this VM's, so it would
|
||||
// outlive the screen — cancel it when the screen goes away.
|
||||
job?.cancel()
|
||||
super.onCleared()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -293,7 +293,6 @@ class CashuWalletWizardViewModel : ViewModel() {
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
discovery?.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="purple_200">#FFBB86FC</color>
|
||||
<color name="purple_500">#FF6200EE</color>
|
||||
<color name="purple_700">#FF3700B3</color>
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
<color name="transparent">#00FFFFFF</color>
|
||||
|
||||
<!-- Launch splash / window background. Tracks MaterialTheme's background so the
|
||||
first composed frame does not step to a different colour. See values-night. -->
|
||||
|
||||
-1
@@ -68,6 +68,5 @@ abstract class FeedViewModel(
|
||||
|
||||
override fun onCleared() {
|
||||
Log.d("Init") { "OnCleared: ${this::class.simpleName}" }
|
||||
super.onCleared()
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -838,7 +838,6 @@ class NestViewModel(
|
||||
closed = true
|
||||
teardownBroadcast(BroadcastUiState.Idle, finalCleanup = true)
|
||||
teardown(targetState = ConnectionUiState.Closed, finalCleanup = true)
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
private fun observeSpeakerState(s: NestsSpeaker) {
|
||||
|
||||
@@ -28,6 +28,7 @@ uiautomator = "2.4.0"
|
||||
biometricKtx = "1.4.0-alpha02"
|
||||
coil = "3.6.2"
|
||||
composeBom = "2026.09.00"
|
||||
tracingPerfetto = "1.0.1"
|
||||
composeRuntimeAnnotation = "1.12.1"
|
||||
coreKtx = "1.19.0"
|
||||
datastore = "1.2.1"
|
||||
@@ -136,6 +137,9 @@ androidx-camera-extensions = { module = "androidx.camera:camera-extensions", ver
|
||||
androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "androidxCamera" }
|
||||
androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "androidxCamera" }
|
||||
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
|
||||
androidx-compose-runtime-tracing = { group = "androidx.compose.runtime", name = "runtime-tracing" }
|
||||
androidx-tracing-perfetto = { group = "androidx.tracing", name = "tracing-perfetto", version.ref = "tracingPerfetto" }
|
||||
androidx-tracing-perfetto-binary = { group = "androidx.tracing", name = "tracing-perfetto-binary", version.ref = "tracingPerfetto" }
|
||||
androidx-compose-foundation = { group = "androidx.compose.foundation", name = "foundation" }
|
||||
androidx-compose-runtime-annotation = { group = "androidx.compose.runtime", name = "runtime-annotation", version.ref = "composeRuntimeAnnotation" }
|
||||
androidx-collection = { group = "androidx.collection", name = "collection", version.ref = "androidxCollection" }
|
||||
|
||||
Reference in New Issue
Block a user