fix(nav): preserve screen state across overlay navigation

RootContent now stays composed when overlays are shown, preventing
search results and other state from being destroyed on navigation.
Overlay wrapped in opaque Surface to cover root content visually.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
nrobi144
2026-03-12 13:32:05 +02:00
parent 5a437ed5ac
commit 327bb1efc8
2 changed files with 73 additions and 60 deletions
@@ -27,6 +27,8 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@@ -120,37 +122,42 @@ fun DeckColumnContainer(
Box( Box(
modifier = Modifier.fillMaxSize().padding(12.dp), modifier = Modifier.fillMaxSize().padding(12.dp),
) { ) {
// Always keep RootContent composed so state (e.g. search results) survives navigation
RootContent(
columnType = column.type,
relayManager = relayManager,
localCache = localCache,
accountManager = accountManager,
account = account,
nwcConnection = nwcConnection,
subscriptionsCoordinator = subscriptionsCoordinator,
appScope = appScope,
onShowComposeDialog = onShowComposeDialog,
onShowReplyDialog = onShowReplyDialog,
onZapFeedback = onZapFeedback,
onNavigateToProfile = { navState.push(DesktopScreen.UserProfile(it)) },
onNavigateToThread = { navState.push(DesktopScreen.Thread(it)) },
)
if (currentOverlay != null) { if (currentOverlay != null) {
OverlayContent( Surface(
screen = currentOverlay, color = MaterialTheme.colorScheme.background,
relayManager = relayManager, modifier = Modifier.fillMaxSize(),
localCache = localCache, ) {
account = account, OverlayContent(
nwcConnection = nwcConnection, screen = currentOverlay,
subscriptionsCoordinator = subscriptionsCoordinator, relayManager = relayManager,
onShowComposeDialog = onShowComposeDialog, localCache = localCache,
onShowReplyDialog = onShowReplyDialog, account = account,
onZapFeedback = onZapFeedback, nwcConnection = nwcConnection,
onNavigateToProfile = { navState.push(DesktopScreen.UserProfile(it)) }, subscriptionsCoordinator = subscriptionsCoordinator,
onNavigateToThread = { navState.push(DesktopScreen.Thread(it)) }, onShowComposeDialog = onShowComposeDialog,
onBack = { navState.pop() }, onShowReplyDialog = onShowReplyDialog,
) onZapFeedback = onZapFeedback,
} else { onNavigateToProfile = { navState.push(DesktopScreen.UserProfile(it)) },
RootContent( onNavigateToThread = { navState.push(DesktopScreen.Thread(it)) },
columnType = column.type, onBack = { navState.pop() },
relayManager = relayManager, )
localCache = localCache, }
accountManager = accountManager,
account = account,
nwcConnection = nwcConnection,
subscriptionsCoordinator = subscriptionsCoordinator,
appScope = appScope,
onShowComposeDialog = onShowComposeDialog,
onShowReplyDialog = onShowReplyDialog,
onZapFeedback = onZapFeedback,
onNavigateToProfile = { navState.push(DesktopScreen.UserProfile(it)) },
onNavigateToThread = { navState.push(DesktopScreen.Thread(it)) },
)
} }
} }
} }
@@ -43,6 +43,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationRail import androidx.compose.material3.NavigationRail
import androidx.compose.material3.NavigationRailItem import androidx.compose.material3.NavigationRailItem
import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.VerticalDivider import androidx.compose.material3.VerticalDivider
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -152,37 +153,42 @@ fun SinglePaneLayout(
Box( Box(
modifier = Modifier.fillMaxSize().padding(12.dp), modifier = Modifier.fillMaxSize().padding(12.dp),
) { ) {
// Always keep RootContent composed so state (e.g. search results) survives navigation
RootContent(
columnType = currentColumnType,
relayManager = relayManager,
localCache = localCache,
accountManager = accountManager,
account = account,
nwcConnection = nwcConnection,
subscriptionsCoordinator = subscriptionsCoordinator,
appScope = appScope,
onShowComposeDialog = onShowComposeDialog,
onShowReplyDialog = onShowReplyDialog,
onZapFeedback = onZapFeedback,
onNavigateToProfile = { navState.push(DesktopScreen.UserProfile(it)) },
onNavigateToThread = { navState.push(DesktopScreen.Thread(it)) },
)
if (currentOverlay != null) { if (currentOverlay != null) {
OverlayContent( Surface(
screen = currentOverlay, color = MaterialTheme.colorScheme.background,
relayManager = relayManager, modifier = Modifier.fillMaxSize(),
localCache = localCache, ) {
account = account, OverlayContent(
nwcConnection = nwcConnection, screen = currentOverlay,
subscriptionsCoordinator = subscriptionsCoordinator, relayManager = relayManager,
onShowComposeDialog = onShowComposeDialog, localCache = localCache,
onShowReplyDialog = onShowReplyDialog, account = account,
onZapFeedback = onZapFeedback, nwcConnection = nwcConnection,
onNavigateToProfile = { navState.push(DesktopScreen.UserProfile(it)) }, subscriptionsCoordinator = subscriptionsCoordinator,
onNavigateToThread = { navState.push(DesktopScreen.Thread(it)) }, onShowComposeDialog = onShowComposeDialog,
onBack = { navState.pop() }, onShowReplyDialog = onShowReplyDialog,
) onZapFeedback = onZapFeedback,
} else { onNavigateToProfile = { navState.push(DesktopScreen.UserProfile(it)) },
RootContent( onNavigateToThread = { navState.push(DesktopScreen.Thread(it)) },
columnType = currentColumnType, onBack = { navState.pop() },
relayManager = relayManager, )
localCache = localCache, }
accountManager = accountManager,
account = account,
nwcConnection = nwcConnection,
subscriptionsCoordinator = subscriptionsCoordinator,
appScope = appScope,
onShowComposeDialog = onShowComposeDialog,
onShowReplyDialog = onShowReplyDialog,
onZapFeedback = onZapFeedback,
onNavigateToProfile = { navState.push(DesktopScreen.UserProfile(it)) },
onNavigateToThread = { navState.push(DesktopScreen.Thread(it)) },
)
} }
} }
} }