Merge pull request #4250 from vitorpamplona/claude/wonderful-einstein-0lg4k8

Fix Material 3 API deprecations and test GC issues
This commit is contained in:
Vitor Pamplona
2026-09-28 11:13:12 -04:00
committed by GitHub
6 changed files with 35 additions and 15 deletions
@@ -30,8 +30,9 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.SheetValue
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.material3.rememberBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
@@ -82,7 +83,11 @@ fun QrImageCodeChooser(
onPick: (ScannedPayload) -> Unit,
onDismiss: () -> Unit,
) {
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
val sheetState =
rememberBottomSheetState(
initialValue = SheetValue.Hidden,
enabledValues = setOf(SheetValue.Hidden, SheetValue.Expanded),
)
ModalBottomSheet(onDismissRequest = onDismiss, sheetState = sheetState) {
Column(
@@ -30,9 +30,10 @@ import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.SheetValue
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.material3.rememberBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
@@ -73,7 +74,11 @@ fun ScanOutcomeSheet(
onOpenLink: (String) -> Unit,
onCopy: (String) -> Unit,
) {
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
val sheetState =
rememberBottomSheetState(
initialValue = SheetValue.Hidden,
enabledValues = setOf(SheetValue.Hidden, SheetValue.Expanded),
)
ModalBottomSheet(onDismissRequest = onDismiss, sheetState = sheetState) {
Column(
@@ -88,7 +88,7 @@ fun OutlinedThinPaddingTextField(
shape: Shape = OutlinedTextFieldDefaults.shape,
colors: TextFieldColors = OutlinedTextFieldDefaults.colors(),
contentPadding: PaddingValues =
OutlinedTextFieldDefaults.contentPadding(
OutlinedTextFieldDefaults.contentPaddingWithoutLabel(
start = 10.dp,
top = 12.dp,
end = 10.dp,
@@ -78,7 +78,7 @@ fun SlimListItem(
) {
val decoratedHeadlineContent: @Composable () -> Unit = {
ProvideTextStyleFromToken(
colors.headlineColor,
colors.contentColor,
MaterialTheme.typography.bodyLarge,
headlineContent,
)
@@ -88,7 +88,7 @@ fun SlimListItem(
{
Box(SupportingContentTopPadding) {
ProvideTextStyleFromToken(
colors.supportingTextColor,
colors.supportingContentColor,
MaterialTheme.typography.bodyMedium,
it,
)
@@ -99,7 +99,7 @@ fun SlimListItem(
overlineContent?.let {
{
ProvideTextStyleFromToken(
colors.overlineColor,
colors.overlineContentColor,
MaterialTheme.typography.labelSmall,
it,
)
@@ -110,7 +110,7 @@ fun SlimListItem(
{
Box(LeadingContentEndPadding) {
CompositionLocalProvider(
LocalContentColor provides colors.leadingIconColor,
LocalContentColor provides colors.leadingContentColor,
content = it,
)
}
@@ -121,7 +121,7 @@ fun SlimListItem(
{
Box(TrailingContentStartPadding) {
ProvideTextStyleFromToken(
colors.trailingIconColor,
colors.trailingContentColor,
MaterialTheme.typography.labelSmall,
content = it,
)
@@ -80,7 +80,7 @@ class SnoObjectCardRenderTest {
MaterialTheme(colorScheme = darkColorScheme()) {
Surface(color = MaterialTheme.colorScheme.surface) {
Column(Modifier.fillMaxSize()) {
SnoObjectCard(payload = payload!!, eventId = "render-test", onClick = {})
SnoObjectCard(payload = payload, eventId = "render-test", onClick = {})
}
}
}
@@ -122,7 +122,7 @@ class SnoObjectCardRenderTest {
MaterialTheme(colorScheme = darkColorScheme()) {
Surface(color = MaterialTheme.colorScheme.surface) {
SnoObjectViewer(
payload = payload!!,
payload = payload,
eventId = "viewer-test",
modifier = Modifier.size(200.dp),
)
@@ -36,6 +36,14 @@ import kotlin.test.assertNull
* kind:10050 routing + `UserContext` wiring, `route` dropped kind 10050 and the
* User model was backed by a map nothing populated, so every recipient looked
* "unreachable via NIP-17" until an indexer fan-out ran.
*
* Each test takes the [com.vitorpamplona.amethyst.commons.model.User] *before*
* consuming and keeps it. The cache's users and addressable notes live in a
* weakly-valued `LargeSoftCache`, so a note nothing references can be collected
* between two `consume` calls — taking the stored kind 10050 with it and letting
* a stale list land on a fresh, empty note. The app keeps a DM recipient's `User`
* alive while it is in use, and a `User` strongly holds its `dmRelayListNote`;
* the tests do the same, otherwise a GC mid-test made them fail on CI.
*/
class DesktopDmRelayListConsumeTest {
private val relayUrl = NormalizedRelayUrl("wss://relay.test/")
@@ -56,11 +64,11 @@ class DesktopDmRelayListConsumeTest {
fun `consume routes kind 10050 into the User model`() {
val cache = DesktopLocalCache()
val signer = NostrSignerSync(KeyPair())
val user = cache.getOrCreateUser(signer.pubKey)
val event = signedDmRelayList(signer)
cache.consume(event, relayUrl)
val user = cache.getOrCreateUser(signer.pubKey)
assertEquals(dmInbox, user.dmInboxRelaysStrict())
}
@@ -76,25 +84,27 @@ class DesktopDmRelayListConsumeTest {
fun `a newer kind 10050 replaces an older one`() {
val cache = DesktopLocalCache()
val signer = NostrSignerSync(KeyPair())
val user = cache.getOrCreateUser(signer.pubKey)
cache.consume(signedDmRelayList(signer, dmInbox, createdAt = 1_700_000_000), relayUrl)
val newerRelays = listOf(NormalizedRelayUrl("wss://moved.example/"))
cache.consume(signedDmRelayList(signer, newerRelays, createdAt = 1_700_000_100), relayUrl)
assertEquals(newerRelays, cache.getOrCreateUser(signer.pubKey).dmInboxRelaysStrict())
assertEquals(newerRelays, user.dmInboxRelaysStrict())
}
@Test
fun `an older kind 10050 does not overwrite a newer one`() {
val cache = DesktopLocalCache()
val signer = NostrSignerSync(KeyPair())
val user = cache.getOrCreateUser(signer.pubKey)
cache.consume(signedDmRelayList(signer, dmInbox, createdAt = 1_700_000_100), relayUrl)
val staleRelays = listOf(NormalizedRelayUrl("wss://stale.example/"))
cache.consume(signedDmRelayList(signer, staleRelays, createdAt = 1_700_000_000), relayUrl)
assertEquals(dmInbox, cache.getOrCreateUser(signer.pubKey).dmInboxRelaysStrict())
assertEquals(dmInbox, user.dmInboxRelaysStrict())
}
}