From 3943e2baab385a85e6d06bc5a8167b4bea29839d Mon Sep 17 00:00:00 2001 From: Ren Amamiya Date: Sun, 28 Jun 2026 02:06:57 +0000 Subject: [PATCH] chore: remove force unwraps (#30) Reviewed-on: https://git.reya.su/reya/coop-mobile/pulls/30 --- .../kotlin/su/reya/coop/screens/ChatScreen.kt | 12 +++++++--- .../kotlin/su/reya/coop/screens/HomeScreen.kt | 2 +- .../commonMain/kotlin/su/reya/coop/Nostr.kt | 23 ++++++++++++------- .../kotlin/su/reya/coop/NostrViewModel.kt | 11 +++++---- 4 files changed, 32 insertions(+), 16 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 0e7db46..27d308e 100644 --- a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ChatScreen.kt +++ b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ChatScreen.kt @@ -59,6 +59,7 @@ import coop.composeapp.generated.resources.ic_arrow_back import coop.composeapp.generated.resources.ic_cancel import coop.composeapp.generated.resources.ic_check_circle import coop.composeapp.generated.resources.ic_send +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.launch import org.jetbrains.compose.resources.painterResource import rust.nostr.sdk.PublicKey @@ -103,8 +104,13 @@ fun ChatScreen(id: Long, screening: Boolean = false) { return } - val displayName by remember(room) { room!!.nameFlow(viewModel) }.collectAsStateWithLifecycle("Loading...") - val picture by remember(room) { room!!.pictureFlow(viewModel) }.collectAsStateWithLifecycle(null) + val displayName by remember(room) { + room?.nameFlow(viewModel) ?: flowOf("Loading...") + }.collectAsStateWithLifecycle("Loading...") + + val picture by remember(room) { + room?.pictureFlow(viewModel) ?: flowOf(null) + }.collectAsStateWithLifecycle(null) var text by remember { mutableStateOf("") } var loading by remember { mutableStateOf(true) } @@ -161,7 +167,7 @@ fun ChatScreen(id: Long, screening: Boolean = false) { Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier.clickable { - room!!.members.firstOrNull()?.let { pubkey -> + room?.members?.firstOrNull()?.let { pubkey -> navigator.navigate(Screen.Profile(pubkey.toBech32())) } } 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 b1dbf27..b18e45f 100644 --- a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/HomeScreen.kt +++ b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/HomeScreen.kt @@ -741,7 +741,7 @@ fun ChatRoom(room: Room, onClick: () -> Unit) { supportingContent = { if (!room.lastMessage.isNullOrBlank()) { Text( - text = room.lastMessage!!, + text = room.lastMessage ?: "", style = MaterialTheme.typography.bodyMedium, overflow = TextOverflow.Ellipsis, maxLines = 1, diff --git a/shared/src/commonMain/kotlin/su/reya/coop/Nostr.kt b/shared/src/commonMain/kotlin/su/reya/coop/Nostr.kt index f6b81ee..9ec72f5 100644 --- a/shared/src/commonMain/kotlin/su/reya/coop/Nostr.kt +++ b/shared/src/commonMain/kotlin/su/reya/coop/Nostr.kt @@ -670,6 +670,8 @@ class Nostr { suspend fun setMsgRelays(urls: List) { try { + + val event = EventBuilder.nip17RelayList(urls).finalizeAsync(signer) client?.sendEvent( @@ -678,8 +680,12 @@ class Nostr { ackPolicy = AckPolicy.none(), ) + val currentUser = + signer.getPublicKeyAsync() ?: throw IllegalStateException("User not signed in") + val kind = Kind.fromStd(KindStandard.INBOX_RELAYS) - val filter = Filter().kind(kind).author(signer.currentUser!!).limit(1u) + val filter = Filter().kind(kind).author(currentUser).limit(1u) + val target = ReqTarget.auto(listOf(filter)) val opts = SubscribeAutoCloseOptions().exitPolicy(ReqExitPolicy.ExitOnEose) @@ -833,9 +839,8 @@ class Nostr { ) stream?.next()?.let { res -> - if (res.event != null) { - connectMsgRelays(res.event!!) - } + val event = res.event ?: return@let + connectMsgRelays(event) } } } catch (e: Exception) { @@ -919,7 +924,10 @@ class Nostr { if (output != null) { // Keep track of sent events sentEvents[output.id] = emptyList() - if (rumor.id() != null) rumorMap[rumor.id()!!] = output.id + + // Keep track of rumor IDs + val id = rumor.id() ?: throw IllegalStateException("Rumor ID is null") + rumorMap[id] = output.id // Collect failed outputs output.failed.forEach { (relayUrl, reason) -> @@ -979,9 +987,8 @@ class Nostr { // Keep searching until the stream is closed or timeout stream?.next()?.let { event -> - if (event.event != null) { - results.add(event.event!!.author()) - } + val event = event.event ?: return@let + results.add(event.author()) } return results diff --git a/shared/src/commonMain/kotlin/su/reya/coop/NostrViewModel.kt b/shared/src/commonMain/kotlin/su/reya/coop/NostrViewModel.kt index fee7464..87e01a5 100644 --- a/shared/src/commonMain/kotlin/su/reya/coop/NostrViewModel.kt +++ b/shared/src/commonMain/kotlin/su/reya/coop/NostrViewModel.kt @@ -436,8 +436,9 @@ class NostrViewModel( try { val avatarUrl = picture?.let { blossomUpload(it, contentType ?: "image/jpeg") } val newMetadata = nostr.updateProfile(name, bio, avatarUrl) + val currentUser = nostr.signer.getPublicKeyAsync() ?: throw Exception("User not found") // Update the metadata state after successfully published - updateMetadata(nostr.signer.currentUser!!, newMetadata) + updateMetadata(currentUser, newMetadata) // Update local state _isBusy.value = false } catch (e: Exception) { @@ -581,7 +582,8 @@ class NostrViewModel( suspend fun currentUserRelayList(): Map { try { - return nostr.getRelayList(nostr.signer.currentUser!!) + val currentUser = nostr.signer.getPublicKeyAsync() ?: throw Exception("User not found") + return nostr.getRelayList(currentUser) } catch (e: Exception) { showError("Error: ${e.message}") return emptyMap() @@ -626,7 +628,8 @@ class NostrViewModel( suspend fun currentUserMsgRelayList(): List { try { - return nostr.getMsgRelays(nostr.signer.currentUser!!) + val currentUser = nostr.signer.getPublicKeyAsync() ?: throw Exception("User not found") + return nostr.getMsgRelays(currentUser) } catch (e: Exception) { showError("Error: ${e.message}") return emptyList() @@ -710,7 +713,7 @@ class NostrViewModel( if (nostr.signer.currentUser == null) throw IllegalStateException("User not signed in") if (to.isEmpty()) throw IllegalArgumentException("At least one recipient is required") - val currentUser = nostr.signer.currentUser!! + val currentUser = nostr.signer.currentUser ?: throw Exception("User not found") // Construct the rumor event val rumor = EventBuilder(Kind.fromStd(KindStandard.PRIVATE_DIRECT_MESSAGE), "")