Prevent conversation settings screens from stacking when switching recipients.
This commit is contained in:
parent
52750e726a
commit
141a128429
@ -607,14 +607,6 @@ class MainActivity :
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(wrappedNavigator.scaffoldValue.primary) {
|
||||
if (wrappedNavigator.scaffoldValue.primary == PaneAdaptedValue.Hidden &&
|
||||
mainNavigationState.currentListLocation.isChatsTab
|
||||
) {
|
||||
mainNavigationViewModel.onChatsDetailPaneCollapsed()
|
||||
}
|
||||
}
|
||||
|
||||
val noEnterTransitionFactory = remember {
|
||||
AppScaffoldAnimationStateFactory(
|
||||
enabledStates = AppScaffoldNavigator.NavigationState.entries.filterNot {
|
||||
@ -736,16 +728,14 @@ class MainActivity :
|
||||
primaryContent = {
|
||||
when (mainNavigationState.currentListLocation) {
|
||||
MainNavigationListLocation.CHATS, MainNavigationListLocation.ARCHIVE -> {
|
||||
if (mainNavigationViewModel.chatsBackStackEntries.isNotEmpty()) {
|
||||
NavDisplay(
|
||||
backStack = mainNavigationViewModel.chatsBackStackEntries,
|
||||
onBack = { mainNavigationViewModel.popChatsDetailLocation() },
|
||||
transitionSpec = TransitionSpecs.HorizontalSlide.transitionSpec,
|
||||
popTransitionSpec = TransitionSpecs.HorizontalSlide.popTransitionSpec,
|
||||
predictivePopTransitionSpec = TransitionSpecs.HorizontalSlide.predictivePopTransitionSpec,
|
||||
entryProvider = entryProvider { chatsNavEntries(convoTransitionState) }
|
||||
)
|
||||
}
|
||||
NavDisplay(
|
||||
backStack = mainNavigationViewModel.chatsBackStackEntries,
|
||||
onBack = { mainNavigationViewModel.popChatsDetailLocation() },
|
||||
transitionSpec = TransitionSpecs.HorizontalSlide.transitionSpec,
|
||||
popTransitionSpec = TransitionSpecs.HorizontalSlide.popTransitionSpec,
|
||||
predictivePopTransitionSpec = TransitionSpecs.HorizontalSlide.predictivePopTransitionSpec,
|
||||
entryProvider = entryProvider { chatsNavEntries(convoTransitionState) }
|
||||
)
|
||||
}
|
||||
|
||||
MainNavigationListLocation.CALLS -> {
|
||||
|
||||
@ -33,7 +33,7 @@ class ChatsBackStack(savedStateHandle: SavedStateHandle) {
|
||||
key = KEY,
|
||||
saver = saver
|
||||
) {
|
||||
mutableStateListOf()
|
||||
mutableStateListOf(MainNavigationDetailLocation.Empty)
|
||||
}
|
||||
|
||||
val activeRecipientId: RecipientId?
|
||||
@ -45,8 +45,8 @@ class ChatsBackStack(savedStateHandle: SavedStateHandle) {
|
||||
}
|
||||
}
|
||||
|
||||
val hasConversation: Boolean
|
||||
get() = entries.any { it is MainNavigationDetailLocation.Conversation }
|
||||
val isEmpty: Boolean
|
||||
get() = entries.singleOrNull() is MainNavigationDetailLocation.Empty
|
||||
|
||||
/**
|
||||
* Pushes an entry onto the stack.
|
||||
@ -76,21 +76,10 @@ class ChatsBackStack(savedStateHandle: SavedStateHandle) {
|
||||
/**
|
||||
* Resets the stack to its base empty state.
|
||||
*/
|
||||
fun reset(isSplitPane: Boolean) {
|
||||
entries.clear()
|
||||
if (isSplitPane) {
|
||||
fun reset() {
|
||||
entries.removeAll { it !is MainNavigationDetailLocation.Empty }
|
||||
if (entries.isEmpty()) {
|
||||
entries.add(MainNavigationDetailLocation.Empty)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that [MainNavigationDetailLocation.Empty] is present in the stack iff isSplitPane=true.
|
||||
*/
|
||||
fun updateEmptyDetailForPaneMode(isSplitPane: Boolean) {
|
||||
val hasEmptyBase = entries.firstOrNull() is MainNavigationDetailLocation.Empty
|
||||
when {
|
||||
isSplitPane && !hasEmptyBase -> entries.add(0, MainNavigationDetailLocation.Empty)
|
||||
!isSplitPane && hasEmptyBase -> entries.removeAll { it is MainNavigationDetailLocation.Empty }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ object ConversationSettingsNavigator {
|
||||
recipient: Recipient
|
||||
) {
|
||||
if (activity is MainNavigationChatDetailRouter) {
|
||||
activity.goToChatDetail(MainNavigationDetailLocation.Chats.ConversationSettings(recipient.id, isContentRoot = true))
|
||||
activity.goToChatDetail(MainNavigationDetailLocation.Chats.ConversationSettings(recipient.id))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -92,9 +92,12 @@ sealed interface MainNavigationDetailLocation : Parcelable, NavKey {
|
||||
|
||||
@Serializable
|
||||
data class ConversationSettings(
|
||||
val recipientId: RecipientId,
|
||||
override val isContentRoot: Boolean = false
|
||||
val recipientId: RecipientId
|
||||
) : Chats {
|
||||
@Transient
|
||||
@IgnoredOnParcel
|
||||
override val isContentRoot: Boolean = false
|
||||
|
||||
@Transient
|
||||
@IgnoredOnParcel
|
||||
override val controllerKey: RecipientId = recipientId
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
package org.thoughtcrime.securesms.main
|
||||
|
||||
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
|
||||
import androidx.compose.material3.adaptive.layout.PaneAdaptedValue
|
||||
import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole
|
||||
import androidx.compose.material3.adaptive.navigation.BackNavigationBehavior
|
||||
import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator
|
||||
@ -172,15 +171,12 @@ class MainNavigationViewModel(
|
||||
|
||||
fun onSplitPaneChanged(isSplitPane: Boolean) {
|
||||
this@MainNavigationViewModel.isSplitPane = isSplitPane
|
||||
chatsBackStack.updateEmptyDetailForPaneMode(isSplitPane)
|
||||
|
||||
// if no conversation is selected, clear the empty detail pane when switching from split pane to single pane mode.
|
||||
if (!isSplitPane &&
|
||||
internalMainNavigationState.value.currentListLocation.isChatsTab &&
|
||||
!chatsBackStack.hasConversation &&
|
||||
navigator?.scaffoldValue?.primary == PaneAdaptedValue.Expanded
|
||||
) {
|
||||
navigatorScope?.launch { navigator?.navigateBack() }
|
||||
if (!isSplitPane) {
|
||||
if (chatsBackStack.isEmpty) {
|
||||
lockPaneToSecondary = true
|
||||
setFocusedPane(ThreePaneScaffoldRole.Secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,7 +291,7 @@ class MainNavigationViewModel(
|
||||
val currentListLocation = internalMainNavigationState.value.currentListLocation
|
||||
|
||||
when (location) {
|
||||
is MainNavigationDetailLocation.Empty if currentListLocation.isChatsTab -> chatsBackStack.reset(isSplitPane)
|
||||
is MainNavigationDetailLocation.Empty if currentListLocation.isChatsTab -> clearDetailLocation(chatsBackStack)
|
||||
is MainNavigationDetailLocation.Chats -> pushChatsDetailLocation(location)
|
||||
is MainNavigationDetailLocation.Conversation -> goToConversation(location)
|
||||
|
||||
@ -329,26 +325,27 @@ class MainNavigationViewModel(
|
||||
}
|
||||
|
||||
private fun pushChatsDetailLocation(location: MainNavigationDetailLocation) {
|
||||
if (location is MainNavigationDetailLocation.Chats && chatsBackStack.activeRecipientId != location.controllerKey) {
|
||||
chatsBackStack.reset()
|
||||
}
|
||||
|
||||
chatsBackStack.push(location)
|
||||
updateActiveStateForLocation(location)
|
||||
setFocusedPane(ThreePaneScaffoldRole.Primary)
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse of [pushChatsDetailLocation]. Pops the top chats detail entry and, if no conversation
|
||||
* remains, records the user's intent to stay on the list pane (so a subsequent config change does
|
||||
* not errantly restore them to the Primary/detail pane).
|
||||
*/
|
||||
fun popChatsDetailLocation() {
|
||||
chatsBackStack.pop()
|
||||
if (!chatsBackStack.hasConversation) {
|
||||
if (chatsBackStack.isEmpty) {
|
||||
lockPaneToSecondary = true
|
||||
setFocusedPane(ThreePaneScaffoldRole.Secondary)
|
||||
}
|
||||
}
|
||||
|
||||
fun onChatsDetailPaneCollapsed() {
|
||||
if (!chatsBackStack.hasConversation) {
|
||||
chatsBackStack.reset(isSplitPane)
|
||||
private fun clearDetailLocation(backStack: ChatsBackStack) {
|
||||
backStack.reset()
|
||||
if (!isSplitPane) {
|
||||
lockPaneToSecondary = true
|
||||
setFocusedPane(ThreePaneScaffoldRole.Secondary)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user