From b6e54db81b126b95e4776fede5aca4050b3df3d8 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 20 Mar 2026 21:38:48 +0000 Subject: [PATCH] refactor: use LocalCache.observeNotes flow for open polls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace LocalCache.notes.forEach iteration with observeNotes using a Filter for PollEvent.KIND and ZapPollEvent.KIND by the current user. This makes the open polls list reactive — it updates automatically when new polls arrive instead of only computing once on composition. https://claude.ai/code/session_01LLLN5MDA5nJFYx38MVo81Q --- .../notifications/OpenPollsSection.kt | 71 ++++++++----------- 1 file changed, 29 insertions(+), 42 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/OpenPollsSection.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/OpenPollsSection.kt index 619ceae07..39223b078 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/OpenPollsSection.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/OpenPollsSection.kt @@ -24,74 +24,61 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.produceState +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.vitorpamplona.amethyst.R -import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent +import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter import com.vitorpamplona.quartz.nip88Polls.poll.PollEvent import com.vitorpamplona.quartz.utils.TimeUtils import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map @Composable fun openPollsState(accountViewModel: AccountViewModel) = - produceState(initialValue = emptyList(), accountViewModel) { - value = - withContext(Dispatchers.IO) { - findOpenPolls(accountViewModel) - } - } + remember(accountViewModel) { + val userPubkeyHex = accountViewModel.account.userProfile().pubkeyHex -private fun findOpenPolls(accountViewModel: AccountViewModel): List { - val userPubkeyHex = accountViewModel.account.userProfile().pubkeyHex + val filter = + Filter( + kinds = listOf(PollEvent.KIND, ZapPollEvent.KIND), + authors = listOf(userPubkeyHex), + ) + + accountViewModel.account.cache + .observeNotes(filter) + .map { notes -> filterOpenPolls(notes) } + .flowOn(Dispatchers.IO) + }.collectAsStateWithLifecycle(initialValue = emptyList()) + +private fun filterOpenPolls(notes: List): List { val now = TimeUtils.now() val oneDayInSeconds = TimeUtils.ONE_DAY - val openPolls = mutableListOf() - - LocalCache.notes.forEach { _, note -> - val event = note.event ?: return@forEach + return notes.filter { note -> + val event = note.event ?: return@filter false when (event) { is PollEvent -> { - if (event.pubKey == userPubkeyHex) { - val endsAt = event.endsAt() - val isOpen = - if (endsAt != null) { - endsAt > now - } else { - event.createdAt + oneDayInSeconds > now - } - if (isOpen) { - openPolls.add(note) - } - } + val endsAt = event.endsAt() + if (endsAt != null) endsAt > now else event.createdAt + oneDayInSeconds > now } is ZapPollEvent -> { - if (event.pubKey == userPubkeyHex) { - val closedAt = event.closedAt() - val isOpen = - if (closedAt != null) { - closedAt > now - } else { - event.createdAt + oneDayInSeconds > now - } - if (isOpen) { - openPolls.add(note) - } - } + val closedAt = event.closedAt() + if (closedAt != null) closedAt > now else event.createdAt + oneDayInSeconds > now } - } - } - return openPolls.sortedByDescending { it.createdAt() } + else -> false + } + }.sortedByDescending { it.createdAt() } } @Composable