feat: add support for reply message (#44)

Reviewed-on: #44
This commit was merged in pull request #44.
This commit is contained in:
2026-07-14 10:22:27 +00:00
parent 0e789b5d91
commit 1485a767ed
5 changed files with 172 additions and 74 deletions

View File

@@ -150,7 +150,7 @@ fun Timestamp.ago(): String {
}
}
fun Timestamp.formatAsGroupHeader(): String {
fun Timestamp.formatAsGroup(): String {
val timeZone = TimeZone.currentSystemDefault()
val inputInstant = Instant.fromEpochSeconds(this.asSecs().toLong())
val inputDate = inputInstant.toLocalDateTime(timeZone).date

View File

@@ -1,7 +1,9 @@
package su.reya.coop.repository
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -33,6 +35,7 @@ class ChatRepository(
private val nostr: Nostr,
private val mediaRepository: MediaRepository,
private val scope: CoroutineScope,
private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default,
) : ErrorHost by createErrorHost() {
private val _state = MutableStateFlow(ChatState())
val state = _state.stateIn(
@@ -58,7 +61,7 @@ class ChatRepository(
.stateIn(scope, SharingStarted.WhileSubscribed(5000), false)
init {
scope.launch {
scope.launch(defaultDispatcher) {
nostr.waitUntilInitialized()
// Observe message sync progress
@@ -137,7 +140,7 @@ class ChatRepository(
}
fun refreshChatRooms() {
scope.launch {
scope.launch(defaultDispatcher) {
try {
val rooms = nostr.messages.getChatRooms() ?: emptySet()
_state.update { currentState ->
@@ -166,7 +169,7 @@ class ChatRepository(
}
fun chatRoomConnect(roomId: Long) {
scope.launch {
scope.launch(defaultDispatcher) {
try {
val room = getChatRoom(roomId) ?: throw IllegalArgumentException("Room not found")
val members = room.members
@@ -183,7 +186,7 @@ class ChatRepository(
showError("Message cannot be empty")
return
}
scope.launch {
scope.launch(defaultDispatcher) {
try {
val room = getChatRoom(roomId) ?: throw IllegalArgumentException("Room not found")
nostr.messages.sendMessage(
@@ -193,7 +196,7 @@ class ChatRepository(
replies = replies,
onRumorCreated = { event ->
updateRoomList(roomId, event)
scope.launch { _newEvents.tryEmit(event) }
scope.launch(defaultDispatcher) { _newEvents.tryEmit(event) }
},
)
} catch (e: Exception) {

View File

@@ -9,6 +9,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import rust.nostr.sdk.EventId
import rust.nostr.sdk.UnsignedEvent
import su.reya.coop.Profile
import su.reya.coop.Room
@@ -39,7 +40,7 @@ class ChatScreenViewModel(
private fun loadMessages() {
chatRepository.loadChatRoomMessages(id) { initialMessages ->
messages.clear()
messages.addAll(initialMessages)
messages.addAll(initialMessages.distinctBy { it.id() })
loading = false
}
}
@@ -52,7 +53,7 @@ class ChatScreenViewModel(
viewModelScope.launch {
chatRepository.newEvents.collect { event ->
if (event.roomId() == id) {
if (event.id() !in messages.map { it.id() }) {
if (messages.none { it.id() == event.id() }) {
messages.add(0, event)
}
} else {
@@ -62,8 +63,9 @@ class ChatScreenViewModel(
}
}
fun sendMessage(text: String) {
chatRepository.sendMessage(id, text)
fun sendMessage(text: String, replyTo: EventId? = null) {
val replyToList = if (replyTo != null) listOf(replyTo) else emptyList()
chatRepository.sendMessage(id, text, replyToList)
}
fun sendFileMessage(file: ByteArray?, type: String?) {