diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/ChatMessageDao.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/ChatMessageDao.kt index 5f34999c..c855e1ba 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/ChatMessageDao.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/ChatMessageDao.kt @@ -2,6 +2,7 @@ package ac.cord.auxiliary.compose.database.dao import ac.cord.auxiliary.compose.database.model.ChatMessage import ac.cord.auxiliary.compose.database.model.Relay +import ac.cord.auxiliary.compose.database.model.intermdiate.LocalChatMessage import androidx.room3.Dao import androidx.room3.Query import androidx.room3.Upsert @@ -10,7 +11,10 @@ import kotlinx.coroutines.flow.Flow @Dao interface ChatMessageDao { @Query("SELECT * FROM ChatMessage WHERE chatRoomId = :chatRoomId") - fun observeChatMessagesByChatRoomId(chatRoomId: String): Flow> + fun observeChatMessagesByChatRoomId(chatRoomId: String): Flow> + + @Query("SELECT * FROM ChatMessage WHERE chatRoomId = :chatRoomId") + fun getChatMessagesByChatRoomId(chatRoomId: String): List @Upsert suspend fun upsert(chatMessage: ChatMessage) diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/intermdiate/LocalChatMessage.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/intermdiate/LocalChatMessage.kt new file mode 100644 index 00000000..4e39e20b --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/intermdiate/LocalChatMessage.kt @@ -0,0 +1,15 @@ +package ac.cord.auxiliary.compose.database.model.intermdiate + +import ac.cord.auxiliary.compose.database.model.ChatMessage +import ac.cord.auxiliary.compose.database.model.ChatRoom +import ac.cord.auxiliary.compose.database.model.Mention +import ac.cord.auxiliary.compose.database.model.Participant +import ac.cord.auxiliary.compose.database.model.Post +import ac.cord.auxiliary.compose.database.model.Profile +import androidx.room3.Embedded +import androidx.room3.Relation + +data class LocalChatMessage( + @Embedded val chatMessage: ChatMessage, + +) diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/repository/DatabaseChatRepository.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/repository/DatabaseChatRepository.kt index 4f8d15a2..8046e4f3 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/repository/DatabaseChatRepository.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/repository/DatabaseChatRepository.kt @@ -2,10 +2,12 @@ package ac.cord.auxiliary.compose.database.repository import ac.cord.auxiliary.compose.database.AuxDatabase import ac.cord.auxiliary.compose.database.model.ChatRoom +import ac.cord.auxiliary.compose.database.model.intermdiate.LocalChatMessage import ac.cord.auxiliary.compose.database.model.intermdiate.LocalChatRoom import ac.cord.auxiliary.compose.repository.ChatRepository import co.touchlab.kermit.Logger import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow class DatabaseChatRepository( private val database: AuxDatabase, @@ -21,6 +23,15 @@ class DatabaseChatRepository( return database.chatRoomDao().findChatRoomById(id) } + override suspend fun getChatMessageListByChatRoomId(chatRoomId: String): List { + return database.chatMessageDao().getChatMessagesByChatRoomId(chatRoomId) + } + + override suspend fun observeChatMessageListByChatRoomId(chatRoomId: String): Flow> { + return database.chatMessageDao().observeChatMessagesByChatRoomId(chatRoomId) + } + + override suspend fun getOrCreateChatRoom(publicKey: String, defaultSubject: String?): LocalChatRoom? = try { return database.nostrNip17Dao().getOrCreateChatRoom( publicKey, diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/repository/ChatRepository.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/repository/ChatRepository.kt index 44d07b64..a7ad8fd4 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/repository/ChatRepository.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/repository/ChatRepository.kt @@ -1,13 +1,20 @@ package ac.cord.auxiliary.compose.repository import ac.cord.auxiliary.compose.database.model.ChatRoom +import ac.cord.auxiliary.compose.database.model.intermdiate.LocalChatMessage import ac.cord.auxiliary.compose.database.model.intermdiate.LocalChatRoom +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow interface ChatRepository { suspend fun getChatRoomListByPublicKey(publicKey: String): List suspend fun getChatRoomByIdentifier(id: String): LocalChatRoom? + suspend fun getChatMessageListByChatRoomId(chatRoomId: String): List + + suspend fun observeChatMessageListByChatRoomId(chatRoomId: String): Flow> + suspend fun getOrCreateChatRoom(publicKey: String, defaultSubject: String? = null): LocalChatRoom? fun updateChatRoomSubject(publicKey: String, subject: String): ChatRoom? @@ -22,6 +29,15 @@ interface ChatRepository { return null } + override suspend fun getChatMessageListByChatRoomId(chatRoomId: String): List { + return emptyList() + } + + override suspend fun observeChatMessageListByChatRoomId(chatRoomId: String): Flow> { + return flow { + } + } + override suspend fun getOrCreateChatRoom(publicKey: String, defaultSubject: String?): LocalChatRoom? { return null } diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/ChatRoomDetailScreen.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/ChatRoomDetailScreen.kt index eba086ba..06a8948f 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/ChatRoomDetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/ChatRoomDetailScreen.kt @@ -56,8 +56,11 @@ import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.key +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview @@ -132,9 +135,7 @@ fun ChatRoomDetailScreen( modifier = Modifier.weight(1f).fillMaxWidth() ) { key(true) { - chatRoomDetailMessageListViewModel.RenderMessages( - onNavigateToDirectMessageDetail = {} - ) + chatRoomDetailMessageListViewModel.RenderMessages() } } @@ -193,54 +194,54 @@ fun ChatRoomDetailScreen( ) } - Row( - modifier = Modifier.padding(4.dp), - horizontalArrangement = Arrangement.spacedBy(4.dp) - ) { - IconButton( - onClick = { - - } - ) { - Icon( - Icons.Default.InsertEmoticon, - contentDescription = "Add emoji" - ) - } - - IconButton( - onClick = { - - } - ) { - Icon( - Icons.Default.AlternateEmail, - contentDescription = "Mention profile" - ) - } - - IconButton( - onClick = { - - } - ) { - Icon( - Icons.Default.Collections, - contentDescription = "Attach media" - ) - } - - IconButton( - onClick = { - - } - ) { - Icon( - Icons.Default.LocationOn, - contentDescription = "Send location" - ) - } - } +// Row( +// modifier = Modifier.padding(4.dp), +// horizontalArrangement = Arrangement.spacedBy(4.dp) +// ) { +// IconButton( +// onClick = { +// +// } +// ) { +// Icon( +// Icons.Default.InsertEmoticon, +// contentDescription = "Add emoji" +// ) +// } +// +// IconButton( +// onClick = { +// +// } +// ) { +// Icon( +// Icons.Default.AlternateEmail, +// contentDescription = "Mention profile" +// ) +// } +// +// IconButton( +// onClick = { +// +// } +// ) { +// Icon( +// Icons.Default.Collections, +// contentDescription = "Attach media" +// ) +// } +// +// IconButton( +// onClick = { +// +// } +// ) { +// Icon( +// Icons.Default.LocationOn, +// contentDescription = "Send location" +// ) +// } +// } } } } diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomDetailMessageListViewModel.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomDetailMessageListViewModel.kt index e09e1a19..d68a1e55 100755 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomDetailMessageListViewModel.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomDetailMessageListViewModel.kt @@ -34,6 +34,7 @@ import androidx.lifecycle.viewmodel.viewModelFactory import co.touchlab.kermit.Logger import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.IO +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.launch class ChatRoomDetailMessageListViewModel( @@ -55,12 +56,12 @@ class ChatRoomDetailMessageListViewModel( fun observeChatRoomFeed() { logger.d("observeChatRoomFeed") viewModelScope.launch(Dispatchers.IO) { - chatRepository.getChatRoomListByPublicKey( + chatRepository.observeChatMessageListByChatRoomId( localChatRoom.chatRoom.userPublicKey - ).let { chatRooms -> - logger.d("ChatRoomList: $chatRooms") + ).distinctUntilChanged().collect { chatMessages -> + logger.d("getChatMessageListByChatRoomId: $chatMessages") chatRoomDetailMessageListUIState = ChatRoomDetailMessageListUIState.Loaded( - chatRoomList = chatRooms + chatMessageList = chatMessages ) } } @@ -89,9 +90,8 @@ class ChatRoomDetailMessageListViewModel( @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable - fun RenderMessages( - onNavigateToDirectMessageDetail: (Route) -> Unit - ) { + fun RenderMessages() { + Column( modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally @@ -111,52 +111,56 @@ class ChatRoomDetailMessageListViewModel( } } is ChatRoomDetailMessageListUIState.Loaded -> { + Spacer( + modifier = Modifier.weight(1f) + ) + Column( modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(10.dp) ) { - if (chatRoomDetailMessageListUIState.chatRoomList.isEmpty()) { + if (chatRoomDetailMessageListUIState.chatMessageList.isEmpty()) { + Spacer( + modifier = Modifier.height(20.dp) + ) Text( - text = "No messages. Go to a profile and send them a message." + modifier = Modifier.padding(20.dp), + text = "Currently no messages have been shared.\nBreak the ice.", + textAlign = TextAlign.Center + ) + + Spacer( + modifier = Modifier.height(20.dp) ) } else { + LazyColumn( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.fillMaxWidth().padding(5.dp), verticalArrangement = Arrangement.spacedBy(10.dp), reverseLayout = true ) { items( - items = chatRoomDetailMessageListUIState.chatRoomList, - key = { it.chatRoom.id } - ) { localChatRoom -> + items = chatRoomDetailMessageListUIState.chatMessageList, + key = { it.chatMessage.id } + ) { localChatMessage -> Card( modifier = Modifier.fillMaxWidth(), onClick = { - onNavigateToDirectMessageDetail.invoke( - ChatRoomDetailRoute( - directMessageIdentifier = localChatRoom.chatRoom.id - ) - ) + } ) { Column( modifier = Modifier.padding(20.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { - if (localChatRoom.participants.size == 1) { - Text( - text = "Note to Self (${localChatRoom.participants.first().profile?.humanReadableNameOrPubkey()})" - ) - } else { - // Remove the active user publicKey from participants... - val participantNames = localChatRoom.participants.filter { it.participant.participantPublicKey != localChatRoom.chatRoom.userPublicKey }.map { it.profile?.humanReadableNameOrPubkey() ?: "unknown participant" } - - Text( - text = localChatRoom.chatRoom.subject ?: participantNames.joinToString() - ) - } + Text( + text = localChatMessage.chatMessage.senderPublicKey // TODO: Get send name... + ) + Text( + text = localChatMessage.chatMessage.content + ) } } } diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/state/ChatRoomDetailMessageListUIState.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/state/ChatRoomDetailMessageListUIState.kt index 141b3028..60ad9125 100755 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/state/ChatRoomDetailMessageListUIState.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/state/ChatRoomDetailMessageListUIState.kt @@ -1,10 +1,10 @@ package ac.cord.auxiliary.compose.ui.view.state -import ac.cord.auxiliary.compose.database.model.intermdiate.LocalChatRoom +import ac.cord.auxiliary.compose.database.model.intermdiate.LocalChatMessage sealed interface ChatRoomDetailMessageListUIState { data class Loaded( - val chatRoomList: List + val chatMessageList: List ): ChatRoomDetailMessageListUIState data object Error: ChatRoomDetailMessageListUIState