From 9190e6faa307bc2de4171b6a34b7cb033c7432b9 Mon Sep 17 00:00:00 2001 From: Ren Amamiya Date: Sun, 24 May 2026 08:26:17 +0700 Subject: [PATCH 1/2] fix crash when create room via qr --- .../kotlin/su/reya/coop/screens/ChatScreen.kt | 13 ++++++- .../kotlin/su/reya/coop/screens/HomeScreen.kt | 10 +++--- .../kotlin/su/reya/coop/screens/ScanScreen.kt | 1 - .../kotlin/su/reya/coop/NostrViewModel.kt | 35 ++++++++++--------- 4 files changed, 37 insertions(+), 22 deletions(-) diff --git a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ChatScreen.kt b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ChatScreen.kt index b016fd3..f315106 100644 --- a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ChatScreen.kt +++ b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ChatScreen.kt @@ -68,8 +68,19 @@ fun ChatScreen( val snackbarHostState = LocalSnackbarHostState.current val viewModel = LocalNostrViewModel.current - val room = viewModel.getChatRoom(id) val listState = rememberLazyListState() + val chatRooms by viewModel.chatRooms.collectAsState() + val room = remember(chatRooms, id) { chatRooms.firstOrNull { it.id == id } } + + if (room == null) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + LoadingIndicator() + } + return + } val displayName by remember(room) { room.displayNameFlow(viewModel) }.collectAsState("Loading...") val picture by remember(room) { room.pictureFlow(viewModel) }.collectAsState(null) diff --git a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/HomeScreen.kt b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/HomeScreen.kt index c6ec696..bb840a7 100644 --- a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/HomeScreen.kt +++ b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/HomeScreen.kt @@ -58,7 +58,6 @@ 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.platform.LocalClipboard import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import coop.composeapp.generated.resources.Res @@ -85,7 +84,6 @@ fun HomeScreen( onOpenChat: (Long) -> Unit, onNewChat: () -> Unit, ) { - val clipboard = LocalClipboard.current val navController = LocalNavController.current val snackbarHostState = LocalSnackbarHostState.current val viewModel = LocalNostrViewModel.current @@ -119,8 +117,12 @@ fun HomeScreen( qrResult?.let { result -> runCatching { PublicKey.parse(result) } .onSuccess { pubkey -> - val roomId = viewModel.createChatRoom(listOf(pubkey)) - navController.navigate(Screen.Chat(roomId)) + try { + val roomId = viewModel.createChatRoom(listOf(pubkey)) + navController.navigate(Screen.Chat(roomId)) + } catch (e: Exception) { + e.message?.let { snackbarHostState.showSnackbar(it) } + } } .onFailure { e -> println("Failed to parse QR: ${e.message}") } diff --git a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ScanScreen.kt b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ScanScreen.kt index b351b02..5a21f4a 100644 --- a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ScanScreen.kt +++ b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ScanScreen.kt @@ -76,7 +76,6 @@ fun ScanScreen( ScannerWithPermissions( modifier = Modifier.fillMaxSize(), onScanned = { - println("Scanned: $it"); onResult(it) true }, diff --git a/shared/src/commonMain/kotlin/su/reya/coop/NostrViewModel.kt b/shared/src/commonMain/kotlin/su/reya/coop/NostrViewModel.kt index 3699031..8a36748 100644 --- a/shared/src/commonMain/kotlin/su/reya/coop/NostrViewModel.kt +++ b/shared/src/commonMain/kotlin/su/reya/coop/NostrViewModel.kt @@ -14,6 +14,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.receiveAsFlow +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeoutOrNull @@ -406,20 +407,26 @@ class NostrViewModel( } fun createChatRoom(to: List): Long { - if (nostr.signer.currentUser == null) throw IllegalStateException("User not signed in") - if (to.isEmpty()) throw IllegalArgumentException("At least one recipient is required") + try { + if (nostr.signer.currentUser == null) throw IllegalStateException("User not signed in") + if (to.isEmpty()) throw IllegalArgumentException("At least one recipient is required") - // Construct the rumor event - val rumor = EventBuilder - .privateMsgRumor(to.first(), "") - .tags(to.map { Tag.publicKey(it) }) - .build(nostr.signer.currentUser!!) + // Construct the rumor event + val rumor = EventBuilder + .privateMsgRumor(to.first(), "") + .tags(to.map { Tag.publicKey(it) }) + .build(nostr.signer.currentUser!!) - // Create a room from the rumor event - val room = Room.new(rumor, nostr.signer.currentUser!!) - _chatRooms.value += room + // Create a room from the rumor event + val room = Room.new(rumor, nostr.signer.currentUser!!) + _chatRooms.update { currentRooms -> + currentRooms + room + } - return room.id + return room.id + } catch (e: Exception) { + throw IllegalArgumentException("Failed to create room: ${e.message}") + } } fun getChatRoom(id: Long): Room { @@ -429,11 +436,7 @@ class NostrViewModel( fun getChatRooms() { viewModelScope.launch { - try { - _chatRooms.value = nostr.getChatRooms() ?: emptySet() - } catch (e: Exception) { - showError("Error: ${e.message}") - } + _chatRooms.value = nostr.getChatRooms() ?: emptySet() } } -- 2.49.1 From 93f285f02fdedb09aa596d3ba1231f703d93b2c2 Mon Sep 17 00:00:00 2001 From: Ren Amamiya Date: Sun, 24 May 2026 08:30:04 +0700 Subject: [PATCH 2/2] . --- .../androidMain/kotlin/su/reya/coop/screens/HomeScreen.kt | 4 +++- .../src/commonMain/kotlin/su/reya/coop/NostrViewModel.kt | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/HomeScreen.kt b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/HomeScreen.kt index bb840a7..d1c0d03 100644 --- a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/HomeScreen.kt +++ b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/HomeScreen.kt @@ -110,7 +110,9 @@ fun HomeScreen( ?: remember { mutableStateOf(null) } LaunchedEffect(Unit) { - viewModel.getChatRooms() + if (qrResult == null) { + viewModel.getChatRooms() + } } LaunchedEffect(qrResult) { diff --git a/shared/src/commonMain/kotlin/su/reya/coop/NostrViewModel.kt b/shared/src/commonMain/kotlin/su/reya/coop/NostrViewModel.kt index 8a36748..4f2d0a8 100644 --- a/shared/src/commonMain/kotlin/su/reya/coop/NostrViewModel.kt +++ b/shared/src/commonMain/kotlin/su/reya/coop/NostrViewModel.kt @@ -436,7 +436,13 @@ class NostrViewModel( fun getChatRooms() { viewModelScope.launch { - _chatRooms.value = nostr.getChatRooms() ?: emptySet() + val rooms = nostr.getChatRooms() ?: emptySet() + _chatRooms.update { currentRooms -> + val virtualRooms = currentRooms.filter { local -> + rooms.none { db -> db.id == local.id } + } + rooms + virtualRooms + } } } -- 2.49.1