Merge pull request #1483 from davotoula/reduce-sonar-code-quality-warnings

Reduce sonar code quality warnings
This commit is contained in:
Vitor Pamplona
2025-09-18 14:45:02 -04:00
committed by GitHub
11 changed files with 90 additions and 120 deletions

View File

@@ -33,34 +33,32 @@ import kotlin.time.measureTimedValue
@Suppress("SENSELESS_COMPARISON")
val isDebug = BuildConfig.DEBUG || BuildConfig.BUILD_TYPE == "benchmark"
fun debugState(context: Context) {
// Amethyst.instance.client
// .allSubscriptions()
// .forEach { Log.d("STATE DUMP", "${it.key} ${it.value.filters.joinToString { it.filter.toJson() }}") }
private const val STATE_DUMP_TAG = "STATE DUMP"
fun debugState(context: Context) {
val totalMemoryMb = Runtime.getRuntime().totalMemory() / (1024 * 1024)
val freeMemoryMb = Runtime.getRuntime().freeMemory() / (1024 * 1024)
val maxMemoryMb = Runtime.getRuntime().maxMemory() / (1024 * 1024)
val jvmHeapAllocatedMb = totalMemoryMb - freeMemoryMb
Log.d("STATE DUMP", "Total Heap Allocated: $jvmHeapAllocatedMb/$maxMemoryMb MB")
Log.d(STATE_DUMP_TAG, "Total Heap Allocated: $jvmHeapAllocatedMb/$maxMemoryMb MB")
val nativeHeap = Debug.getNativeHeapAllocatedSize() / (1024 * 1024)
val maxNative = Debug.getNativeHeapSize() / (1024 * 1024)
Log.d("STATE DUMP", "Total Native Heap Allocated: $nativeHeap/$maxNative MB")
Log.d(STATE_DUMP_TAG, "Total Native Heap Allocated: $nativeHeap/$maxNative MB")
val activityManager: ActivityManager? = context.getSystemService()
if (activityManager != null) {
val isLargeHeap = (context.applicationInfo.flags and ApplicationInfo.FLAG_LARGE_HEAP) != 0
val memClass = if (isLargeHeap) activityManager.largeMemoryClass else activityManager.memoryClass
Log.d("STATE DUMP", "Memory Class $memClass MB (largeHeap $isLargeHeap)")
Log.d(STATE_DUMP_TAG, "Memory Class $memClass MB (largeHeap $isLargeHeap)")
}
Log.d(
"STATE DUMP",
STATE_DUMP_TAG,
"Connected Relays: " +
Amethyst.instance.client
.relayStatusFlow()
@@ -71,16 +69,16 @@ fun debugState(context: Context) {
)
Log.d(
"STATE DUMP",
STATE_DUMP_TAG,
"Image Disk Cache ${(Amethyst.instance.diskCache.size) / (1024 * 1024)}/${(Amethyst.instance.diskCache.maxSize) / (1024 * 1024)} MB",
)
Log.d(
"STATE DUMP",
STATE_DUMP_TAG,
"Image Memory Cache ${(Amethyst.instance.memoryCache.size) / (1024 * 1024)}/${(Amethyst.instance.memoryCache.maxSize) / (1024 * 1024)} MB",
)
Log.d(
"STATE DUMP",
STATE_DUMP_TAG,
"Notes: " +
LocalCache.notes.filter { _, it -> it.flowSet != null }.size +
" / " +
@@ -89,7 +87,7 @@ fun debugState(context: Context) {
LocalCache.notes.size(),
)
Log.d(
"STATE DUMP",
STATE_DUMP_TAG,
"Addressables: " +
LocalCache.addressables.filter { _, it -> it.flowSet != null }.size +
" / " +
@@ -98,7 +96,7 @@ fun debugState(context: Context) {
LocalCache.addressables.size(),
)
Log.d(
"STATE DUMP",
STATE_DUMP_TAG,
"Users: " +
LocalCache.users.filter { _, it -> it.flowSet != null }.size +
" / " +
@@ -107,7 +105,7 @@ fun debugState(context: Context) {
LocalCache.users.size(),
)
Log.d(
"STATE DUMP",
STATE_DUMP_TAG,
"Public Chat Channels: " +
LocalCache.publicChatChannels.filter { _, it -> it.flowSet != null }.size +
" / " +
@@ -116,7 +114,7 @@ fun debugState(context: Context) {
LocalCache.publicChatChannels.values().sumOf { it.notes.size() },
)
Log.d(
"STATE DUMP",
STATE_DUMP_TAG,
"Live Chat Channels: " +
LocalCache.liveChatChannels.filter { _, it -> it.flowSet != null }.size +
" / " +
@@ -125,7 +123,7 @@ fun debugState(context: Context) {
LocalCache.liveChatChannels.values().sumOf { it.notes.size() },
)
Log.d(
"STATE DUMP",
STATE_DUMP_TAG,
"Ephemeral Chat Channels: " +
LocalCache.ephemeralChannels.filter { _, it -> it.flowSet != null }.size +
" / " +
@@ -135,7 +133,7 @@ fun debugState(context: Context) {
)
LocalCache.chatroomList.forEach { key, room ->
Log.d(
"STATE DUMP",
STATE_DUMP_TAG,
"Private Chats $key: " +
room.rooms.size() +
" / " +
@@ -143,12 +141,12 @@ fun debugState(context: Context) {
)
}
Log.d(
"STATE DUMP",
STATE_DUMP_TAG,
"Deletion Events: " +
LocalCache.deletionIndex.size(),
)
Log.d(
"STATE DUMP",
STATE_DUMP_TAG,
"Observable Events: " +
LocalCache.observablesByKindAndETag.size +
" / " +
@@ -156,13 +154,13 @@ fun debugState(context: Context) {
)
Log.d(
"STATE DUMP",
STATE_DUMP_TAG,
"Spam: " +
LocalCache.antiSpam.spamMessages.size() + " / " + LocalCache.antiSpam.recentEventIds.size() + " / " + LocalCache.antiSpam.recentAddressables.size(),
)
Log.d(
"STATE DUMP",
STATE_DUMP_TAG,
"Memory used by Events: " +
LocalCache.notes.sumOf { _, note -> note.event?.countMemory() ?: 0 } / (1024 * 1024) +
" MB",
@@ -179,10 +177,10 @@ fun debugState(context: Context) {
.sumByGroup(groupMap = { _, it -> it.event?.kind }, sumOf = { _, it -> it.event?.countMemory()?.toLong() ?: 0L })
qttNotes.toList().sortedByDescending { bytesNotes[it.first] }.forEach { (kind, qtt) ->
Log.d("STATE DUMP", "Kind ${kind.toString().padStart(5,' ')}:\t${qtt.toString().padStart(6,' ')} elements\t${bytesNotes[kind]?.div((1024 * 1024))}MB ")
Log.d(STATE_DUMP_TAG, "Kind ${kind.toString().padStart(5,' ')}:\t${qtt.toString().padStart(6,' ')} elements\t${bytesNotes[kind]?.div((1024 * 1024))}MB ")
}
qttAddressables.toList().sortedByDescending { bytesNotes[it.first] }.forEach { (kind, qtt) ->
Log.d("STATE DUMP", "Kind ${kind.toString().padStart(5,' ')}:\t${qtt.toString().padStart(6,' ')} elements\t${bytesAddressables[kind]?.div((1024 * 1024))}MB ")
Log.d(STATE_DUMP_TAG, "Kind ${kind.toString().padStart(5,' ')}:\t${qtt.toString().padStart(6,' ')} elements\t${bytesAddressables[kind]?.div((1024 * 1024))}MB ")
}
}

View File

@@ -75,8 +75,9 @@ class AccountPreferenceStores(
)
}
fun removeAccount(npub: String) {
file(npub).delete()
fun removeAccount(npub: String): Boolean {
val deleted = file(npub).delete()
storeCache.remove(npub)
return deleted
}
}

View File

@@ -69,8 +69,9 @@ class AccountSecretsEncryptedStores(
serializer = Nip47WalletConnect.Nip47URI::serializer,
)
fun removeAccount(npub: String) {
file(npub).delete()
fun removeAccount(npub: String): Boolean {
val deleted = file(npub).delete()
storeCache.remove(npub)
return deleted
}
}

View File

@@ -27,16 +27,18 @@ import okio.FileNotFoundException
import java.io.FileInputStream
import java.io.InputStreamReader
private const val STACK_TRACE_FILENAME = "stack.trace"
class CrashReportCache(
val appContext: Context,
) {
private fun outputStream() = appContext.openFileOutput("stack.trace", Context.MODE_PRIVATE)
private fun outputStream() = appContext.openFileOutput(STACK_TRACE_FILENAME, Context.MODE_PRIVATE)
private fun deleteReport() = appContext.deleteFile("stack.trace")
private fun deleteReport() = appContext.deleteFile(STACK_TRACE_FILENAME)
private fun inputStreamOrNull(): FileInputStream? =
try {
appContext.openFileInput("stack.trace")
appContext.openFileInput(STACK_TRACE_FILENAME)
} catch (_: FileNotFoundException) {
null
}

View File

@@ -52,13 +52,12 @@ import com.vitorpamplona.quartz.utils.TimeUtils
import java.math.BigDecimal
import kotlin.coroutines.cancellation.CancellationException
private const val TAG = "EventNotificationConsumer"
private const val ACCOUNT_QUERY_PARAM = "?account="
class EventNotificationConsumer(
private val applicationContext: Context,
) {
companion object {
const val TAG = "EventNotificationConsumer"
}
suspend fun consume(event: GiftWrapEvent) {
Log.d(TAG, "New Notification Arrived")
@@ -210,7 +209,7 @@ class EventNotificationConsumer(
val user = chatNote.author?.toBestDisplayName() ?: ""
val userPicture = chatNote.author?.profilePicture()
val noteUri =
chatNote.toNEvent() + "?account=" +
chatNote.toNEvent() + ACCOUNT_QUERY_PARAM +
account.signer.pubKey
.hexToByteArray()
.toNpub()
@@ -255,7 +254,7 @@ class EventNotificationConsumer(
val user = chatNote.author?.toBestDisplayName() ?: ""
val userPicture = chatNote.author?.profilePicture()
val noteUri =
chatNote.toNEvent() + "?account=" +
chatNote.toNEvent() + ACCOUNT_QUERY_PARAM +
account.signer.pubKey
.hexToByteArray()
.toNpub()
@@ -297,7 +296,7 @@ class EventNotificationConsumer(
val user = note.author?.toBestDisplayName() ?: ""
val userPicture = note.author?.profilePicture()
val noteUri =
note.toNEvent() + "?account=" +
note.toNEvent() + ACCOUNT_QUERY_PARAM +
account.signer.pubKey
.hexToByteArray()
.toNpub()
@@ -324,17 +323,17 @@ class EventNotificationConsumer(
signer: NostrSigner,
): String? {
val event = note.event
when (event) {
return when (event) {
is PrivateDmEvent -> {
return event.decryptContent(signer)
event.decryptContent(signer)
}
is LnZapRequestEvent -> {
return decryptZapContentAuthor(event, signer)?.content
decryptZapContentAuthor(event, signer)?.content
}
else -> {
return event?.content
event?.content
}
}
}
@@ -402,7 +401,7 @@ class EventNotificationConsumer(
}
val userPicture = senderInfo.first.profilePicture()
val noteUri =
"notifications?account=" +
"notifications$ACCOUNT_QUERY_PARAM" +
account.signer.pubKey
.hexToByteArray()
.toNpub()
@@ -437,7 +436,7 @@ class EventNotificationConsumer(
val userPicture = senderInfo.first.profilePicture()
val noteUri =
"notifications?account=" +
"notifications$ACCOUNT_QUERY_PARAM" +
account.signer.pubKey
.hexToByteArray()
.toNpub()

View File

@@ -20,27 +20,16 @@
*/
package com.vitorpamplona.amethyst.ui.navigation.navs
import androidx.compose.material3.DrawerState
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlin.reflect.KClass
class ObservableNav(
val sourceNav: INav,
private val sourceNav: INav,
override val navigationScope: CoroutineScope,
val onBeforeNavigate: () -> Unit,
) : INav {
override val drawerState: DrawerState = sourceNav.drawerState
override fun closeDrawer() {
sourceNav.closeDrawer()
}
override fun openDrawer() {
sourceNav.openDrawer()
}
) : INav by sourceNav {
override fun nav(route: Route) {
navigationScope.launch {
onBeforeNavigate()
@@ -71,11 +60,11 @@ class ObservableNav(
override fun <T : Route> popUpTo(
route: Route,
upToClass: KClass<T>,
klass: KClass<T>,
) {
navigationScope.launch {
onBeforeNavigate()
}
sourceNav.popUpTo(route, upToClass)
sourceNav.popUpTo(route, klass)
}
}

View File

@@ -72,8 +72,10 @@ import com.vitorpamplona.amethyst.ui.theme.ripple24dp
import com.vitorpamplona.amethyst.ui.theme.warningColorOnSecondSurface
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
private const val DAMUS_RELAY_URL = "wss://relay.damus.io"
@Composable
public fun RelayBadgesHorizontal(
fun RelayBadgesHorizontal(
baseNote: Note,
accountViewModel: AccountViewModel,
nav: INav,
@@ -162,24 +164,24 @@ fun RenderRelayIconPreview() {
ThemeComparisonColumn {
Row {
RenderRelayIcon(
displayUrl = "wss://relay.damus.io",
iconUrl = "wss://relay.damus.io",
displayUrl = DAMUS_RELAY_URL,
iconUrl = DAMUS_RELAY_URL,
loadProfilePicture = true,
pingInMs = 100,
loadRobohash = true,
iconModifier = LargeRelayIconModifier,
)
RenderRelayIcon(
displayUrl = "wss://relay.damus.io",
iconUrl = "wss://relay.damus.io",
displayUrl = DAMUS_RELAY_URL,
iconUrl = DAMUS_RELAY_URL,
loadProfilePicture = true,
pingInMs = 300,
loadRobohash = true,
iconModifier = LargeRelayIconModifier,
)
RenderRelayIcon(
displayUrl = "wss://relay.damus.io",
iconUrl = "wss://relay.damus.io",
displayUrl = DAMUS_RELAY_URL,
iconUrl = DAMUS_RELAY_URL,
loadProfilePicture = true,
pingInMs = 500,
loadRobohash = true,

View File

@@ -28,9 +28,12 @@ import com.vitorpamplona.quartz.utils.TimeUtils
import java.text.SimpleDateFormat
import java.util.Locale
private const val YEAR_DATE_FORMAT = "MMM dd, yyyy"
private const val MONTH_DATE_FORMAT = "MMM dd"
var locale = Locale.getDefault()
var yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale)
var monthFormatter = SimpleDateFormat("MMM dd", locale)
var yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale)
var monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale)
fun timeAgo(
time: Long?,
@@ -46,8 +49,8 @@ fun timeAgo(
if (locale != Locale.getDefault()) {
locale = Locale.getDefault()
yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale)
monthFormatter = SimpleDateFormat("MMM dd", locale)
yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale)
monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale)
}
"" + yearFormatter.format(time * 1000)
@@ -55,8 +58,8 @@ fun timeAgo(
// Dec 12
if (locale != Locale.getDefault()) {
locale = Locale.getDefault()
yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale)
monthFormatter = SimpleDateFormat("MMM dd", locale)
yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale)
monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale)
}
"" + monthFormatter.format(time * 1000)
@@ -86,8 +89,8 @@ fun timeAgoNoDot(
if (locale != Locale.getDefault()) {
locale = Locale.getDefault()
yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale)
monthFormatter = SimpleDateFormat("MMM dd", locale)
yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale)
monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale)
}
yearFormatter.format(time * 1000)
@@ -95,8 +98,8 @@ fun timeAgoNoDot(
// Dec 12
if (locale != Locale.getDefault()) {
locale = Locale.getDefault()
yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale)
monthFormatter = SimpleDateFormat("MMM dd", locale)
yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale)
monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale)
}
monthFormatter.format(time * 1000)
@@ -127,8 +130,8 @@ fun dateFormatter(
if (locale != Locale.getDefault()) {
locale = Locale.getDefault()
yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale)
monthFormatter = SimpleDateFormat("MMM dd", locale)
yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale)
monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale)
}
yearFormatter.format(time * 1000)
@@ -136,8 +139,8 @@ fun dateFormatter(
// Dec 12
if (locale != Locale.getDefault()) {
locale = Locale.getDefault()
yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale)
monthFormatter = SimpleDateFormat("MMM dd", locale)
yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale)
monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale)
}
monthFormatter.format(time * 1000)

View File

@@ -59,6 +59,8 @@ import com.vitorpamplona.amethyst.ui.theme.chatDraftBackground
import com.vitorpamplona.amethyst.ui.theme.mediumImportanceLink
import com.vitorpamplona.amethyst.ui.theme.messageBubbleLimits
private const val RELAYS_AND_ACTIONS_TEXT = "Relays and Actions"
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ChatBubbleLayout(
@@ -205,7 +207,7 @@ private fun BubblePreview() {
},
)
},
detailRow = { Text("Relays and Actions") },
detailRow = { Text(RELAYS_AND_ACTIONS_TEXT) },
) { bgColor ->
Text("This is my note")
}
@@ -239,7 +241,7 @@ private fun BubblePreview() {
},
)
},
detailRow = { Text("Relays and Actions") },
detailRow = { Text(RELAYS_AND_ACTIONS_TEXT) },
) { bgColor ->
Text("This is a very long long loong note")
}
@@ -273,7 +275,7 @@ private fun BubblePreview() {
},
)
},
detailRow = { Text("Relays and Actions") },
detailRow = { Text(RELAYS_AND_ACTIONS_TEXT) },
) { bgColor ->
Text("This is a draft note")
}
@@ -307,7 +309,7 @@ private fun BubblePreview() {
},
)
},
detailRow = { Text("Relays and Actions") },
detailRow = { Text(RELAYS_AND_ACTIONS_TEXT) },
) { bgColor ->
Text("Short note")
}

View File

@@ -20,20 +20,16 @@
*/
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.rooms.twopane
import androidx.compose.material3.DrawerState
import androidx.compose.runtime.mutableStateOf
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlin.reflect.KClass
class TwoPaneNav(
val nav: INav,
private val nav: INav,
override val navigationScope: CoroutineScope,
) : INav {
override val drawerState: DrawerState = nav.drawerState
) : INav by nav {
val innerNav = mutableStateOf<Route?>(null)
override fun nav(route: Route) {
@@ -56,27 +52,4 @@ class TwoPaneNav(
}
}
}
override fun newStack(route: Route) {
nav.newStack(route)
}
override fun popBack() {
nav.popBack()
}
override fun <T : Route> popUpTo(
route: Route,
klass: KClass<T>,
) {
nav.popUpTo<T>(route, klass)
}
override fun closeDrawer() {
nav.closeDrawer()
}
override fun openDrawer() {
nav.openDrawer()
}
}

View File

@@ -33,16 +33,16 @@ import kotlinx.collections.immutable.toImmutableMap
import kotlinx.coroutines.flow.MutableStateFlow
@Immutable
abstract class Card {
abstract fun createdAt(): Long
interface Card {
fun createdAt(): Long
abstract fun id(): String
fun id(): String
}
@Immutable
class BadgeCard(
val note: Note,
) : Card() {
) : Card {
override fun createdAt(): Long = note.createdAt() ?: 0L
override fun id() = note.idHex
@@ -51,7 +51,7 @@ class BadgeCard(
@Immutable
class NoteCard(
val note: Note,
) : Card() {
) : Card {
override fun createdAt(): Long = note.createdAt() ?: 0L
override fun id() = note.idHex
@@ -61,7 +61,7 @@ class NoteCard(
class ZapUserSetCard(
val user: User,
val zapEvents: ImmutableList<CombinedZap>,
) : Card() {
) : Card {
val createdAt = zapEvents.maxOfOrNull { it.createdAt() ?: 0L } ?: 0L
override fun createdAt(): Long = createdAt
@@ -75,7 +75,7 @@ class MultiSetCard(
val boostEvents: ImmutableList<Note>,
val likeEvents: ImmutableList<Note>,
val zapEvents: ImmutableList<CombinedZap>,
) : Card() {
) : Card {
val maxCreatedAt =
maxOf(
zapEvents.maxOfOrNull { it.createdAt() ?: 0L } ?: 0L,
@@ -108,7 +108,7 @@ class MultiSetCard(
@Immutable
class MessageSetCard(
val note: Note,
) : Card() {
) : Card {
override fun createdAt(): Long = note.createdAt() ?: 0L
override fun id() = note.idHex