chore: optimize the battery usage #16

Merged
reya merged 5 commits from optimize-battery into master 2026-06-07 00:35:48 +00:00
2 changed files with 42 additions and 30 deletions
Showing only changes of commit 30df5ec972 - Show all commits

View File

@@ -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()))
}
}

View File

@@ -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) ->