fix
This commit is contained in:
@@ -39,6 +39,7 @@ import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
@@ -50,6 +51,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import coop.composeapp.generated.resources.Res
|
||||
import coop.composeapp.generated.resources.ic_arrow_back
|
||||
import coop.composeapp.generated.resources.ic_send
|
||||
@@ -74,7 +76,10 @@ fun ChatScreen(id: Long) {
|
||||
val viewModel = LocalNostrViewModel.current
|
||||
|
||||
// Get chat room by ID
|
||||
val room = viewModel.getChatRoom(id)
|
||||
val chatRooms by viewModel.chatRooms.collectAsStateWithLifecycle()
|
||||
val room by remember(id) {
|
||||
derivedStateOf { chatRooms.firstOrNull { it.id == id } }
|
||||
}
|
||||
|
||||
// Show empty screen
|
||||
if (room == null) {
|
||||
@@ -91,8 +96,8 @@ fun ChatScreen(id: Long) {
|
||||
return
|
||||
}
|
||||
|
||||
val displayName by remember(room) { room.displayNameFlow(viewModel) }.collectAsState("Loading...")
|
||||
val picture by remember(room) { room.pictureFlow(viewModel) }.collectAsState(null)
|
||||
val displayName by remember(room) { room!!.displayNameFlow(viewModel) }.collectAsState("Loading...")
|
||||
val picture by remember(room) { room!!.pictureFlow(viewModel) }.collectAsState(null)
|
||||
|
||||
var text by remember { mutableStateOf("") }
|
||||
var loading by remember { mutableStateOf(true) }
|
||||
@@ -157,7 +162,7 @@ fun ChatScreen(id: Long) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.clickable {
|
||||
room.members.firstOrNull()?.let { pubkey ->
|
||||
room!!.members.firstOrNull()?.let { pubkey ->
|
||||
navigator.navigate(Screen.Profile(pubkey.toBech32()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,14 +13,10 @@ import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.merge
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -63,6 +59,12 @@ class NostrViewModel(
|
||||
private val _isRelayListEmpty = MutableStateFlow(false)
|
||||
val isRelayListEmpty = _isRelayListEmpty.asStateFlow()
|
||||
|
||||
private val _chatRooms = MutableStateFlow<Set<Room>>(emptySet())
|
||||
val chatRooms = _chatRooms.asStateFlow()
|
||||
|
||||
private val _contactList = MutableStateFlow<Set<PublicKey>>(emptySet())
|
||||
val contactList = _contactList.asStateFlow()
|
||||
|
||||
private val _newEvents = MutableSharedFlow<UnsignedEvent>(extraBufferCapacity = 100)
|
||||
val newEvents = _newEvents.asSharedFlow()
|
||||
|
||||
@@ -75,28 +77,6 @@ class NostrViewModel(
|
||||
private val _metadataStore = mutableMapOf<PublicKey, MutableStateFlow<Metadata?>>()
|
||||
private val metadataRequestChannel = Channel<PublicKey>(Channel.UNLIMITED)
|
||||
private val seenPublicKeys = mutableSetOf<PublicKey>()
|
||||
private val manualRoomUpdates = MutableSharedFlow<Set<Room>>()
|
||||
private val _chatRooms = MutableStateFlow<Set<Room>>(emptySet())
|
||||
|
||||
val chatRooms: StateFlow<Set<Room>> = merge(
|
||||
nostr.newEvents.map { event ->
|
||||
processIncomingEvent(event)
|
||||
_chatRooms.value
|
||||
},
|
||||
manualRoomUpdates
|
||||
).stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(5000),
|
||||
initialValue = emptySet()
|
||||
)
|
||||
|
||||
val contactList: StateFlow<Set<PublicKey>> = nostr.contactListUpdates
|
||||
.map { it.toSet() }
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(5000),
|
||||
initialValue = emptySet()
|
||||
)
|
||||
|
||||
init {
|
||||
// Skip the splash screen if a user is already logged in
|
||||
@@ -178,6 +158,33 @@ class NostrViewModel(
|
||||
}
|
||||
|
||||
private suspend fun runObserver() = coroutineScope {
|
||||
// Observe new messages
|
||||
launch {
|
||||
nostr.newEvents.collect { event ->
|
||||
val roomId = event.roomId()
|
||||
val existingRoom = _chatRooms.value.firstOrNull { it.id == roomId }
|
||||
|
||||
if (existingRoom == null) {
|
||||
val currentUser = nostr.signer.currentUser
|
||||
if (currentUser != null) {
|
||||
val newRoom = Room.new(event, currentUser)
|
||||
_chatRooms.update { (it + newRoom).sortedDescending().toSet() }
|
||||
}
|
||||
} else {
|
||||
updateRoomList(roomId, event)
|
||||
}
|
||||
|
||||
_newEvents.emit(event)
|
||||
}
|
||||
}
|
||||
|
||||
// Observe contact list updates
|
||||
launch {
|
||||
nostr.contactListUpdates.collect { contacts ->
|
||||
_contactList.value = contacts.toSet()
|
||||
}
|
||||
}
|
||||
|
||||
// Observe metadata updates
|
||||
launch {
|
||||
nostr.metadataUpdates.collect { (pubkey, metadata) ->
|
||||
|
||||
Reference in New Issue
Block a user