Merge pull request #822 from permissionlesstech/uniform-lists-design

Unify people lists with conversation-row avatar design
This commit is contained in:
callebtc 2026-07-29 19:39:07 +02:00 committed by GitHub
commit c7ced41bcb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 261 additions and 164 deletions

View File

@ -385,7 +385,7 @@ org.jetbrains.kotlin:kotlin-daemon-client:2.4.10=kotlinBuildToolsApiClasspath,ko
org.jetbrains.kotlin:kotlin-daemon-embeddable:2.4.0=kotlinAbiValidationCompatClasspath org.jetbrains.kotlin:kotlin-daemon-embeddable:2.4.0=kotlinAbiValidationCompatClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:2.4.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease org.jetbrains.kotlin:kotlin-daemon-embeddable:2.4.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease
org.jetbrains.kotlin:kotlin-parcelize-compiler:2.4.10=kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease org.jetbrains.kotlin:kotlin-parcelize-compiler:2.4.10=kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease
org.jetbrains.kotlin:kotlin-parcelize-runtime:2.4.10=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jetbrains.kotlin:kotlin-parcelize-runtime:2.4.10=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugRuntimeClasspathCopy,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,releaseRuntimeClasspathCopy
org.jetbrains.kotlin:kotlin-reflect:1.6.10=kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease org.jetbrains.kotlin:kotlin-reflect:1.6.10=kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease
org.jetbrains.kotlin:kotlin-reflect:1.8.21=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher org.jetbrains.kotlin:kotlin-reflect:1.8.21=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher
org.jetbrains.kotlin:kotlin-reflect:2.1.20=debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath org.jetbrains.kotlin:kotlin-reflect:2.1.20=debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
@ -407,7 +407,7 @@ org.jetbrains.kotlin:kotlin-stdlib:1.9.0=unified-test-platform-android-driver-in
org.jetbrains.kotlin:kotlin-stdlib:2.2.10=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action org.jetbrains.kotlin:kotlin-stdlib:2.2.10=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
org.jetbrains.kotlin:kotlin-stdlib:2.2.21=composeMappingProducerClasspath org.jetbrains.kotlin:kotlin-stdlib:2.2.21=composeMappingProducerClasspath
org.jetbrains.kotlin:kotlin-stdlib:2.4.0=kotlinAbiValidationCompatClasspath org.jetbrains.kotlin:kotlin-stdlib:2.4.0=kotlinAbiValidationCompatClasspath
org.jetbrains.kotlin:kotlin-stdlib:2.4.10=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jetbrains.kotlin:kotlin-stdlib:2.4.10=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugRuntimeClasspathCopy,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,releaseRuntimeClasspathCopy
org.jetbrains.kotlin:kotlin-tooling-core:2.4.10=kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath org.jetbrains.kotlin:kotlin-tooling-core:2.4.10=kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath
org.jetbrains.kotlinx:atomicfu-jvm:0.22.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-gradle-work-action,unified-test-platform-launcher org.jetbrains.kotlinx:atomicfu-jvm:0.22.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-gradle-work-action,unified-test-platform-launcher
org.jetbrains.kotlinx:atomicfu-jvm:0.28.0=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jetbrains.kotlinx:atomicfu-jvm:0.28.0=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
@ -429,7 +429,7 @@ org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0=debugAndroidTestCompileClas
org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
org.jetbrains:annotations:13.0=composeMappingProducerClasspath,kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease org.jetbrains:annotations:13.0=composeMappingProducerClasspath,debugRuntimeClasspathCopy,kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease,releaseRuntimeClasspathCopy
org.jetbrains:annotations:23.0.0=androidLintTool,debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher org.jetbrains:annotations:23.0.0=androidLintTool,debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher
org.jspecify:jspecify:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jspecify:jspecify:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
org.jvnet.staxex:stax-ex:1.8.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle org.jvnet.staxex:stax-ex:1.8.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle

View File

