Merge pull request #2124 from vitorpamplona/claude/dismiss-poll-notifications-AEVw5

Add ability to dismiss poll notifications
This commit is contained in:
Vitor Pamplona
2026-04-03 18:19:13 -04:00
committed by GitHub
6 changed files with 48 additions and 5 deletions
@@ -130,6 +130,7 @@ private object PrefKeys {
const val LOGIN_WITH_EXTERNAL_SIGNER = "login_with_external_signer"
const val SIGNER_PACKAGE_NAME = "signer_package_name"
const val HAS_DONATED_IN_VERSION = "has_donated_in_version"
const val DISMISSED_POLL_NOTE_IDS = "dismissed_poll_note_ids"
const val PENDING_ATTESTATIONS = "pending_attestations"
const val ALL_ACCOUNT_INFO = "all_saved_accounts_info"
@@ -389,6 +390,7 @@ object LocalPreferences {
JsonMapper.toJson(regularMap),
)
putStringSet(PrefKeys.HAS_DONATED_IN_VERSION, settings.hasDonatedInVersion.value)
putStringSet(PrefKeys.DISMISSED_POLL_NOTE_IDS, settings.dismissedPollNoteIds.value)
putString(
PrefKeys.PENDING_ATTESTATIONS,
@@ -473,6 +475,7 @@ object LocalPreferences {
val hideBlockAlertDialog = getBoolean(PrefKeys.HIDE_BLOCK_ALERT_DIALOG, false)
val hideNIP17WarningDialog = getBoolean(PrefKeys.HIDE_NIP_17_WARNING_DIALOG, false)
val hasDonatedInVersion = getStringSet(PrefKeys.HAS_DONATED_IN_VERSION, null) ?: setOf()
val dismissedPollNoteIds = getStringSet(PrefKeys.DISMISSED_POLL_NOTE_IDS, null) ?: setOf()
val localRelayServers = getStringSet(PrefKeys.LOCAL_RELAY_SERVERS, null) ?: setOf()
val defaultHomeFollowListStr = getString(PrefKeys.DEFAULT_HOME_FOLLOW_LIST, null)
@@ -594,6 +597,7 @@ object LocalPreferences {
backupTrustProviderList = latestTrustProviderList.await(),
lastReadPerRoute = MutableStateFlow(lastReadPerRoute.await()),
hasDonatedInVersion = MutableStateFlow(hasDonatedInVersion),
dismissedPollNoteIds = MutableStateFlow(dismissedPollNoteIds),
pendingAttestations = MutableStateFlow(pendingAttestations.await()),
backupNipA3PaymentTargets = latestPaymentTargets.await(),
)
@@ -2150,6 +2150,8 @@ class Account(
fun markDonatedInThisVersion() = settings.markDonatedInThisVersion(BuildConfig.VERSION_NAME)
fun dismissPollNotification(noteId: String) = settings.dismissPollNotification(noteId)
init {
Log.d("AccountRegisterObservers", "Init")
@@ -193,6 +193,7 @@ class AccountSettings(
var backupTrustProviderList: TrustProviderListEvent? = null,
val lastReadPerRoute: MutableStateFlow<Map<String, MutableStateFlow<Long>>> = MutableStateFlow(mapOf()),
val hasDonatedInVersion: MutableStateFlow<Set<String>> = MutableStateFlow(setOf()),
val dismissedPollNoteIds: MutableStateFlow<Set<String>> = MutableStateFlow(setOf()),
val pendingAttestations: MutableStateFlow<Map<HexKey, String>> = MutableStateFlow(mapOf()),
var backupNipA3PaymentTargets: PaymentTargetsEvent? = null,
) : EphemeralChatRepository,
@@ -679,6 +680,21 @@ class AccountSettings(
return false
}
// ---
// dismissed polls
// ---
fun isDismissedPoll(noteId: String) = dismissedPollNoteIds.value.contains(noteId)
fun dismissPollNotification(noteId: String) {
if (!dismissedPollNoteIds.value.contains(noteId)) {
dismissedPollNoteIds.update {
it + noteId
}
saveAccountSettings()
}
}
// ----
// last read flows
// ----
@@ -1126,6 +1126,8 @@ class AccountViewModel(
fun markDonatedInThisVersion() = account.markDonatedInThisVersion()
fun dismissPollNotification(noteId: String) = account.dismissPollNotification(noteId)
fun dontTranslateFrom() = account.settings.syncedSettings.languages.dontTranslateFrom.value
fun translateTo() = account.settings.syncedSettings.languages.translateTo.value
@@ -36,6 +36,7 @@ import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.Card
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
@@ -59,6 +60,7 @@ import com.vitorpamplona.amethyst.ui.feeds.FeedError
import com.vitorpamplona.amethyst.ui.feeds.LoadingFeed
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.note.BadgeCompose
import com.vitorpamplona.amethyst.ui.note.CloseIcon
import com.vitorpamplona.amethyst.ui.note.MessageSetCompose
import com.vitorpamplona.amethyst.ui.note.MultiSetCompose
import com.vitorpamplona.amethyst.ui.note.NoteCompose
@@ -184,7 +186,19 @@ private fun FeedLoaded(
Card(
modifier = MaterialTheme.colorScheme.imageModifier,
) {
OpenPollsSectionHeader()
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
OpenPollsSectionHeader()
IconButton(
modifier = Modifier.padding(end = Size10dp),
onClick = { accountViewModel.dismissPollNotification(note.idHex) },
) {
CloseIcon()
}
}
Row(Modifier.fillMaxWidth().animateItem()) {
NoteCompose(
baseNote = note,
@@ -31,6 +31,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
@@ -47,10 +48,14 @@ class OpenPollsState(
)
val flow: StateFlow<List<Note>> =
account.cache
.observeNotes(filter)
.map { notes -> filterOpenPolls(notes) }
.flowOn(Dispatchers.IO)
combine(
account.cache
.observeNotes(filter)
.map { notes -> filterOpenPolls(notes) },
account.settings.dismissedPollNoteIds,
) { polls, dismissed ->
polls.filter { it.idHex !in dismissed }
}.flowOn(Dispatchers.IO)
.stateIn(
scope,
SharingStarted.Eagerly,