refactor: use LocalCache.observeNotes flow for open polls
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
This commit is contained in:
+29
-42
@@ -24,74 +24,61 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.produceState
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent
|
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.nip88Polls.poll.PollEvent
|
||||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun openPollsState(accountViewModel: AccountViewModel) =
|
fun openPollsState(accountViewModel: AccountViewModel) =
|
||||||
produceState(initialValue = emptyList<Note>(), accountViewModel) {
|
remember(accountViewModel) {
|
||||||
value =
|
val userPubkeyHex = accountViewModel.account.userProfile().pubkeyHex
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
findOpenPolls(accountViewModel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findOpenPolls(accountViewModel: AccountViewModel): List<Note> {
|
val filter =
|
||||||
val userPubkeyHex = accountViewModel.account.userProfile().pubkeyHex
|
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<Note>): List<Note> {
|
||||||
val now = TimeUtils.now()
|
val now = TimeUtils.now()
|
||||||
val oneDayInSeconds = TimeUtils.ONE_DAY
|
val oneDayInSeconds = TimeUtils.ONE_DAY
|
||||||
|
|
||||||
val openPolls = mutableListOf<Note>()
|
return notes.filter { note ->
|
||||||
|
val event = note.event ?: return@filter false
|
||||||
LocalCache.notes.forEach { _, note ->
|
|
||||||
val event = note.event ?: return@forEach
|
|
||||||
|
|
||||||
when (event) {
|
when (event) {
|
||||||
is PollEvent -> {
|
is PollEvent -> {
|
||||||
if (event.pubKey == userPubkeyHex) {
|
val endsAt = event.endsAt()
|
||||||
val endsAt = event.endsAt()
|
if (endsAt != null) endsAt > now else event.createdAt + oneDayInSeconds > now
|
||||||
val isOpen =
|
|
||||||
if (endsAt != null) {
|
|
||||||
endsAt > now
|
|
||||||
} else {
|
|
||||||
event.createdAt + oneDayInSeconds > now
|
|
||||||
}
|
|
||||||
if (isOpen) {
|
|
||||||
openPolls.add(note)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is ZapPollEvent -> {
|
is ZapPollEvent -> {
|
||||||
if (event.pubKey == userPubkeyHex) {
|
val closedAt = event.closedAt()
|
||||||
val closedAt = event.closedAt()
|
if (closedAt != null) closedAt > now else event.createdAt + oneDayInSeconds > now
|
||||||
val isOpen =
|
|
||||||
if (closedAt != null) {
|
|
||||||
closedAt > now
|
|
||||||
} else {
|
|
||||||
event.createdAt + oneDayInSeconds > now
|
|
||||||
}
|
|
||||||
if (isOpen) {
|
|
||||||
openPolls.add(note)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return openPolls.sortedByDescending { it.createdAt() }
|
else -> false
|
||||||
|
}
|
||||||
|
}.sortedByDescending { it.createdAt() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
Reference in New Issue
Block a user