@ -281,6 +281,7 @@ private fun GeohashPersonItem(
onTap: () -> Unit onTap: () -> Unit
) { ) {
val palette = LocalBitchatPalette.current val palette = LocalBitchatPalette.current
val colorScheme = MaterialTheme.colorScheme
val statusIconRes = val statusIconRes =
if (isTeleported) R.drawable.ic_spec_teleport if (isTeleported) R.drawable.ic_spec_teleport
@ -298,25 +299,14 @@ private fun GeohashPersonItem(
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
// Exact height, not padding: a row that sizes to its content makes the card change
// height whenever the list reorders.
.height(SheetRowHeight)
.clickable(onClick = onTap) .clickable(onClick = onTap)
.padding(horizontal = SheetRowHorizontal), .padding(horizontal = SheetRowHorizontal, vertical = 10.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Box( PeerAvatar(
modifier = Modifier.size(SheetRowLeadingSlot), name = baseNameRaw,
contentAlignment = Alignment.Center color = baseColor,
) { badge = {
if (hasUnreadDM) {
Icon(
imageVector = Icons.Filled.Email,
contentDescription = stringResource(R.string.cd_unread_message),
modifier = Modifier.size(22.dp),
tint = palette.accentOrange
)
} else {
Icon( Icon(
painter = painterResource(statusIconRes), painter = painterResource(statusIconRes),
contentDescription = if (isTeleported) { contentDescription = if (isTeleported) {
@ -324,13 +314,13 @@ private fun GeohashPersonItem(
} else { } else {
stringResource(R.string.section_on_location) stringResource(R.string.section_on_location)
}, },
modifier = Modifier.size(22.dp), modifier = Modifier.size(13.dp),
tint = baseColor tint = if (isTeleported) palette.accentPurple else colorScheme.primary
) )
} }
} )
Spacer(modifier = Modifier.width(SheetRowLeadingGutter)) Spacer(modifier = Modifier.width(12.dp))
Row( Row(
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
@ -365,5 +355,16 @@ private fun GeohashPersonItem(
) )
} }
} }
if (hasUnreadDM) {
Icon(
imageVector = Icons.Filled.Email,
contentDescription = stringResource(R.string.cd_unread_message),
modifier = Modifier
.padding(start = 8.dp)
.size(18.dp),
tint = palette.accentOrange
)
}
} }
} }

View File

