From fcc30157bb3e1d414f6298809c1263e6c1d54c51 Mon Sep 17 00:00:00 2001 From: Ren Amamiya Date: Wed, 15 Jul 2026 17:02:55 +0700 Subject: [PATCH] Revert "clean up chat screen" This reverts commit 9c9d9ae88246f36f7dc36595442290d96dae75b1. --- .../androidMain/kotlin/su/reya/coop/App.kt | 47 +++++++------------ .../su/reya/coop/screens/chat/ChatScreen.kt | 41 +++++++++++----- .../commonMain/kotlin/su/reya/coop/Room.kt | 2 +- .../coop/viewmodel/ChatScreenViewModel.kt | 20 ++------ 4 files changed, 53 insertions(+), 57 deletions(-) diff --git a/composeApp/src/androidMain/kotlin/su/reya/coop/App.kt b/composeApp/src/androidMain/kotlin/su/reya/coop/App.kt index 7af97d1..c5ae4df 100644 --- a/composeApp/src/androidMain/kotlin/su/reya/coop/App.kt +++ b/composeApp/src/androidMain/kotlin/su/reya/coop/App.kt @@ -6,14 +6,11 @@ import android.os.Build import androidx.activity.ComponentActivity import androidx.activity.compose.BackHandler import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.MaterialExpressiveTheme import androidx.compose.material3.MotionScheme import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.Text import androidx.compose.material3.Typography import androidx.compose.material3.darkColorScheme import androidx.compose.material3.dynamicDarkColorScheme @@ -27,8 +24,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.runtime.staticCompositionLocalOf -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.core.util.Consumer import androidx.lifecycle.ViewModel @@ -235,34 +230,26 @@ fun App( NewIdentityScreen(accountViewModel) } entry { key -> - val initialRoom = remember(key.id) { chatRepository.getChatRoom(key.id) } - - if (initialRoom != null) { - val factory = remember(initialRoom) { - object : ViewModelProvider.Factory { - override fun create(modelClass: Class): T { - return ChatScreenViewModel( - initialRoom, - key.screening, - accountRepository, - chatRepository - ) as T - } + val factory = remember(key) { + object : ViewModelProvider.Factory { + override fun create(modelClass: Class): T { + @Suppress("UNCHECKED_CAST") + return ChatScreenViewModel( + key.id, + key.screening, + accountRepository, + chatRepository + ) as T } } - ChatScreen( - viewModel( - key = key.id.toString(), - factory = factory - ), - accountViewModel - ) - } else { - // Handle the rare case where the room isn't in DB (e.g., invalid deep link) - Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - Text("Room not found") - } } + ChatScreen( + viewModel( + key = key.id.toString(), + factory = factory + ), + accountViewModel + ) } entry { NewChatScreen(accountViewModel, chatViewModel) diff --git a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/chat/ChatScreen.kt b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/chat/ChatScreen.kt index cf36094..1e7fc78 100644 --- a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/chat/ChatScreen.kt +++ b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/chat/ChatScreen.kt @@ -94,11 +94,12 @@ import rust.nostr.sdk.UnsignedEvent import su.reya.coop.LocalNavigator import su.reya.coop.LocalProfileCache import su.reya.coop.LocalSnackbarHostState +import su.reya.coop.Room import su.reya.coop.RoomUiState import su.reya.coop.Screen -import su.reya.coop.flow import su.reya.coop.formatAsGroup import su.reya.coop.shared.Avatar +import su.reya.coop.uiStateFlow import su.reya.coop.viewmodel.AccountViewModel import su.reya.coop.viewmodel.ChatScreenViewModel @@ -117,11 +118,25 @@ fun ChatScreen( val scope = rememberCoroutineScope() val listState = rememberLazyListState() + val id = viewModel.id val currentUser by viewModel.currentUser.collectAsStateWithLifecycle() - val pubkey = currentUser?.publicKey + val chatRooms by viewModel.chatRooms.collectAsStateWithLifecycle() + val room by remember(id) { derivedStateOf { chatRooms.firstOrNull { it.id == id } } } - val room by viewModel.room.collectAsStateWithLifecycle() - val roomState by room.flow(profileCache, pubkey).collectAsStateWithLifecycle(RoomUiState()) + // Show empty screen + if (room == null) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Text( + text = "Something went wrong.", + style = MaterialTheme.typography.titleMediumEmphasized, + color = MaterialTheme.colorScheme.onSurface + ) + } + return + } val loading = viewModel.loading val newOtherMessages = viewModel.newOtherMessages @@ -131,6 +146,9 @@ fun ChatScreen( val groupedMessages = remember { derivedStateOf { messages.groupBy { it.createdAt().formatAsGroup() } } } + val roomState by (room as Room).uiStateFlow(profileCache, currentUser?.publicKey) + .collectAsStateWithLifecycle(RoomUiState()) + var text by remember { mutableStateOf("") } var selectedMessage by remember { mutableStateOf?>(null) } var replyingTo by remember { mutableStateOf(null) } @@ -175,7 +193,9 @@ fun ChatScreen( } } - Box(modifier = Modifier.fillMaxSize()) { + Box( + modifier = Modifier.fillMaxSize() + ) { Scaffold( modifier = Modifier.blur(blurAmount), contentWindowInsets = ScaffoldDefaults.contentWindowInsets.union(WindowInsets.ime), @@ -187,7 +207,7 @@ fun ChatScreen( Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier.clickable { - room.members.firstOrNull()?.let { pubkey -> + room?.members?.firstOrNull()?.let { pubkey -> navigator.navigate(Screen.Profile(pubkey.toBech32())) } } @@ -245,7 +265,7 @@ fun ChatScreen( .padding(bottom = innerPadding.calculateBottomPadding()) ) { if (requireScreening) { - ScreenerCard(accountViewModel, room) + room?.let { ScreenerCard(accountViewModel, it) } } when (messages.isNotEmpty()) { @@ -263,7 +283,8 @@ fun ChatScreen( items = messagesInGroup, key = { it.ensureId().id()?.toHex()!! } ) { event -> - val model = rememberMessageModel(event, pubkey) + val model = + rememberMessageModel(event, currentUser?.publicKey) val replyPreview = remember(model.replyEventIds, messages.size) { @@ -277,9 +298,7 @@ fun ChatScreen( modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(2.dp) ) { - replyPreview?.let { - ReplyPreview(it, model.isMine) - } + replyPreview?.let { ReplyPreview(it, model.isMine) } ChatMessage( model = model, modifier = Modifier.graphicsLayer { diff --git a/shared/src/commonMain/kotlin/su/reya/coop/Room.kt b/shared/src/commonMain/kotlin/su/reya/coop/Room.kt index b49d379..2a01f29 100644 --- a/shared/src/commonMain/kotlin/su/reya/coop/Room.kt +++ b/shared/src/commonMain/kotlin/su/reya/coop/Room.kt @@ -71,7 +71,7 @@ data class RoomUiState( val isGroup: Boolean = false ) -fun Room.flow( +fun Room.uiStateFlow( profileCache: ProfileCache, currentUser: PublicKey? = null ): Flow { diff --git a/shared/src/commonMain/kotlin/su/reya/coop/viewmodel/ChatScreenViewModel.kt b/shared/src/commonMain/kotlin/su/reya/coop/viewmodel/ChatScreenViewModel.kt index a8f2f76..bec9f34 100644 --- a/shared/src/commonMain/kotlin/su/reya/coop/viewmodel/ChatScreenViewModel.kt +++ b/shared/src/commonMain/kotlin/su/reya/coop/viewmodel/ChatScreenViewModel.kt @@ -7,40 +7,30 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import rust.nostr.sdk.EventId import rust.nostr.sdk.UnsignedEvent +import su.reya.coop.Profile import su.reya.coop.Room import su.reya.coop.repository.AccountRepository import su.reya.coop.repository.ChatRepository import su.reya.coop.roomId class ChatScreenViewModel( - initialRoom: Room, + val id: Long, screening: Boolean, accountRepository: AccountRepository, private val chatRepository: ChatRepository, ) : ViewModel(), ErrorHost by chatRepository { + val currentUser: StateFlow = accountRepository.currentUserProfile + val chatRooms: StateFlow> = chatRepository.chatRooms + var loading by mutableStateOf(true) var newOtherMessages by mutableIntStateOf(0) var requireScreening by mutableStateOf(screening) val messages = mutableStateListOf() - val currentUser = accountRepository.currentUserProfile - val id = initialRoom.id - - val room: StateFlow = chatRepository.chatRooms - .map { rooms -> rooms.find { it.id == id } ?: initialRoom } - .stateIn( - scope = viewModelScope, - started = SharingStarted.WhileSubscribed(5000), - initialValue = initialRoom - ) - init { loadMessages() connect()