feat(cache): wire State classes on DesktopIAccount for GC retention
- Add BookmarkListState, Kind3FollowListState, Nip65RelayListState to DesktopIAccount — pins important AddressableNotes via strong refs - Create stub Kind3FollowListRepository + Nip65RelayListRepository (no persistence yet, null backups) - Update followingKeySet() to read from Kind3FollowListState.flow - Revert accidental long-form branch changes in DeckColumnContainer
This commit is contained in:
@@ -153,6 +153,7 @@ sealed class DesktopScreen {
|
||||
) : DesktopScreen()
|
||||
|
||||
data object Drafts : DesktopScreen()
|
||||
|
||||
data object Settings : DesktopScreen()
|
||||
}
|
||||
|
||||
|
||||
+41
-1
@@ -24,6 +24,11 @@ import com.vitorpamplona.amethyst.commons.model.IAccount
|
||||
import com.vitorpamplona.amethyst.commons.model.INwcSignerState
|
||||
import com.vitorpamplona.amethyst.commons.model.Note
|
||||
import com.vitorpamplona.amethyst.commons.model.User
|
||||
import com.vitorpamplona.amethyst.commons.model.nip02FollowList.Kind3FollowListRepository
|
||||
import com.vitorpamplona.amethyst.commons.model.nip02FollowList.Kind3FollowListState
|
||||
import com.vitorpamplona.amethyst.commons.model.nip51Lists.BookmarkListState
|
||||
import com.vitorpamplona.amethyst.commons.model.nip65RelayList.Nip65RelayListRepository
|
||||
import com.vitorpamplona.amethyst.commons.model.nip65RelayList.Nip65RelayListState
|
||||
import com.vitorpamplona.amethyst.commons.model.privateChats.ChatroomList
|
||||
import com.vitorpamplona.amethyst.desktop.account.AccountState
|
||||
import com.vitorpamplona.amethyst.desktop.cache.DesktopLocalCache
|
||||
@@ -31,6 +36,7 @@ import com.vitorpamplona.amethyst.desktop.network.RelayConnectionManager
|
||||
import com.vitorpamplona.amethyst.desktop.ui.chats.DmSendTracker
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
|
||||
import com.vitorpamplona.quartz.nip04Dm.messages.PrivateDmEvent
|
||||
import com.vitorpamplona.quartz.nip17Dm.NIP17Factory
|
||||
import com.vitorpamplona.quartz.nip17Dm.files.ChatMessageEncryptedFileHeaderEvent
|
||||
@@ -42,6 +48,7 @@ import com.vitorpamplona.quartz.nip47WalletConnect.rpc.Response
|
||||
import com.vitorpamplona.quartz.nip57Zaps.IPrivateZapsDecryptionCache
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
||||
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip89AppHandlers.clientTag.NostrSignerWithClientTag
|
||||
import com.vitorpamplona.quartz.utils.DualCase
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -67,6 +74,39 @@ class DesktopIAccount(
|
||||
|
||||
override val pubKey: String = accountState.pubKeyHex
|
||||
|
||||
// ----- State Classes (pin important notes via strong refs for GC retention) -----
|
||||
|
||||
val bookmarkState = BookmarkListState(signer, localCache, scope)
|
||||
|
||||
val kind3FollowList =
|
||||
Kind3FollowListState(
|
||||
signer,
|
||||
localCache,
|
||||
scope,
|
||||
object : Kind3FollowListRepository {
|
||||
override val backupContactList: ContactListEvent? = null
|
||||
|
||||
override fun updateContactListTo(event: ContactListEvent) { /* no persistence yet */ }
|
||||
},
|
||||
)
|
||||
|
||||
val nip65RelayList =
|
||||
Nip65RelayListState(
|
||||
signer,
|
||||
localCache,
|
||||
scope,
|
||||
object : Nip65RelayListRepository {
|
||||
override val backupNIP65RelayList: AdvertisedRelayListEvent? = null
|
||||
|
||||
override fun updateNIP65RelayList(event: AdvertisedRelayListEvent) { /* no persistence yet */ }
|
||||
|
||||
override val defaultOutboxRelays = relayManager.connectedRelays.value
|
||||
override val defaultInboxRelays = relayManager.connectedRelays.value
|
||||
},
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
override val showSensitiveContent: Boolean? = null
|
||||
|
||||
override val hiddenWordsCase: List<DualCase> = emptyList()
|
||||
@@ -97,7 +137,7 @@ class DesktopIAccount(
|
||||
|
||||
override fun isWriteable(): Boolean = !accountState.isReadOnly
|
||||
|
||||
override fun followingKeySet(): Set<String> = emptySet()
|
||||
override fun followingKeySet(): Set<String> = kind3FollowList.flow.value.authors
|
||||
|
||||
override fun isHidden(user: User): Boolean = false
|
||||
|
||||
|
||||
+46
-7
@@ -45,6 +45,7 @@ import com.vitorpamplona.amethyst.desktop.chess.ChessScreen
|
||||
import com.vitorpamplona.amethyst.desktop.model.DesktopIAccount
|
||||
import com.vitorpamplona.amethyst.desktop.network.DesktopRelayConnectionManager
|
||||
import com.vitorpamplona.amethyst.desktop.service.drafts.DesktopDraftStore
|
||||
import com.vitorpamplona.amethyst.desktop.service.highlights.DesktopHighlightStore
|
||||
import com.vitorpamplona.amethyst.desktop.subscriptions.DesktopRelaySubscriptionsCoordinator
|
||||
import com.vitorpamplona.amethyst.desktop.subscriptions.FeedMode
|
||||
import com.vitorpamplona.amethyst.desktop.ui.ArticleEditorScreen
|
||||
@@ -96,6 +97,8 @@ fun DeckColumnContainer(
|
||||
iAccount: DesktopIAccount,
|
||||
nwcConnection: Nip47URINorm?,
|
||||
subscriptionsCoordinator: DesktopRelaySubscriptionsCoordinator,
|
||||
highlightStore: DesktopHighlightStore,
|
||||
draftStore: DesktopDraftStore,
|
||||
appScope: CoroutineScope,
|
||||
onShowComposeDialog: () -> Unit,
|
||||
onShowReplyDialog: (com.vitorpamplona.quartz.nip01Core.core.Event) -> Unit,
|
||||
@@ -136,6 +139,8 @@ fun DeckColumnContainer(
|
||||
iAccount = iAccount,
|
||||
nwcConnection = nwcConnection,
|
||||
subscriptionsCoordinator = subscriptionsCoordinator,
|
||||
highlightStore = highlightStore,
|
||||
draftStore = draftStore,
|
||||
appScope = appScope,
|
||||
compactMode = true,
|
||||
onShowComposeDialog = onShowComposeDialog,
|
||||
@@ -144,6 +149,7 @@ fun DeckColumnContainer(
|
||||
onNavigateToProfile = { navState.push(DesktopScreen.UserProfile(it)) },
|
||||
onNavigateToThread = { navState.push(DesktopScreen.Thread(it)) },
|
||||
onNavigateToArticle = { navState.push(DesktopScreen.Article(it)) },
|
||||
onNavigateToEditor = { navState.push(DesktopScreen.Editor(it)) },
|
||||
)
|
||||
if (currentOverlay != null) {
|
||||
Surface(
|
||||
@@ -157,11 +163,14 @@ fun DeckColumnContainer(
|
||||
account = account,
|
||||
nwcConnection = nwcConnection,
|
||||
subscriptionsCoordinator = subscriptionsCoordinator,
|
||||
highlightStore = highlightStore,
|
||||
draftStore = draftStore,
|
||||
onShowComposeDialog = onShowComposeDialog,
|
||||
onShowReplyDialog = onShowReplyDialog,
|
||||
onZapFeedback = onZapFeedback,
|
||||
onNavigateToProfile = { navState.push(DesktopScreen.UserProfile(it)) },
|
||||
onNavigateToThread = { navState.push(DesktopScreen.Thread(it)) },
|
||||
onNavigateToArticle = { navState.push(DesktopScreen.Article(it)) },
|
||||
onBack = { navState.pop() },
|
||||
)
|
||||
}
|
||||
@@ -180,6 +189,8 @@ internal fun RootContent(
|
||||
iAccount: DesktopIAccount,
|
||||
nwcConnection: Nip47URINorm?,
|
||||
subscriptionsCoordinator: DesktopRelaySubscriptionsCoordinator,
|
||||
highlightStore: DesktopHighlightStore? = null,
|
||||
draftStore: DesktopDraftStore? = null,
|
||||
appScope: CoroutineScope,
|
||||
compactMode: Boolean = false,
|
||||
onShowComposeDialog: () -> Unit,
|
||||
@@ -188,6 +199,7 @@ internal fun RootContent(
|
||||
onNavigateToProfile: (String) -> Unit,
|
||||
onNavigateToThread: (String) -> Unit,
|
||||
onNavigateToArticle: (String) -> Unit = {},
|
||||
onNavigateToEditor: (String?) -> Unit = {},
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
@@ -237,8 +249,11 @@ internal fun RootContent(
|
||||
relayManager = relayManager,
|
||||
localCache = localCache,
|
||||
account = account,
|
||||
nwcConnection = nwcConnection,
|
||||
onNavigateToProfile = onNavigateToProfile,
|
||||
onNavigateToArticle = onNavigateToArticle,
|
||||
onNavigateToThread = onNavigateToThread,
|
||||
onZapFeedback = onZapFeedback,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -281,6 +296,7 @@ internal fun RootContent(
|
||||
onBack = {},
|
||||
onCompose = onShowComposeDialog,
|
||||
onNavigateToProfile = onNavigateToProfile,
|
||||
onNavigateToArticle = onNavigateToArticle,
|
||||
onZapFeedback = onZapFeedback,
|
||||
)
|
||||
}
|
||||
@@ -336,16 +352,16 @@ internal fun RootContent(
|
||||
localCache = localCache,
|
||||
account = account,
|
||||
subscriptionsCoordinator = subscriptionsCoordinator,
|
||||
highlightStore = highlightStore,
|
||||
onBack = {},
|
||||
onNavigateToProfile = onNavigateToProfile,
|
||||
)
|
||||
}
|
||||
|
||||
DeckColumnType.Editor -> {
|
||||
val draftStore = remember { DesktopDraftStore(scope) }
|
||||
is DeckColumnType.Editor -> {
|
||||
ArticleEditorScreen(
|
||||
draftSlug = null,
|
||||
draftStore = draftStore,
|
||||
draftSlug = columnType.draftSlug,
|
||||
draftStore = draftStore ?: remember { DesktopDraftStore(scope) },
|
||||
account = account,
|
||||
relayManager = relayManager,
|
||||
onBack = {},
|
||||
@@ -354,10 +370,16 @@ internal fun RootContent(
|
||||
}
|
||||
|
||||
DeckColumnType.Drafts -> {
|
||||
val draftStore = remember { DesktopDraftStore(scope) }
|
||||
DraftsScreen(
|
||||
draftStore = draftStore,
|
||||
onOpenEditor = {},
|
||||
draftStore = draftStore ?: remember { DesktopDraftStore(scope) },
|
||||
onOpenEditor = { slug -> onNavigateToEditor(slug) },
|
||||
)
|
||||
}
|
||||
|
||||
DeckColumnType.MyHighlights -> {
|
||||
com.vitorpamplona.amethyst.desktop.ui.highlights.MyHighlightsScreen(
|
||||
highlightStore = highlightStore ?: remember { DesktopHighlightStore(scope) },
|
||||
onNavigateToArticle = onNavigateToArticle,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -382,11 +404,14 @@ internal fun OverlayContent(
|
||||
account: AccountState.LoggedIn,
|
||||
nwcConnection: Nip47URINorm?,
|
||||
subscriptionsCoordinator: DesktopRelaySubscriptionsCoordinator,
|
||||
highlightStore: DesktopHighlightStore? = null,
|
||||
draftStore: DesktopDraftStore? = null,
|
||||
onShowComposeDialog: () -> Unit,
|
||||
onShowReplyDialog: (com.vitorpamplona.quartz.nip01Core.core.Event) -> Unit,
|
||||
onZapFeedback: (ZapFeedback) -> Unit,
|
||||
onNavigateToProfile: (String) -> Unit,
|
||||
onNavigateToThread: (String) -> Unit,
|
||||
onNavigateToArticle: (String) -> Unit = {},
|
||||
onBack: () -> Unit,
|
||||
) {
|
||||
when (screen) {
|
||||
@@ -401,6 +426,7 @@ internal fun OverlayContent(
|
||||
onBack = onBack,
|
||||
onCompose = onShowComposeDialog,
|
||||
onNavigateToProfile = onNavigateToProfile,
|
||||
onNavigateToArticle = onNavigateToArticle,
|
||||
onZapFeedback = onZapFeedback,
|
||||
)
|
||||
}
|
||||
@@ -428,11 +454,24 @@ internal fun OverlayContent(
|
||||
localCache = localCache,
|
||||
account = account,
|
||||
subscriptionsCoordinator = subscriptionsCoordinator,
|
||||
highlightStore = highlightStore,
|
||||
onBack = onBack,
|
||||
onNavigateToProfile = onNavigateToProfile,
|
||||
)
|
||||
}
|
||||
|
||||
is DesktopScreen.Editor -> {
|
||||
val overlayScope = androidx.compose.runtime.rememberCoroutineScope()
|
||||
ArticleEditorScreen(
|
||||
draftSlug = screen.draftSlug,
|
||||
draftStore = draftStore ?: remember { DesktopDraftStore(overlayScope) },
|
||||
account = account,
|
||||
relayManager = relayManager,
|
||||
onBack = onBack,
|
||||
onPublished = onBack,
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
androidx.compose.material3.Text(
|
||||
"Unsupported screen type",
|
||||
|
||||
Vendored
+2
@@ -79,6 +79,8 @@ class CoordinatorPipelineTest {
|
||||
|
||||
override fun disconnect() {}
|
||||
|
||||
override fun close() {}
|
||||
|
||||
override fun reconnect(
|
||||
onlyIfChanged: Boolean,
|
||||
ignoreRetryDelays: Boolean,
|
||||
|
||||
Reference in New Issue
Block a user