diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt index 51a2719e4..c8dcdfbee 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt @@ -392,7 +392,10 @@ object LocalPreferences { ) putStringSet(PrefKeys.HAS_DONATED_IN_VERSION, settings.hasDonatedInVersion.value) putStringSet(PrefKeys.DISMISSED_POLL_NOTE_IDS, settings.dismissedPollNoteIds.value) - putStringSet(PrefKeys.VIEWED_POLL_RESULT_NOTE_IDS, settings.viewedPollResultNoteIds.value) + putString( + PrefKeys.VIEWED_POLL_RESULT_NOTE_IDS, + JsonMapper.toJson(settings.viewedPollResultNoteIds.value), + ) putString( PrefKeys.PENDING_ATTESTATIONS, @@ -478,7 +481,7 @@ object LocalPreferences { 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 viewedPollResultNoteIds = getStringSet(PrefKeys.VIEWED_POLL_RESULT_NOTE_IDS, null) ?: setOf() + val viewedPollResultNoteIdsStr = getString(PrefKeys.VIEWED_POLL_RESULT_NOTE_IDS, null) val localRelayServers = getStringSet(PrefKeys.LOCAL_RELAY_SERVERS, null) ?: setOf() val defaultHomeFollowListStr = getString(PrefKeys.DEFAULT_HOME_FOLLOW_LIST, null) @@ -531,6 +534,7 @@ object LocalPreferences { val zapPaymentRequestServer = async { parseOrNull(zapPaymentRequestServerStr) } val defaultFileServer = async { parseOrNull(defaultFileServerStr) ?: DEFAULT_MEDIA_SERVERS[0] } + val viewedPollResultNoteIds = async { parseOrNull>(viewedPollResultNoteIdsStr) ?: mapOf() } val pendingAttestations = async { parseOrNull>(pendingAttestationsStr) ?: mapOf() } val latestUserMetadata = async { parseEventOrNull(latestUserMetadataStr) } val latestContactList = async { parseEventOrNull(latestContactListStr) } @@ -601,7 +605,7 @@ object LocalPreferences { lastReadPerRoute = MutableStateFlow(lastReadPerRoute.await()), hasDonatedInVersion = MutableStateFlow(hasDonatedInVersion), dismissedPollNoteIds = MutableStateFlow(dismissedPollNoteIds), - viewedPollResultNoteIds = MutableStateFlow(viewedPollResultNoteIds), + viewedPollResultNoteIds = MutableStateFlow(viewedPollResultNoteIds.await()), pendingAttestations = MutableStateFlow(pendingAttestations.await()), backupNipA3PaymentTargets = latestPaymentTargets.await(), ) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index c913f3de1..2349a7307 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -2154,7 +2154,10 @@ class Account( fun hasViewedPollResults(noteId: String) = settings.hasViewedPollResults(noteId) - fun markPollResultsViewed(noteId: String) = settings.markPollResultsViewed(noteId) + fun markPollResultsViewed( + noteId: String, + pollEndsAt: Long?, + ) = settings.markPollResultsViewed(noteId, pollEndsAt) init { Log.d("AccountRegisterObservers", "Init") diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSettings.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSettings.kt index fdc6b5520..ef5422280 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSettings.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSettings.kt @@ -57,6 +57,7 @@ import com.vitorpamplona.quartz.nip65RelayList.tags.AdvertisedRelayType import com.vitorpamplona.quartz.nip72ModCommunities.follow.CommunityListEvent import com.vitorpamplona.quartz.nip78AppData.AppSpecificDataEvent import com.vitorpamplona.quartz.nip85TrustedAssertions.list.TrustProviderListEvent +import com.vitorpamplona.quartz.utils.TimeUtils import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -194,7 +195,7 @@ class AccountSettings( val lastReadPerRoute: MutableStateFlow>> = MutableStateFlow(mapOf()), val hasDonatedInVersion: MutableStateFlow> = MutableStateFlow(setOf()), val dismissedPollNoteIds: MutableStateFlow> = MutableStateFlow(setOf()), - val viewedPollResultNoteIds: MutableStateFlow> = MutableStateFlow(setOf()), + val viewedPollResultNoteIds: MutableStateFlow> = MutableStateFlow(mapOf()), val pendingAttestations: MutableStateFlow> = MutableStateFlow(mapOf()), var backupNipA3PaymentTargets: PaymentTargetsEvent? = null, ) : EphemeralChatRepository, @@ -700,17 +701,34 @@ class AccountSettings( // viewed poll results // --- - fun hasViewedPollResults(noteId: String) = viewedPollResultNoteIds.value.contains(noteId) + fun hasViewedPollResults(noteId: String): Boolean { + val expiresAt = viewedPollResultNoteIds.value[noteId] ?: return false + return expiresAt > TimeUtils.now() + } - fun markPollResultsViewed(noteId: String) { - if (!viewedPollResultNoteIds.value.contains(noteId)) { + fun markPollResultsViewed( + noteId: String, + pollEndsAt: Long?, + ) { + if (noteId !in viewedPollResultNoteIds.value) { + val expiresAt = + if (pollEndsAt != null && pollEndsAt > TimeUtils.now()) { + pollEndsAt + } else { + TimeUtils.now() + TimeUtils.ONE_DAY + } viewedPollResultNoteIds.update { - it + noteId + pruneExpiredViews(it) + (noteId to expiresAt) } saveAccountSettings() } } + private fun pruneExpiredViews(views: Map): Map { + val now = TimeUtils.now() + return views.filterValues { it > now } + } + // ---- // last read flows // ---- diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Poll.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Poll.kt index 049ef36e0..8edda46dd 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Poll.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Poll.kt @@ -271,7 +271,7 @@ fun RenderPollCard( accountViewModel.account.pollRespond(event, responses) } }, - onViewResults = { accountViewModel.markPollResultsViewed(event.id) }, + onViewResults = { accountViewModel.markPollResultsViewed(event.id, event.endsAt()) }, hasViewedResults = { accountViewModel.hasViewedPollResults(event.id) }, resultContent = galleryUser, labelContent = labelContent, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index 00043b7f1..801fc8a70 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -1130,7 +1130,10 @@ class AccountViewModel( fun hasViewedPollResults(noteId: String) = account.hasViewedPollResults(noteId) - fun markPollResultsViewed(noteId: String) = account.markPollResultsViewed(noteId) + fun markPollResultsViewed( + noteId: String, + pollEndsAt: Long?, + ) = account.markPollResultsViewed(noteId, pollEndsAt) fun dontTranslateFrom() = account.settings.syncedSettings.languages.dontTranslateFrom.value