@ -831,18 +831,14 @@ fun PeopleSection(
displayName = displayName, displayName = displayName,
isDirect = isDirectLive, isDirect = isDirectLive,
isWifiAware = peerID in wifiAwarePeerIDs, isWifiAware = peerID in wifiAwarePeerIDs,
isConnected = true,
isSelected = conversationID == selectedPrivatePeer || peerID == selectedPrivatePeer, isSelected = conversationID == selectedPrivatePeer || peerID == selectedPrivatePeer,
isFavorite = isFavorite, isFavorite = isFavorite,
theyFavoritedUs = theyFavoritedUs, theyFavoritedUs = theyFavoritedUs,
isVerified = isVerified, isVerified = isVerified,
hasUnreadDM = combinedHasUnread,
colorScheme = colorScheme, colorScheme = colorScheme,
viewModel = viewModel, viewModel = viewModel,
onItemClick = { onPrivateChatStart(peerID) }, onItemClick = { onPrivateChatStart(peerID) },
onToggleFavorite = {
Log.d("SidebarComponents", "Sidebar toggle favorite: peerID=$peerID, currentFavorite=$isFavorite")
viewModel.toggleFavorite(peerID)
},
unreadCount = if (combinedUnreadCount > 0) combinedUnreadCount else if (combinedHasUnread) 1 else 0, unreadCount = if (combinedUnreadCount > 0) combinedUnreadCount else if (combinedHasUnread) 1 else 0,
showNostrGlobe = false, showNostrGlobe = false,
showHashSuffix = showHash showHashSuffix = showHash
@ -881,18 +877,14 @@ fun PeopleSection(
peerID = favPeerID, peerID = favPeerID,
displayName = dn, displayName = dn,
isDirect = false, isDirect = false,
isConnected = false,
isSelected = conversationID == selectedPrivatePeer || (mappedConnectedPeerID ?: favPeerID) == selectedPrivatePeer, isSelected = conversationID == selectedPrivatePeer || (mappedConnectedPeerID ?: favPeerID) == selectedPrivatePeer,
isFavorite = true, isFavorite = true,
theyFavoritedUs = fav.theyFavoritedUs, theyFavoritedUs = fav.theyFavoritedUs,
isVerified = isVerified, isVerified = isVerified,
hasUnreadDM = hasUnread,
colorScheme = colorScheme, colorScheme = colorScheme,
viewModel = viewModel, viewModel = viewModel,
onItemClick = { onPrivateChatStart(mappedConnectedPeerID ?: favPeerID) }, onItemClick = { onPrivateChatStart(mappedConnectedPeerID ?: favPeerID) },
onToggleFavorite = {
Log.d("SidebarComponents", "Sidebar toggle favorite (offline): peerID=$favPeerID")
viewModel.toggleFavorite(favPeerID)
},
unreadCount = if (unreadCount > 0) unreadCount else if (hasUnread) 1 else 0, unreadCount = if (unreadCount > 0) unreadCount else if (hasUnread) 1 else 0,
showNostrGlobe = (fav.isMutual && fav.peerNostrPublicKey != null), showNostrGlobe = (fav.isMutual && fav.peerNostrPublicKey != null),
showHashSuffix = showHash showHashSuffix = showHash
@ -1263,72 +1255,42 @@ private fun ConversationRow(
), ),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Box( PeerAvatar(
modifier = Modifier.size(42.dp), name = baseNameRaw,
contentAlignment = Alignment.Center, color = assignedColor,
) { badge = {
Box( when {
modifier = Modifier conversation.isConnected -> Icon(
.size(38.dp) painter = painterResource(
.background(assignedColor.copy(alpha = 0.16f), CircleShape), conversationTransportIcon(
contentAlignment = Alignment.Center isReachedOverInternet = false,
) { isWifiAware = isWifiAware,
Text( isDirect = isDirect
text = baseNameRaw )
.trim() ),
.firstOrNull() contentDescription = connectionDescription,
?.uppercase() modifier = Modifier.size(13.dp),
?: "#", tint = colorScheme.primary
style = MaterialTheme.typography.titleMedium.copy( )
fontFamily = BitchatFontFamily,
fontWeight = FontWeight.SemiBold
),
color = assignedColor
)
}
Surface( conversation.transport == DirectMessageTransport.NOSTR -> Icon(
modifier = Modifier painter = painterResource(R.drawable.ic_spec_globe),
.size(18.dp) contentDescription = stringResource(
.align(Alignment.BottomEnd), R.string.offline_reachable_via_nostr
shape = CircleShape, ),
color = colorScheme.surface, modifier = Modifier.size(13.dp),
tonalElevation = 1.dp tint = palette.accentPurple
) { )
Box(contentAlignment = Alignment.Center) {
when {
conversation.isConnected -> Icon(
painter = painterResource(
conversationTransportIcon(
isReachedOverInternet = false,
isWifiAware = isWifiAware,
isDirect = isDirect
)
),
contentDescription = connectionDescription,
modifier = Modifier.size(13.dp),
tint = colorScheme.primary
)
conversation.transport == DirectMessageTransport.NOSTR -> Icon( else -> Icon(
painter = painterResource(R.drawable.ic_spec_globe), imageVector = Icons.Outlined.Circle,
contentDescription = stringResource( contentDescription = stringResource(R.string.offline_not_in_mesh),
R.string.offline_reachable_via_nostr modifier = Modifier.size(11.dp),
), tint = palette.textTertiary
modifier = Modifier.size(13.dp), )
tint = palette.accentPurple
)
else -> Icon(
imageVector = Icons.Outlined.Circle,
contentDescription = stringResource(R.string.offline_not_in_mesh),
modifier = Modifier.size(11.dp),
tint = palette.textTertiary
)
}
} }
} }
} )
Spacer(modifier = Modifier.width(12.dp)) Spacer(modifier = Modifier.width(12.dp))
@ -1559,15 +1521,14 @@ private fun PeerItem(
displayName: String, displayName: String,
isDirect: Boolean, isDirect: Boolean,
isWifiAware: Boolean = false, isWifiAware: Boolean = false,
isConnected: Boolean = true,
isSelected: Boolean, isSelected: Boolean,
isFavorite: Boolean, isFavorite: Boolean,
theyFavoritedUs: Boolean = false, theyFavoritedUs: Boolean = false,
isVerified: Boolean, isVerified: Boolean,
hasUnreadDM: Boolean,
colorScheme: ColorScheme, colorScheme: ColorScheme,
viewModel: ChatViewModel, viewModel: ChatViewModel,
onItemClick: () -> Unit, onItemClick: () -> Unit,
onToggleFavorite: () -> Unit,
unreadCount: Int = 0, unreadCount: Int = 0,
showNostrGlobe: Boolean = false, showNostrGlobe: Boolean = false,
showHashSuffix: Boolean = true showHashSuffix: Boolean = true
@ -1595,57 +1556,47 @@ private fun PeerItem(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.clickable(onClick = onItemClick) .clickable(onClick = onItemClick)
.padding(horizontal = SheetRowHorizontal, vertical = SheetRowVertical), .padding(horizontal = SheetRowHorizontal, vertical = 10.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Box( PeerAvatar(
modifier = Modifier.size(SheetRowLeadingSlot), name = baseNameRaw,
contentAlignment = Alignment.Center color = baseColor,
) { isFavorite = isFavorite,
if (isSelected) { theyFavoritedUs = theyFavoritedUs,
Box( badge = {
modifier = Modifier when {
.size(SheetRowSelectedDot) isConnected -> Icon(
.background(colorScheme.primary, CircleShape) painter = painterResource(
) conversationTransportIcon(
} else if (hasUnreadDM) { isReachedOverInternet = false,
Icon( isWifiAware = isWifiAware,
painter = painterResource(R.drawable.ic_spec_envelope), isDirect = isDirect
contentDescription = stringResource(R.string.cd_unread_message), )
modifier = Modifier.size(PeerRowIconSize), ),
tint = palette.accentOrange contentDescription = connectionDescription,
) modifier = Modifier.size(13.dp),
} else if (showNostrGlobe) { tint = colorScheme.primary
Icon( )
painter = painterResource(R.drawable.ic_spec_globe),
contentDescription = stringResource(R.string.cd_reachable_via_nostr),
modifier = Modifier.size(PeerRowIconSize),
tint = palette.accentPurple
)
} else if (!isDirect && isFavorite) {
Icon(
imageVector = Icons.Outlined.Circle,
contentDescription = stringResource(R.string.cd_offline_favorite),
modifier = Modifier.size(PeerRowIconSize),
tint = palette.textTertiary
)
} else {
Icon(
painter = painterResource(
conversationTransportIcon(
isReachedOverInternet = false,
isWifiAware = isWifiAware,
isDirect = isDirect
)
),
contentDescription = connectionDescription,
modifier = Modifier.size(PeerRowIconSize),
tint = colorScheme.onSurfaceVariant
)
}
}
Spacer(modifier = Modifier.width(SheetRowLeadingGutter)) showNostrGlobe -> Icon(
painter = painterResource(R.drawable.ic_spec_globe),
contentDescription = stringResource(R.string.cd_reachable_via_nostr),
modifier = Modifier.size(13.dp),
tint = palette.accentPurple
)
else -> Icon(
imageVector = Icons.Outlined.Circle,
contentDescription = stringResource(R.string.cd_offline_favorite),
modifier = Modifier.size(11.dp),
tint = palette.textTertiary
)
}
}
)
Spacer(modifier = Modifier.width(12.dp))
Row( Row(
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
@ -1682,21 +1633,18 @@ private fun PeerItem(
} }
} }
Box( UnreadBadge(
modifier = Modifier count = unreadCount,
.size(36.dp) colorScheme = colorScheme,
.clickable(onClick = onToggleFavorite), modifier = Modifier.padding(start = 4.dp)
contentAlignment = Alignment.Center )
) {
// Three-state star (matches private-chat header): grey outline (no relation), if (isSelected) {
// orange outline (they favorited us), filled orange (we favorited them). Box(
Icon( modifier = Modifier
painter = painterResource( .padding(start = 8.dp)
if (isFavorite) R.drawable.ic_spec_star_filled else R.drawable.ic_spec_star .size(SheetRowSelectedDot)
), .background(colorScheme.primary, CircleShape)
contentDescription = if (isFavorite) "Remove from favorites" else "Add to favorites",
modifier = Modifier.size(PeerRowIconSize),
tint = if (isFavorite || theyFavoritedUs) palette.accentOrange else palette.textTertiary
) )
} }
} }

