diff --git a/SalmonEgg/SalmonEgg/Presentation/Views/Chat/ChatView.xaml b/SalmonEgg/SalmonEgg/Presentation/Views/Chat/ChatView.xaml index 797aa35d..3f7739c2 100644 --- a/SalmonEgg/SalmonEgg/Presentation/Views/Chat/ChatView.xaml +++ b/SalmonEgg/SalmonEgg/Presentation/Views/Chat/ChatView.xaml @@ -394,6 +394,7 @@ ResolveConversationSurfaceProjection().ShouldShowConversationInputSurface; + public bool ShouldLoadConversationInputSurface + => ResolveConversationSurfaceProjection().ShouldLoadConversationInputSurface; + public bool ShouldShowBlockingLoadingMask => ResolveConversationSurfaceProjection().ShouldShowBlockingLoadingMask; diff --git a/src/SalmonEgg.Presentation.Core/ViewModels/Chat/Overlay/ChatConversationSurfaceProjection.cs b/src/SalmonEgg.Presentation.Core/ViewModels/Chat/Overlay/ChatConversationSurfaceProjection.cs index 9b675525..2fabd019 100644 --- a/src/SalmonEgg.Presentation.Core/ViewModels/Chat/Overlay/ChatConversationSurfaceProjection.cs +++ b/src/SalmonEgg.Presentation.Core/ViewModels/Chat/Overlay/ChatConversationSurfaceProjection.cs @@ -11,6 +11,7 @@ internal readonly record struct ChatConversationSurfaceProjection( bool ShouldShowTranscriptSurface, bool ShouldLoadTranscriptSurface, bool ShouldShowConversationInputSurface, + bool ShouldLoadConversationInputSurface, bool ShouldShowBlockingLoadingMask, bool ShouldShowLoadingOverlayStatusPill, bool ShouldShowLoadingOverlayPresenter, diff --git a/src/SalmonEgg.Presentation.Core/ViewModels/Chat/Overlay/ChatConversationSurfaceProjectionCoordinator.cs b/src/SalmonEgg.Presentation.Core/ViewModels/Chat/Overlay/ChatConversationSurfaceProjectionCoordinator.cs index 287317cd..1c72b133 100644 --- a/src/SalmonEgg.Presentation.Core/ViewModels/Chat/Overlay/ChatConversationSurfaceProjectionCoordinator.cs +++ b/src/SalmonEgg.Presentation.Core/ViewModels/Chat/Overlay/ChatConversationSurfaceProjectionCoordinator.cs @@ -6,6 +6,7 @@ internal sealed class ChatConversationSurfaceProjectionCoordinator { private bool _hasLoadedActiveConversationRoot; private bool _hasLoadedTranscriptSurface; + private bool _hasLoadedConversationInputSurface; public ChatConversationSurfaceProjection Project(ChatConversationSurfaceStateInput input) { @@ -13,6 +14,7 @@ public ChatConversationSurfaceProjection Project(ChatConversationSurfaceStateInp _hasLoadedActiveConversationRoot |= state.ShouldShowActiveConversationRoot; _hasLoadedTranscriptSurface |= state.ShouldShowTranscriptSurface; + _hasLoadedConversationInputSurface |= state.ShouldShowConversationInputSurface; return new ChatConversationSurfaceProjection( state.IsActivationOverlayVisible, @@ -23,6 +25,7 @@ public ChatConversationSurfaceProjection Project(ChatConversationSurfaceStateInp state.ShouldShowTranscriptSurface, _hasLoadedTranscriptSurface, state.ShouldShowConversationInputSurface, + _hasLoadedConversationInputSurface, state.ShouldShowBlockingLoadingMask, state.ShouldShowLoadingOverlayStatusPill, state.ShouldShowLoadingOverlayPresenter, diff --git a/tests/SalmonEgg.Presentation.Core.Tests/Chat/Overlay/ChatConversationSurfaceProjectionCoordinatorTests.cs b/tests/SalmonEgg.Presentation.Core.Tests/Chat/Overlay/ChatConversationSurfaceProjectionCoordinatorTests.cs index b1bc7652..cb109306 100644 --- a/tests/SalmonEgg.Presentation.Core.Tests/Chat/Overlay/ChatConversationSurfaceProjectionCoordinatorTests.cs +++ b/tests/SalmonEgg.Presentation.Core.Tests/Chat/Overlay/ChatConversationSurfaceProjectionCoordinatorTests.cs @@ -99,4 +99,51 @@ public void Project_WhenTranscriptSurfaceWasShown_KeepsLoadStateWhenLaterHidden( Assert.False(hidden.ShouldShowTranscriptSurface); Assert.True(hidden.ShouldLoadTranscriptSurface); } + + [Fact] + public void Project_WhenConversationInputSurfaceWasShown_KeepsLoadStateWhenLaterHidden() + { + var coordinator = new ChatConversationSurfaceProjectionCoordinator(); + + var visible = coordinator.Project(new ChatConversationSurfaceStateInput( + IsSessionActive: true, + CurrentSessionId: "conv-1", + MessageHistoryCount: 0, + VisibleTranscriptConversationId: null, + IsChatShellVisibleForRemoteUi: true, + IsConnecting: false, + IsInitializing: false, + IsHydrating: false, + IsLayoutLoading: false, + IsSessionSwitching: false, + SessionSwitchOverlayConversationId: null, + SessionSwitchPreviewConversationId: null, + ConnectionLifecycleOverlayConversationId: null, + HistoryOverlayConversationId: null, + PendingShellActivationConversationId: null, + HydrationLoadedMessageCount: 0)); + + var hidden = coordinator.Project(new ChatConversationSurfaceStateInput( + IsSessionActive: true, + CurrentSessionId: "conv-1", + MessageHistoryCount: 0, + VisibleTranscriptConversationId: null, + IsChatShellVisibleForRemoteUi: true, + IsConnecting: false, + IsInitializing: false, + IsHydrating: false, + IsLayoutLoading: false, + IsSessionSwitching: true, + SessionSwitchOverlayConversationId: "conv-2", + SessionSwitchPreviewConversationId: null, + ConnectionLifecycleOverlayConversationId: null, + HistoryOverlayConversationId: null, + PendingShellActivationConversationId: null, + HydrationLoadedMessageCount: 0)); + + Assert.True(visible.ShouldShowConversationInputSurface); + Assert.True(visible.ShouldLoadConversationInputSurface); + Assert.False(hidden.ShouldShowConversationInputSurface); + Assert.True(hidden.ShouldLoadConversationInputSurface); + } } diff --git a/tests/SalmonEgg.Presentation.Core.Tests/Ui/XamlComplianceTests.cs b/tests/SalmonEgg.Presentation.Core.Tests/Ui/XamlComplianceTests.cs index de66063d..ea359af5 100644 --- a/tests/SalmonEgg.Presentation.Core.Tests/Ui/XamlComplianceTests.cs +++ b/tests/SalmonEgg.Presentation.Core.Tests/Ui/XamlComplianceTests.cs @@ -1403,6 +1403,7 @@ public void ChatView_UsesDeferredTranscriptLoadingWithoutWholePageLifecycleHack( Assert.Contains("x:Name=\"ActiveConversationRoot\"", xaml); Assert.Contains("x:Load=\"{x:Bind ViewModel.ShouldLoadActiveConversationRoot, Mode=OneWay}\"", xaml); Assert.Contains("x:Load=\"{x:Bind ViewModel.ShouldLoadTranscriptSurface, Mode=OneWay}\"", xaml); + Assert.Contains("x:Load=\"{x:Bind ViewModel.ShouldLoadConversationInputSurface, Mode=OneWay}\"", xaml); Assert.Contains("Unloaded=\"OnMessagesListUnloaded\"", xaml); Assert.Contains("private void OnMessagesListUnloaded", codeBehind); Assert.DoesNotContain("PointerPressed=\"OnMessagesListPointerPressed\"", xaml, StringComparison.Ordinal);