Merge PR: fix(desktop): reload the visible page when switching accounts

Merges nostr proposal 22a8247d into main:
- Wrap MainContent in key(account.pubKeyHex) so the account-scoped subtree
  is torn down on an account switch. Deck layout and workspace state are
  remembered outside this key and survive.

Fixes a stale-identity leak, not just staleness: NotificationsScreen holds
its accumulated items in an unkeyed `remember { EventCollectionState(...) }`,
so account A's notifications stayed on screen under account B even though
the subscription below re-keyed correctly. ReadsScreen has the same unkeyed
collection, and DeckColumnContainer's ColumnNavigationState is keyed on
column.id only, so each column's screen stack also survived the switch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vitor Pamplona
2026-07-28 19:45:57 -04:00
co-authored by Claude Opus 5
@@ -1473,37 +1473,52 @@ private fun AppInner(
modifier = bannerModifier,
)
Box(modifier = Modifier.weight(1f)) {
MainContent(
layoutMode = layoutMode,
deckState = deckState,
workspaceManager = workspaceManager,
singlePaneState = singlePaneState,
pinnedNavBarState = pinnedNavBarState,
relayManager = relayManager,
localCache = localCache,
accountManager = accountManager,
account = account,
iAccount = iAccount,
accountRelays = accountRelays,
dmSendTracker = dmSendTracker,
nwcConnection = nwcConnection,
subscriptionsCoordinator = subscriptionsCoordinator,
indexRelaysStore = indexRelaysStore,
nip11Fetcher = nip11Fetcher,
dmInboxResolver = dmInboxResolver,
appScope = scope,
torStatus = currentTorStatus,
onShowComposeDialog = onShowComposeDialog,
onShowReplyDialog = onShowReplyDialog,
onEditInComposer = onEditInComposer,
onShowAppDrawer = onShowAppDrawer,
onOpenFeedsDrawer = {
appDrawerInitialTab =
com.vitorpamplona.amethyst.desktop.ui.deck.AppDrawerTab.FEEDS
onShowAppDrawer()
},
onShowImportFollowListDialog = onShowImportFollowListDialog,
)
// Force a Compose subtree teardown when the active
// account changes. Without this, the currently-open
// column keeps its account-A `remember { ... }`
// state (LazyListState scroll position, expanded
// rows, filter-tab selection, in-flight metadata
// observers, per-column view-models) even though the
// outer `iAccount` / `accountRelays` swap correctly.
// Users saw account A's notifications / profile /
// messages page rendered under account B's identity
// until they navigated away and back. `key(pubKeyHex)`
// is the idiomatic Compose way to reset an entire
// subtree on identity change while keeping the outer
// deck layout / workspace state (declared above) alive.
androidx.compose.runtime.key(account.pubKeyHex) {
MainContent(
layoutMode = layoutMode,
deckState = deckState,
workspaceManager = workspaceManager,
singlePaneState = singlePaneState,
pinnedNavBarState = pinnedNavBarState,
relayManager = relayManager,
localCache = localCache,
accountManager = accountManager,
account = account,
iAccount = iAccount,
accountRelays = accountRelays,
dmSendTracker = dmSendTracker,
nwcConnection = nwcConnection,
subscriptionsCoordinator = subscriptionsCoordinator,
indexRelaysStore = indexRelaysStore,
nip11Fetcher = nip11Fetcher,
dmInboxResolver = dmInboxResolver,
appScope = scope,
torStatus = currentTorStatus,
onShowComposeDialog = onShowComposeDialog,
onShowReplyDialog = onShowReplyDialog,
onEditInComposer = onEditInComposer,
onShowAppDrawer = onShowAppDrawer,
onOpenFeedsDrawer = {
appDrawerInitialTab =
com.vitorpamplona.amethyst.desktop.ui.deck.AppDrawerTab.FEEDS
onShowAppDrawer()
},
onShowImportFollowListDialog = onShowImportFollowListDialog,
)
}
}
}