View File

@ -0,0 +1,105 @@
package com.bitchat.android.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.bitchat.android.R
import com.bitchat.android.ui.theme.BitchatFontFamily
import com.bitchat.android.ui.theme.LocalBitchatPalette
internal val PeerAvatarBadgeSize = 18.dp
private val PeerAvatarStarSize = 16.dp
@Composable
internal fun PeerAvatar(
name: String,
color: Color,
modifier: Modifier = Modifier,
isFavorite: Boolean = false,
theyFavoritedUs: Boolean = false,
badge: (@Composable () -> Unit)? = null
) {
val palette = LocalBitchatPalette.current
val colorScheme = MaterialTheme.colorScheme
Box(
modifier = modifier.size(42.dp),
contentAlignment = Alignment.Center
) {
Box(
modifier = Modifier
.size(38.dp)
.background(color.copy(alpha = 0.16f), CircleShape),
contentAlignment = Alignment.Center
) {
Text(
text = name.trim().firstOrNull()?.uppercase() ?: "#",
style = MaterialTheme.typography.titleMedium.copy(
fontFamily = BitchatFontFamily,
fontWeight = FontWeight.SemiBold
),
color = color
)
}
if (badge != null) {
Surface(
modifier = Modifier
.size(PeerAvatarBadgeSize)
.align(Alignment.BottomEnd),
shape = CircleShape,
color = colorScheme.surface,
tonalElevation = 1.dp
) {
Box(contentAlignment = Alignment.Center) {
badge()
}
}
}
if (isFavorite || theyFavoritedUs) {
Surface(
modifier = Modifier
.size(PeerAvatarStarSize)
.align(Alignment.TopEnd),
shape = CircleShape,
color = colorScheme.surface,
tonalElevation = 1.dp
) {
Box(contentAlignment = Alignment.Center) {
Icon(
painter = painterResource(
if (isFavorite) {
R.drawable.ic_spec_star_filled
} else {
R.drawable.ic_spec_star
}
),
contentDescription = stringResource(
if (isFavorite) {
R.string.cd_favorite
} else {
R.string.cd_favorited_you
}
),
modifier = Modifier.size(10.dp),
tint = palette.accentOrange
)
}
}
}
}
}

