Creates an additional pointer for Account lists to make sure the GC doesn't clear instances that are only stored in the LocalCache's WeakReference DB.

This commit is contained in:
Vitor Pamplona
2025-08-29 07:37:24 -04:00
parent df85c3969c
commit a594d741b1
23 changed files with 131 additions and 139 deletions
@@ -399,18 +399,6 @@ class Account(
val liveNotificationFollowListsPerRelay = OutboxLoaderState(liveNotificationFollowLists, cache, scope).flow
/*
val mergedTopFeedAuthorLists =
MergedTopFeedAuthorListsState(
liveHomeFollowListsPerRelay,
liveStoriesFollowListsPerRelay,
liveDiscoveryFollowListsPerRelay,
liveNotificationFollowListsPerRelay,
scope,
).flow
*/
fun isWriteable(): Boolean = settings.isWriteable()
suspend fun updateWarnReports(warnReports: Boolean): Boolean {
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.model.edits
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
@@ -48,13 +47,14 @@ class PrivateStorageRelayListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val privateOutboxListNote = cache.getOrCreateAddressableNote(getPrivateOutboxRelayListAddress())
fun getPrivateOutboxRelayListAddress() = PrivateOutboxRelayListEvent.createAddress(signer.pubKey)
fun getPrivateOutboxRelayListNote(): AddressableNote = LocalCache.getOrCreateAddressableNote(getPrivateOutboxRelayListAddress())
fun getPrivateOutboxRelayListFlow(): StateFlow<NoteState> = privateOutboxListNote.flow().metadata.stateFlow
fun getPrivateOutboxRelayListFlow(): StateFlow<NoteState> = getPrivateOutboxRelayListNote().flow().metadata.stateFlow
fun getPrivateOutboxRelayList(): PrivateOutboxRelayListEvent? = getPrivateOutboxRelayListNote().event as? PrivateOutboxRelayListEvent
fun getPrivateOutboxRelayList(): PrivateOutboxRelayListEvent? = privateOutboxListNote.event as? PrivateOutboxRelayListEvent
suspend fun normalizePrivateOutboxRelayListWithBackup(note: Note): Set<NormalizedRelayUrl> {
val event = note.event as? PrivateOutboxRelayListEvent ?: settings.backupPrivateHomeRelayList
@@ -65,7 +65,7 @@ class PrivateStorageRelayListState(
getPrivateOutboxRelayListFlow()
.map { normalizePrivateOutboxRelayListWithBackup(it.note) }
.onStart {
emit(normalizePrivateOutboxRelayListWithBackup(getPrivateOutboxRelayListNote()))
emit(normalizePrivateOutboxRelayListWithBackup(privateOutboxListNote))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.model.emphChat
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
@@ -49,13 +48,14 @@ class EphemeralChatListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val ephemeralChatListNote = cache.getOrCreateAddressableNote(getEphemeralChatListAddress())
fun getEphemeralChatListAddress() = EphemeralChatListEvent.createAddress(signer.pubKey)
fun getEphemeralChatListNote(): AddressableNote = cache.getOrCreateAddressableNote(getEphemeralChatListAddress())
fun getEphemeralChatListFlow(): StateFlow<NoteState> = ephemeralChatListNote.flow().metadata.stateFlow
fun getEphemeralChatListFlow(): StateFlow<NoteState> = getEphemeralChatListNote().flow().metadata.stateFlow
fun getEphemeralChatList(): EphemeralChatListEvent? = getEphemeralChatListNote().event as? EphemeralChatListEvent
fun getEphemeralChatList(): EphemeralChatListEvent? = ephemeralChatListNote.event as? EphemeralChatListEvent
suspend fun ephemeralChatListWithBackup(note: Note): Set<RoomId> {
val event = note.event as? EphemeralChatListEvent ?: settings.backupEphemeralChatList
@@ -68,7 +68,7 @@ class EphemeralChatListState(
.transformLatest { noteState ->
emit(ephemeralChatListWithBackup(noteState.note))
}.onStart {
emit(ephemeralChatListWithBackup(getEphemeralChatListNote()))
emit(ephemeralChatListWithBackup(ephemeralChatListNote))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -51,13 +51,12 @@ class FollowListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// fun getEphemeralChatListAddress() = cache.getOrCreateUser(signer.pubKey)
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val user = cache.getOrCreateUser(signer.pubKey)
fun getFollowListUser(): User = cache.getOrCreateUser(signer.pubKey)
fun getFollowListFlow(): StateFlow<UserState> = user.flow().follows.stateFlow
fun getFollowListFlow(): StateFlow<UserState> = getFollowListUser().flow().follows.stateFlow
fun getFollowListEvent(): ContactListEvent? = getFollowListUser().latestContactList
fun getFollowListEvent(): ContactListEvent? = user.latestContactList
@OptIn(ExperimentalCoroutinesApi::class)
private val innerFlow: Flow<Kind3Follows> =
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.model.nip17Dms
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
@@ -47,13 +46,14 @@ class DmRelayListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val dmListNote = cache.getOrCreateAddressableNote(getDMRelayListAddress())
fun getDMRelayListAddress() = ChatMessageRelayListEvent.createAddress(signer.pubKey)
fun getDMRelayListNote(): AddressableNote = LocalCache.getOrCreateAddressableNote(getDMRelayListAddress())
fun getDMRelayListFlow(): StateFlow<NoteState> = dmListNote.flow().metadata.stateFlow
fun getDMRelayListFlow(): StateFlow<NoteState> = getDMRelayListNote().flow().metadata.stateFlow
fun getDMRelayList(): ChatMessageRelayListEvent? = getDMRelayListNote().event as? ChatMessageRelayListEvent
fun getDMRelayList(): ChatMessageRelayListEvent? = dmListNote.event as? ChatMessageRelayListEvent
fun normalizeDMRelayListWithBackup(note: Note): Set<NormalizedRelayUrl> {
val event = note.event as? ChatMessageRelayListEvent ?: settings.backupDMRelayList
@@ -63,7 +63,7 @@ class DmRelayListState(
val flow =
getDMRelayListFlow()
.map { normalizeDMRelayListWithBackup(it.note) }
.onStart { emit(normalizeDMRelayListWithBackup(getDMRelayListNote())) }
.onStart { emit(normalizeDMRelayListWithBackup(dmListNote)) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.model.nip28PublicChats
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
@@ -51,13 +50,14 @@ class PublicChatListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val publicChatListNote = cache.getOrCreateAddressableNote(getChannelListAddress())
fun getChannelListAddress() = ChannelListEvent.createAddress(signer.pubKey)
fun getChannelListNote(): AddressableNote = cache.getOrCreateAddressableNote(getChannelListAddress())
fun getChannelListFlow(): StateFlow<NoteState> = publicChatListNote.flow().metadata.stateFlow
fun getChannelListFlow(): StateFlow<NoteState> = getChannelListNote().flow().metadata.stateFlow
fun getChannelList(): ChannelListEvent? = getChannelListNote().event as? ChannelListEvent
fun getChannelList(): ChannelListEvent? = publicChatListNote.event as? ChannelListEvent
suspend fun publicChatListWithBackup(note: Note): Set<ChannelTag> {
val event = note.event as? ChannelListEvent ?: settings.backupChannelList
@@ -70,7 +70,7 @@ class PublicChatListState(
.transformLatest { noteState ->
emit(publicChatListWithBackup(noteState.note))
}.onStart {
emit(publicChatListWithBackup(getChannelListNote()))
emit(publicChatListWithBackup(publicChatListNote))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -21,7 +21,6 @@
package com.vitorpamplona.amethyst.model.nip30CustomEmojis
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlImage
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
@@ -52,13 +51,14 @@ class EmojiPackState(
val link: MediaUrlImage,
)
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val emojiPackListNote = cache.getOrCreateAddressableNote(getEmojiPackSelectionAddress())
fun getEmojiPackSelectionAddress() = EmojiPackSelectionEvent.createAddress(signer.pubKey)
fun getEmojiPackSelection(): EmojiPackSelectionEvent? = getEmojiPackSelectionNote().event as? EmojiPackSelectionEvent
fun getEmojiPackSelection(): EmojiPackSelectionEvent? = emojiPackListNote.event as? EmojiPackSelectionEvent
fun getEmojiPackSelectionFlow(): StateFlow<NoteState> = getEmojiPackSelectionNote().flow().metadata.stateFlow
fun getEmojiPackSelectionNote(): AddressableNote = cache.getOrCreateAddressableNote(getEmojiPackSelectionAddress())
fun getEmojiPackSelectionFlow(): StateFlow<NoteState> = emojiPackListNote.flow().metadata.stateFlow
fun convertEmojiSelectionPack(selection: EmojiPackSelectionEvent?): List<StateFlow<NoteState>>? =
selection?.taggedAddresses()?.map {
@@ -51,13 +51,14 @@ class BookmarkListState(
val private: List<Note> = emptyList(),
)
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val bookmarkList = cache.getOrCreateAddressableNote(getBookmarkListAddress())
fun getBookmarkListAddress() = BookmarkListEvent.createBookmarkAddress(signer.pubKey)
fun getBookmarkListNote() = cache.getOrCreateAddressableNote(getBookmarkListAddress())
fun getBookmarkListFlow(): StateFlow<NoteState> = bookmarkList.flow().metadata.stateFlow
fun getBookmarkListFlow(): StateFlow<NoteState> = getBookmarkListNote().flow().metadata.stateFlow
fun getBookmarkList(): BookmarkListEvent? = getBookmarkListNote().event as? BookmarkListEvent
fun getBookmarkList(): BookmarkListEvent? = bookmarkList.event as? BookmarkListEvent
suspend fun publicBookmarks(note: Note): List<BookmarkIdTag> {
val noteEvent = note.event as? BookmarkListEvent
@@ -75,7 +76,7 @@ class BookmarkListState(
.map { noteState ->
publicBookmarks(noteState.note)
}.onStart {
emit(publicBookmarks(getBookmarkListNote()))
emit(publicBookmarks(bookmarkList))
}.debounce(100)
.flowOn(Dispatchers.Default)
.stateIn(
@@ -90,7 +91,7 @@ class BookmarkListState(
.map { noteState ->
privateBookmarks(noteState.note)
}.onStart {
emit(privateBookmarks(getBookmarkListNote()))
emit(privateBookmarks(bookmarkList))
}.debounce(100)
.flowOn(Dispatchers.Default)
.stateIn(
@@ -43,13 +43,14 @@ class BlockPeopleListState(
val decryptionCache: PeopleListDecryptionCache,
val scope: CoroutineScope,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val blockListNote = cache.getOrCreateAddressableNote(getBlockListAddress())
fun getBlockListAddress() = PeopleListEvent.createBlockAddress(signer.pubKey)
fun getBlockListNote() = LocalCache.getOrCreateAddressableNote(getBlockListAddress())
fun getBlockListFlow(): StateFlow<NoteState> = blockListNote.flow().metadata.stateFlow
fun getBlockListFlow(): StateFlow<NoteState> = getBlockListNote().flow().metadata.stateFlow
fun getBlockList(): PeopleListEvent? = getBlockListNote().event as? PeopleListEvent
fun getBlockList(): PeopleListEvent? = blockListNote.event as? PeopleListEvent
suspend fun blockListWithBackup(note: Note): List<MuteTag> {
val event = note.event as? PeopleListEvent
@@ -59,7 +60,7 @@ class BlockPeopleListState(
val flow =
getBlockListFlow()
.map { blockListWithBackup(it.note) }
.onStart { emit(blockListWithBackup(getBlockListNote())) }
.onStart { emit(blockListWithBackup(blockListNote)) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.model.nip51Lists.blockedRelays
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
@@ -49,13 +48,14 @@ class BlockedRelayListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val blockedListNote = cache.getOrCreateAddressableNote(getBlockedRelayListAddress())
fun getBlockedRelayListAddress() = BlockedRelayListEvent.createAddress(signer.pubKey)
fun getBlockedRelayListNote(): AddressableNote = LocalCache.getOrCreateAddressableNote(getBlockedRelayListAddress())
fun getBlockedRelayListFlow(): StateFlow<NoteState> = blockedListNote.flow().metadata.stateFlow
fun getBlockedRelayListFlow(): StateFlow<NoteState> = getBlockedRelayListNote().flow().metadata.stateFlow
fun getBlockedRelayList(): BlockedRelayListEvent? = getBlockedRelayListNote().event as? BlockedRelayListEvent
fun getBlockedRelayList(): BlockedRelayListEvent? = blockedListNote.event as? BlockedRelayListEvent
suspend fun normalizeBlockedRelayListWithBackup(note: Note): Set<NormalizedRelayUrl> {
val event = note.event as? BlockedRelayListEvent ?: settings.backupBlockedRelayList
@@ -66,7 +66,7 @@ class BlockedRelayListState(
getBlockedRelayListFlow()
.map {
normalizeBlockedRelayListWithBackup(it.note)
}.onStart { emit(normalizeBlockedRelayListWithBackup(getBlockedRelayListNote())) }
}.onStart { emit(normalizeBlockedRelayListWithBackup(blockedListNote)) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -21,7 +21,6 @@
package com.vitorpamplona.amethyst.model.nip51Lists.broadcastRelays
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
@@ -44,13 +43,14 @@ class BroadcastRelayListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val broadcastListNote = cache.getOrCreateAddressableNote(getBroadcastRelayListAddress())
fun getBroadcastRelayListAddress() = BroadcastRelayListEvent.createAddress(signer.pubKey)
fun getBroadcastRelayListNote(): AddressableNote = cache.getOrCreateAddressableNote(getBroadcastRelayListAddress())
fun getBroadcastRelayListFlow(): StateFlow<NoteState> = broadcastListNote.flow().metadata.stateFlow
fun getBroadcastRelayListFlow(): StateFlow<NoteState> = getBroadcastRelayListNote().flow().metadata.stateFlow
fun getBroadcastRelayList(): BroadcastRelayListEvent? = getBroadcastRelayListNote().event as? BroadcastRelayListEvent
fun getBroadcastRelayList(): BroadcastRelayListEvent? = broadcastListNote.event as? BroadcastRelayListEvent
suspend fun normalizeBroadcastRelayListWithBackup(note: Note): Set<NormalizedRelayUrl> {
val event = note.event as? BroadcastRelayListEvent
@@ -60,7 +60,7 @@ class BroadcastRelayListState(
val flow =
getBroadcastRelayListFlow()
.map { normalizeBroadcastRelayListWithBackup(it.note) }
.onStart { emit(normalizeBroadcastRelayListWithBackup(getBroadcastRelayListNote())) }
.onStart { emit(normalizeBroadcastRelayListWithBackup(broadcastListNote)) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.model.nip51Lists.geohashLists
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
@@ -48,13 +47,14 @@ class GeohashListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val geohashListNote = cache.getOrCreateAddressableNote(getGeohashListAddress())
fun getGeohashListAddress() = GeohashListEvent.createAddress(signer.pubKey)
fun getGeohashListNote(): AddressableNote = cache.getOrCreateAddressableNote(getGeohashListAddress())
fun getGeohashListFlow(): StateFlow<NoteState> = geohashListNote.flow().metadata.stateFlow
fun getGeohashListFlow(): StateFlow<NoteState> = getGeohashListNote().flow().metadata.stateFlow
fun getGeohashList(): GeohashListEvent? = getGeohashListNote().event as? GeohashListEvent
fun getGeohashList(): GeohashListEvent? = geohashListNote.event as? GeohashListEvent
suspend fun geohashListWithBackup(note: Note): Set<String> {
val event = note.event as? GeohashListEvent ?: settings.backupGeohashList
@@ -67,7 +67,7 @@ class GeohashListState(
.transformLatest { noteState ->
emit(geohashListWithBackup(noteState.note))
}.onStart {
emit(geohashListWithBackup(getGeohashListNote()))
emit(geohashListWithBackup(geohashListNote))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.model.nip51Lists.hashtagLists
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
@@ -48,13 +47,14 @@ class HashtagListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val hashtagListNote = cache.getOrCreateAddressableNote(getHashtagListAddress())
fun getHashtagListAddress() = HashtagListEvent.createAddress(signer.pubKey)
fun getHashtagListNote(): AddressableNote = cache.getOrCreateAddressableNote(getHashtagListAddress())
fun getHashtagListFlow(): StateFlow<NoteState> = hashtagListNote.flow().metadata.stateFlow
fun getHashtagListFlow(): StateFlow<NoteState> = getHashtagListNote().flow().metadata.stateFlow
fun getHashtagList(): HashtagListEvent? = getHashtagListNote().event as? HashtagListEvent
fun getHashtagList(): HashtagListEvent? = hashtagListNote.event as? HashtagListEvent
suspend fun hashtagListWithBackup(note: Note): Set<String> {
val event = note.event as? HashtagListEvent ?: settings.backupHashtagList
@@ -67,7 +67,7 @@ class HashtagListState(
.transformLatest { noteState ->
emit(hashtagListWithBackup(noteState.note))
}.onStart {
emit(hashtagListWithBackup(getHashtagListNote()))
emit(hashtagListWithBackup(hashtagListNote))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -21,7 +21,6 @@
package com.vitorpamplona.amethyst.model.nip51Lists.indexerRelays
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
@@ -45,13 +44,14 @@ class IndexerRelayListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val indexerListNote = cache.getOrCreateAddressableNote(getIndexerRelayListAddress())
fun getIndexerRelayListAddress() = IndexerRelayListEvent.createAddress(signer.pubKey)
fun getIndexerRelayListNote(): AddressableNote = cache.getOrCreateAddressableNote(getIndexerRelayListAddress())
fun getIndexerRelayListFlow(): StateFlow<NoteState> = indexerListNote.flow().metadata.stateFlow
fun getIndexerRelayListFlow(): StateFlow<NoteState> = getIndexerRelayListNote().flow().metadata.stateFlow
fun getIndexerRelayList(): IndexerRelayListEvent? = getIndexerRelayListNote().event as? IndexerRelayListEvent
fun getIndexerRelayList(): IndexerRelayListEvent? = indexerListNote.event as? IndexerRelayListEvent
suspend fun normalizeIndexerRelayListWithBackup(note: Note): Set<NormalizedRelayUrl> {
val event = note.event as? IndexerRelayListEvent
@@ -61,7 +61,7 @@ class IndexerRelayListState(
val flow =
getIndexerRelayListFlow()
.map { normalizeIndexerRelayListWithBackup(it.note) }
.onStart { emit(normalizeIndexerRelayListWithBackup(getIndexerRelayListNote())) }
.onStart { emit(normalizeIndexerRelayListWithBackup(indexerListNote)) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -49,13 +49,14 @@ class MuteListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val muteListNote = cache.getOrCreateAddressableNote(getMuteListAddress())
fun getMuteListAddress() = MuteListEvent.createAddress(signer.pubKey)
fun getMuteListNote() = cache.getOrCreateAddressableNote(getMuteListAddress())
fun getMuteListFlow(): StateFlow<NoteState> = muteListNote.flow().metadata.stateFlow
fun getMuteListFlow(): StateFlow<NoteState> = getMuteListNote().flow().metadata.stateFlow
fun getMuteList(): MuteListEvent? = getMuteListNote().event as? MuteListEvent
fun getMuteList(): MuteListEvent? = muteListNote.event as? MuteListEvent
suspend fun muteListWithBackup(note: Note): List<MuteTag> {
val event = note.event as? MuteListEvent ?: settings.backupMuteList
@@ -65,7 +66,7 @@ class MuteListState(
val flow =
getMuteListFlow()
.map { muteListWithBackup(it.note) }
.onStart { emit(muteListWithBackup(getMuteListNote())) }
.onStart { emit(muteListWithBackup(muteListNote)) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -21,7 +21,6 @@
package com.vitorpamplona.amethyst.model.nip51Lists.proxyRelays
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
@@ -44,13 +43,14 @@ class ProxyRelayListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val proxyListNote = cache.getOrCreateAddressableNote(getProxyRelayListAddress())
fun getProxyRelayListAddress() = ProxyRelayListEvent.createAddress(signer.pubKey)
fun getProxyRelayListNote(): AddressableNote = cache.getOrCreateAddressableNote(getProxyRelayListAddress())
fun getProxyRelayListFlow(): StateFlow<NoteState> = proxyListNote.flow().metadata.stateFlow
fun getProxyRelayListFlow(): StateFlow<NoteState> = getProxyRelayListNote().flow().metadata.stateFlow
fun getProxyRelayList(): ProxyRelayListEvent? = getProxyRelayListNote().event as? ProxyRelayListEvent
fun getProxyRelayList(): ProxyRelayListEvent? = proxyListNote.event as? ProxyRelayListEvent
suspend fun normalizeProxyRelayListWithBackup(note: Note): Set<NormalizedRelayUrl> {
val event = note.event as? ProxyRelayListEvent
@@ -60,7 +60,7 @@ class ProxyRelayListState(
val flow =
getProxyRelayListFlow()
.map { normalizeProxyRelayListWithBackup(it.note) }
.onStart { emit(normalizeProxyRelayListWithBackup(getProxyRelayListNote())) }
.onStart { emit(normalizeProxyRelayListWithBackup(proxyListNote)) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.model.nip51Lists.searchRelays
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.DefaultSearchRelayList
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
@@ -49,13 +48,14 @@ class SearchRelayListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val searchListNote = cache.getOrCreateAddressableNote(getSearchRelayListAddress())
fun getSearchRelayListAddress() = SearchRelayListEvent.Companion.createAddress(signer.pubKey)
fun getSearchRelayListNote(): AddressableNote = LocalCache.getOrCreateAddressableNote(getSearchRelayListAddress())
fun getSearchRelayListFlow(): StateFlow<NoteState> = searchListNote.flow().metadata.stateFlow
fun getSearchRelayListFlow(): StateFlow<NoteState> = getSearchRelayListNote().flow().metadata.stateFlow
fun getSearchRelayList(): SearchRelayListEvent? = getSearchRelayListNote().event as? SearchRelayListEvent
fun getSearchRelayList(): SearchRelayListEvent? = searchListNote.event as? SearchRelayListEvent
fun searchListEvent(note: Note) = note.event as? SearchRelayListEvent ?: settings.backupSearchRelayList
@@ -66,7 +66,7 @@ class SearchRelayListState(
val flow =
getSearchRelayListFlow()
.map { normalizeSearchRelayListWithBackup(it.note) }
.onStart { emit(normalizeSearchRelayListWithBackup(getSearchRelayListNote())) }
.onStart { emit(normalizeSearchRelayListWithBackup(searchListNote)) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -77,7 +77,7 @@ class SearchRelayListState(
val flowNoDefaults =
getSearchRelayListFlow()
.map { normalizeSearchRelayListWithBackupNoDefaults(it.note) }
.onStart { emit(normalizeSearchRelayListWithBackupNoDefaults(getSearchRelayListNote())) }
.onStart { emit(normalizeSearchRelayListWithBackupNoDefaults(searchListNote)) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.model.nip51Lists.trustedRelays
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
@@ -48,13 +47,14 @@ class TrustedRelayListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
fun getTrustedRelayListAddress() = TrustedRelayListEvent.Companion.createAddress(signer.pubKey)
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val trustedListNote = cache.getOrCreateAddressableNote(getTrustedRelayListAddress())
fun getTrustedRelayListNote(): AddressableNote = cache.getOrCreateAddressableNote(getTrustedRelayListAddress())
fun getTrustedRelayListAddress() = TrustedRelayListEvent.createAddress(signer.pubKey)
fun getTrustedRelayListFlow(): StateFlow<NoteState> = getTrustedRelayListNote().flow().metadata.stateFlow
fun getTrustedRelayListFlow(): StateFlow<NoteState> = trustedListNote.flow().metadata.stateFlow
fun getTrustedRelayList(): TrustedRelayListEvent? = getTrustedRelayListNote().event as? TrustedRelayListEvent
fun getTrustedRelayList(): TrustedRelayListEvent? = trustedListNote.event as? TrustedRelayListEvent
suspend fun normalizeTrustedRelayListWithBackup(note: Note): Set<NormalizedRelayUrl> {
val event = note.event as? TrustedRelayListEvent ?: settings.backupTrustedRelayList
@@ -64,7 +64,7 @@ class TrustedRelayListState(
val flow =
getTrustedRelayListFlow()
.map { normalizeTrustedRelayListWithBackup(it.note) }
.onStart { emit(normalizeTrustedRelayListWithBackup(getTrustedRelayListNote())) }
.onStart { emit(normalizeTrustedRelayListWithBackup(trustedListNote)) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.model.nip65RelayList
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.Constants
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
@@ -49,13 +48,14 @@ class Nip65RelayListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val nip65ListNote = cache.getOrCreateAddressableNote(getNIP65RelayListAddress())
fun getNIP65RelayListAddress() = AdvertisedRelayListEvent.createAddress(signer.pubKey)
fun getNIP65RelayListNote(): AddressableNote = cache.getOrCreateAddressableNote(getNIP65RelayListAddress())
fun getNIP65RelayListFlow(): StateFlow<NoteState> = nip65ListNote.flow().metadata.stateFlow
fun getNIP65RelayListFlow(): StateFlow<NoteState> = getNIP65RelayListNote().flow().metadata.stateFlow
fun getNIP65RelayList(): AdvertisedRelayListEvent? = getNIP65RelayListNote().event as? AdvertisedRelayListEvent
fun getNIP65RelayList(): AdvertisedRelayListEvent? = nip65ListNote.event as? AdvertisedRelayListEvent
fun nip65Event(note: Note) = note.event as? AdvertisedRelayListEvent ?: settings.backupNIP65RelayList
@@ -70,7 +70,7 @@ class Nip65RelayListState(
val outboxFlow =
getNIP65RelayListFlow()
.map { normalizeNIP65WriteRelayListWithBackup(it.note) }
.onStart { emit(normalizeNIP65ReadRelayListWithBackup(getNIP65RelayListNote())) }
.onStart { emit(normalizeNIP65ReadRelayListWithBackup(nip65ListNote)) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -81,7 +81,7 @@ class Nip65RelayListState(
val inboxFlow =
getNIP65RelayListFlow()
.map { normalizeNIP65ReadRelayListWithBackup(it.note) }
.onStart { emit(normalizeNIP65ReadRelayListWithBackup(getNIP65RelayListNote())) }
.onStart { emit(normalizeNIP65ReadRelayListWithBackup(nip65ListNote)) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -92,7 +92,7 @@ class Nip65RelayListState(
val allFlowNoDefaults =
getNIP65RelayListFlow()
.map { normalizeNIP65AllRelayListWithBackupNoDefaults(it.note) }
.onStart { emit(normalizeNIP65AllRelayListWithBackupNoDefaults(getNIP65RelayListNote())) }
.onStart { emit(normalizeNIP65AllRelayListWithBackupNoDefaults(nip65ListNote)) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -51,13 +51,14 @@ class CommunityListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val communityListNote = cache.getOrCreateAddressableNote(getCommunityListAddress())
fun getCommunityListAddress() = CommunityListEvent.createAddress(signer.pubKey)
fun getCommunityListNote(): AddressableNote = cache.getOrCreateAddressableNote(getCommunityListAddress())
fun getCommunityListFlow(): StateFlow<NoteState> = communityListNote.flow().metadata.stateFlow
fun getCommunityListFlow(): StateFlow<NoteState> = getCommunityListNote().flow().metadata.stateFlow
fun getCommunityList(): CommunityListEvent? = getCommunityListNote().event as? CommunityListEvent
fun getCommunityList(): CommunityListEvent? = communityListNote.event as? CommunityListEvent
suspend fun communityListWithBackup(note: Note): Set<CommunityTag> {
val event = note.event as? CommunityListEvent ?: settings.backupCommunityList
@@ -70,7 +71,7 @@ class CommunityListState(
.transformLatest { noteState ->
emit(communityListWithBackup(noteState.note))
}.onStart {
emit(communityListWithBackup(getCommunityListNote()))
emit(communityListWithBackup(communityListNote))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -47,11 +47,12 @@ class AppSpecificState(
const val APP_SPECIFIC_DATA_D_TAG = "AmethystSettings"
}
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val amethystSettingsNote = cache.getOrCreateAddressableNote(getAppSpecificDataAddress())
fun getAppSpecificDataAddress() = AppSpecificDataEvent.createAddress(signer.pubKey, APP_SPECIFIC_DATA_D_TAG)
fun getAppSpecificDataNote() = cache.getOrCreateAddressableNote(getAppSpecificDataAddress())
fun getAppSpecificDataFlow(): StateFlow<NoteState> = getAppSpecificDataNote().flow().metadata.stateFlow
fun getAppSpecificDataFlow(): StateFlow<NoteState> = amethystSettingsNote.flow().metadata.stateFlow
suspend fun saveNewAppSpecificData(): AppSpecificDataEvent {
val toInternal = settings.syncedSettings.toInternal()
@@ -21,7 +21,6 @@
package com.vitorpamplona.amethyst.model.nip96FileStorage
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
@@ -42,13 +41,14 @@ class FileStorageServerListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val fileStorageListNote = cache.getOrCreateAddressableNote(getFileServersAddress())
fun getFileServersAddress() = FileServersEvent.createAddress(signer.pubKey)
fun getFileServersNote(): AddressableNote = LocalCache.getOrCreateAddressableNote(getFileServersAddress())
fun getFileServersListFlow(): StateFlow<NoteState> = fileStorageListNote.flow().metadata.stateFlow
fun getFileServersListFlow(): StateFlow<NoteState> = getFileServersNote().flow().metadata.stateFlow
fun getFileServersList(): FileServersEvent? = getFileServersNote().event as? FileServersEvent
fun getFileServersList(): FileServersEvent? = fileStorageListNote.event as? FileServersEvent
fun normalizeServers(note: Note): List<String> {
val event = note.event as? FileServersEvent
@@ -58,7 +58,7 @@ class FileStorageServerListState(
val flow =
getFileServersListFlow()
.map { normalizeServers(it.note) }
.onStart { emit(normalizeServers(getFileServersNote())) }
.onStart { emit(normalizeServers(fileStorageListNote)) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -21,7 +21,6 @@
package com.vitorpamplona.amethyst.model.nipB7Blossom
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
@@ -44,13 +43,14 @@ class BlossomServerListState(
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self
val blossomListNote = cache.getOrCreateAddressableNote(getBlossomServersAddress())
fun getBlossomServersAddress() = BlossomServersEvent.createAddress(signer.pubKey)
fun getBlossomServersNote(): AddressableNote = cache.getOrCreateAddressableNote(getBlossomServersAddress())
fun getBlossomServersListFlow(): StateFlow<NoteState> = blossomListNote.flow().metadata.stateFlow
fun getBlossomServersListFlow(): StateFlow<NoteState> = getBlossomServersNote().flow().metadata.stateFlow
fun getBlossomServersList(): BlossomServersEvent? = getBlossomServersNote().event as? BlossomServersEvent
fun getBlossomServersList(): BlossomServersEvent? = blossomListNote.event as? BlossomServersEvent
fun normalizeServers(note: Note): List<String> {
val event = note.event as? BlossomServersEvent
@@ -60,7 +60,7 @@ class BlossomServerListState(
val flow =
getBlossomServersListFlow()
.map { normalizeServers(it.note) }
.onStart { emit(normalizeServers(getBlossomServersNote())) }
.onStart { emit(normalizeServers(blossomListNote)) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,