From 6fe28520116243eab2c7392c7cba5585f102f9f4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 8 Apr 2026 01:03:18 +0000 Subject: [PATCH] feat: auto-publish key package on MarmotGroupListScreen entry Replace the manual KeyPackage publish button with a LaunchedEffect that auto-publishes if no key package exists yet. The subscription already correctly downloads our own kind:30443 via ownKeyPackageFilter() on home relays, and rotation is handled reactively when Welcome messages are processed. https://claude.ai/code/session_01LhfCp8DHqNVx6mSiYfpQny --- .../marmotGroup/MarmotGroupListScreen.kt | 69 ++++--------------- 1 file changed, 12 insertions(+), 57 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/marmotGroup/MarmotGroupListScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/marmotGroup/MarmotGroupListScreen.kt index 4cc225f10..586723e49 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/marmotGroup/MarmotGroupListScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/marmotGroup/MarmotGroupListScreen.kt @@ -36,8 +36,6 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.Add -import androidx.compose.material.icons.filled.VpnKey -import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.HorizontalDivider @@ -45,8 +43,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold -import androidx.compose.material3.SnackbarHost -import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable @@ -54,12 +50,10 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow @@ -71,8 +65,6 @@ import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.quartz.nip01Core.core.HexKey -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -81,10 +73,6 @@ fun MarmotGroupListScreen( nav: INav, ) { var groupList by remember { mutableStateOf(listOf>()) } - val scope = rememberCoroutineScope() - val snackbarHostState = remember { SnackbarHostState() } - var isPublishing by remember { mutableStateOf(false) } - var hasPublishedKeyPackage by remember { mutableStateOf(accountViewModel.hasPublishedKeyPackage()) } // Load group list LaunchedEffect(Unit) { @@ -98,6 +86,17 @@ fun MarmotGroupListScreen( } } + // Auto-publish KeyPackage if none exists yet + LaunchedEffect(Unit) { + if (!accountViewModel.hasPublishedKeyPackage()) { + try { + accountViewModel.publishMarmotKeyPackage() + } catch (_: Exception) { + // Silently retry on next screen visit + } + } + } + Scaffold( topBar = { TopAppBar( @@ -110,47 +109,8 @@ fun MarmotGroupListScreen( } }, title = { Text("Marmot Groups") }, - actions = { - if (isPublishing) { - CircularProgressIndicator( - modifier = Modifier.padding(12.dp).size(24.dp), - strokeWidth = 2.dp, - strokeCap = StrokeCap.Round, - ) - } else { - IconButton( - onClick = { - isPublishing = true - scope.launch(Dispatchers.IO) { - try { - accountViewModel.publishMarmotKeyPackage() - hasPublishedKeyPackage = true - snackbarHostState.showSnackbar("KeyPackage published successfully") - } catch (e: Exception) { - snackbarHostState.showSnackbar("Failed to publish KeyPackage: ${e.message}") - } finally { - isPublishing = false - } - } - }, - ) { - Icon( - imageVector = Icons.Default.VpnKey, - contentDescription = - if (hasPublishedKeyPackage) "Republish KeyPackage" else "Publish KeyPackage", - tint = - if (hasPublishedKeyPackage) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.onSurfaceVariant - }, - ) - } - } - }, ) }, - snackbarHost = { SnackbarHost(snackbarHostState) }, floatingActionButton = { FloatingActionButton(onClick = { nav.nav(Route.CreateMarmotGroup) }, shape = CircleShape) { Icon(Icons.Default.Add, contentDescription = "Create Group") @@ -168,12 +128,7 @@ fun MarmotGroupListScreen( style = MaterialTheme.typography.titleMedium, ) Text( - text = - if (hasPublishedKeyPackage) { - "Your KeyPackage is published. Waiting for group invitations." - } else { - "Tap the key icon above to publish your KeyPackage and receive invitations." - }, + text = "Create a group or wait for an invitation.", style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.padding(top = 4.dp),