View File

@ -69,6 +69,8 @@
<!-- Favorites accessibility --> <!-- Favorites accessibility -->
<string name="cd_add_favorite">Add to favorites</string> <string name="cd_add_favorite">Add to favorites</string>
<string name="cd_remove_favorite">Remove from favorites</string> <string name="cd_remove_favorite">Remove from favorites</string>
<string name="cd_favorite">Favorite</string>
<string name="cd_favorited_you">Favorited you</string>
<string name="cd_add_bookmark">Add bookmark</string> <string name="cd_add_bookmark">Add bookmark</string>
<!-- Chat header &amp; accessibility --> <!-- Chat header &amp; accessibility -->

View File

@ -7,11 +7,37 @@ plugins {
alias(libs.plugins.kotlin.compose) apply false alias(libs.plugins.kotlin.compose) apply false
} }
val resolveIdeRuntimeClasspathCopyLocks = tasks.register("resolveIdeRuntimeClasspathCopyLocks") {
group = "build setup"
description = "Resolves Android Studio runtime classpath copies when refreshing lock state."
}
subprojects { subprojects {
dependencyLocking { dependencyLocking {
lockAllConfigurations() lockAllConfigurations()
lockMode.set(LockMode.STRICT) lockMode.set(LockMode.STRICT)
} }
pluginManager.withPlugin("com.android.application") {
val resolveIdeRuntimeClasspathCopyLock = tasks.register("resolveIdeRuntimeClasspathCopyLock") {
group = "build setup"
description = "Resolves this module's Android Studio runtime classpath copies."
notCompatibleWithConfigurationCache("Resolves copied configurations at execution time")
doFirst {
check(gradle.startParameter.isWriteDependencyLocks) {
"$path must be run with --write-locks"
}
}
doLast {
listOf("debugRuntimeClasspath", "releaseRuntimeClasspath").forEach { configurationName ->
configurations.getByName(configurationName).copy().resolve()
}
}
}
resolveIdeRuntimeClasspathCopyLocks.configure {
dependsOn(resolveIdeRuntimeClasspathCopyLock)
}
}
} }
tasks.whenTaskAdded { tasks.whenTaskAdded {

View File

@ -224,11 +224,16 @@ Dependency changes must update and review both the lock state and verification
metadata: metadata:
```bash ```bash
./gradlew testDebugUnitTest lintDebug \ ./gradlew testDebugUnitTest lintDebug resolveIdeRuntimeClasspathCopyLocks \
--write-locks \ --write-locks \
--write-verification-metadata sha256 --write-verification-metadata sha256
``` ```
`resolveIdeRuntimeClasspathCopyLocks` records the transient runtime classpath
copies that Android Studio resolves during model import. Their selected versions
are persisted under the generated copy configuration names while the canonical
debug and release runtime classpaths remain strictly locked.
Generate release lock entries in separate invocations because split APK and AAB Generate release lock entries in separate invocations because split APK and AAB
intermediates cannot coexist: intermediates cannot coexist:
@ -245,6 +250,11 @@ Review every new repository, component, artifact name, version, and checksum.
Do not accept verification metadata generated after an unexplained checksum Do not accept verification metadata generated after an unexplained checksum
failure. failure.
The verification metadata deliberately trusts only IDE documentation and source
attachments (`*-javadoc.jar`, `*-sources.jar`, and Gradle's `*-src.zip`). Android
Studio resolves these outside the build dependency graph, and they are not build
inputs. Compiled artifacts and dependency metadata remain checksum-verified.
When changing Gradle, update the wrapper and independently verify the new When changing Gradle, update the wrapper and independently verify the new
distribution SHA-256. When changing JDK or Android tools, update the exact distribution SHA-256. When changing JDK or Android tools, update the exact
version, archive checksum, and base-image digest together. Native updates follow version, archive checksum, and base-image digest together. Native updates follow

View File

@ -3,6 +3,11 @@
<configuration> <configuration>
<verify-metadata>true</verify-metadata> <verify-metadata>true</verify-metadata>
<verify-signatures>false</verify-signatures> <verify-signatures>false</verify-signatures>
<trusted-artifacts>
<trust file=".*-javadoc[.]jar" regex="true" reason="IDE documentation attachments are not build inputs"/>
<trust file=".*-sources[.]jar" regex="true" reason="IDE source attachments are not build inputs"/>
<trust file=".*-src[.]zip" regex="true" reason="Gradle IDE source attachments are not build inputs"/>
</trusted-artifacts>
</configuration> </configuration>
<components> <components>
<component group="androidx.activity" name="activity" version="1.13.0"> <component group="androidx.activity" name="activity" version="1.13.0">

View File

@ -339,7 +339,7 @@ org.jetbrains.kotlin:kotlin-daemon-client:2.4.10=kotlinBuildToolsApiClasspath,ko
org.jetbrains.kotlin:kotlin-daemon-embeddable:2.4.0=kotlinAbiValidationCompatClasspath org.jetbrains.kotlin:kotlin-daemon-embeddable:2.4.0=kotlinAbiValidationCompatClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:2.4.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease org.jetbrains.kotlin:kotlin-daemon-embeddable:2.4.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease
org.jetbrains.kotlin:kotlin-parcelize-compiler:2.4.10=kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease org.jetbrains.kotlin:kotlin-parcelize-compiler:2.4.10=kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease
org.jetbrains.kotlin:kotlin-parcelize-runtime:2.4.10=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jetbrains.kotlin:kotlin-parcelize-runtime:2.4.10=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugRuntimeClasspathCopy,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,releaseRuntimeClasspathCopy
org.jetbrains.kotlin:kotlin-reflect:1.6.10=kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease org.jetbrains.kotlin:kotlin-reflect:1.6.10=kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease
org.jetbrains.kotlin:kotlin-reflect:1.8.21=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher org.jetbrains.kotlin:kotlin-reflect:1.8.21=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher
org.jetbrains.kotlin:kotlin-reflect:2.1.20=debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath org.jetbrains.kotlin:kotlin-reflect:2.1.20=debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath
@ -359,7 +359,7 @@ org.jetbrains.kotlin:kotlin-stdlib:1.9.0=unified-test-platform-android-driver-in
org.jetbrains.kotlin:kotlin-stdlib:2.2.10=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action org.jetbrains.kotlin:kotlin-stdlib:2.2.10=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action
org.jetbrains.kotlin:kotlin-stdlib:2.2.21=composeMappingProducerClasspath org.jetbrains.kotlin:kotlin-stdlib:2.2.21=composeMappingProducerClasspath
org.jetbrains.kotlin:kotlin-stdlib:2.4.0=kotlinAbiValidationCompatClasspath org.jetbrains.kotlin:kotlin-stdlib:2.4.0=kotlinAbiValidationCompatClasspath
org.jetbrains.kotlin:kotlin-stdlib:2.4.10=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jetbrains.kotlin:kotlin-stdlib:2.4.10=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugRuntimeClasspathCopy,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,releaseRuntimeClasspathCopy
org.jetbrains.kotlin:kotlin-tooling-core:2.4.10=kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath org.jetbrains.kotlin:kotlin-tooling-core:2.4.10=kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath
org.jetbrains.kotlinx:atomicfu-jvm:0.22.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-gradle-work-action,unified-test-platform-launcher org.jetbrains.kotlinx:atomicfu-jvm:0.22.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-gradle-work-action,unified-test-platform-launcher
org.jetbrains.kotlinx:atomicfu:0.22.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-gradle-work-action,unified-test-platform-launcher org.jetbrains.kotlinx:atomicfu:0.22.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-gradle-work-action,unified-test-platform-launcher
@ -379,7 +379,7 @@ org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0=debugUnitTestCompileClasspa
org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
org.jetbrains:annotations:13.0=composeMappingProducerClasspath,kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease org.jetbrains:annotations:13.0=composeMappingProducerClasspath,debugRuntimeClasspathCopy,kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease,releaseRuntimeClasspathCopy
org.jetbrains:annotations:23.0.0=androidLintTool,debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher org.jetbrains:annotations:23.0.0=androidLintTool,debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher
org.jspecify:jspecify:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jspecify:jspecify:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath
org.jvnet.staxex:stax-ex:1.8.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle org.jvnet.staxex:stax-ex:1.8.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle