From 762cbbff38f816f21c4eda139eceedf24b74c231 Mon Sep 17 00:00:00 2001 From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> Date: Mon, 2 Oct 2023 13:56:55 -0400 Subject: [PATCH] mainview: prevent details panel from opening maximized also-misc: Removes SplitPanel state-saving Gitlab: #1370 Change-Id: I71f5c209922ad69fb701e935a03078fb8e5ad2de --- src/app/commoncomponents/JamiSplitView.qml | 1 + src/app/mainview/ConversationView.qml | 20 +-- src/app/mainview/components/ChatView.qml | 122 +++++++++++------- .../mainview/components/ChatViewHeader.qml | 25 ++-- .../components/ConversationExtrasPanel.qml | 68 +++++----- .../mainview/components/OngoingCallPage.qml | 40 +++--- .../mainview/components/SwarmDetailsPanel.qml | 1 + 7 files changed, 155 insertions(+), 122 deletions(-) diff --git a/src/app/commoncomponents/JamiSplitView.qml b/src/app/commoncomponents/JamiSplitView.qml index e21b94623..0442116b9 100644 --- a/src/app/commoncomponents/JamiSplitView.qml +++ b/src/app/commoncomponents/JamiSplitView.qml @@ -19,6 +19,7 @@ import QtQuick.Controls import net.jami.Adapters 1.1 import net.jami.Constants 1.1 +// A SplitView that supports dynamic RTL and splitView state saving. SplitView { id: root diff --git a/src/app/mainview/ConversationView.qml b/src/app/mainview/ConversationView.qml index 0f1c8e8f0..3bc72cd0d 100644 --- a/src/app/mainview/ConversationView.qml +++ b/src/app/mainview/ConversationView.qml @@ -32,6 +32,9 @@ ListSelectionView { splitViewStateKey: "Main" hasValidSelection: CurrentConversation.id !== '' + visible: false + onPresented: visible = true + Connections { target: CurrentConversation function onReloadInteractions() { @@ -75,7 +78,7 @@ ListSelectionView { anchors.fill: parent inCallView: parent == callStackView.chatViewContainer - property string currentConvId: CurrentConversation.id + readonly property string currentConvId: CurrentConversation.id onCurrentConvIdChanged: { if (!CurrentConversation.hasCall) { Qt.callLater(focusChatView); @@ -86,7 +89,7 @@ ListSelectionView { } onDismiss: { - if (parent == chatViewContainer) { + if (!inCallView) { viewNode.dismiss(); } else { callStackView.chatViewContainer.visible = false; @@ -94,13 +97,14 @@ ListSelectionView { } } + // Handle visibility change for the in-call chat only. onVisibleChanged: { - if (!inCallView) - return; - if (visible && !parent.showDetails) { - focusChatView(); - } else { - callStackView.contentView.forceActiveFocus(); + if (inCallView) { + if (visible) { + focusChatView(); + } else { + callStackView.contentView.forceActiveFocus(); + } } } } diff --git a/src/app/mainview/components/ChatView.qml b/src/app/mainview/components/ChatView.qml index 9182c823d..0bb64705f 100644 --- a/src/app/mainview/components/ChatView.qml +++ b/src/app/mainview/components/ChatView.qml @@ -21,6 +21,7 @@ import net.jami.Models 1.1 import net.jami.Adapters 1.1 import net.jami.Constants 1.1 import net.jami.Enums 1.1 + import "../../commoncomponents" import "../js/pluginhandlerpickercreation.js" as PluginHandlerPickerCreation @@ -28,7 +29,7 @@ Rectangle { id: root // An enum to make the details panels more readable. - enum Panel { + enum ExtrasPanel { SwarmDetailsPanel, MessagesResearchPanel, AddMemberPanel @@ -40,6 +41,18 @@ Rectangle { required property bool inCallView + // Hide the extrasPanel when going into a call view, but save the previous + // state to restore it when leaving the call view. + property int chatExtrasPanelIndex: extrasPanel.currentIndex + onInCallViewChanged: { + if (inCallView) { + chatExtrasPanelIndex = extrasPanel.currentIndex; + extrasPanel.closePanel(); + } else if (chatExtrasPanelIndex >= 0) { + extrasPanel.openPanel(chatExtrasPanelIndex); + } + } + signal dismiss function focusChatView() { @@ -61,6 +74,16 @@ Rectangle { } } + // Used externally to switch to a extras panel. + function switchToPanel(panel, toggle = true) { + extrasPanel.switchToPanel(panel, toggle); + } + + // Used externally to close the extras panel. + function closePanel() { + extrasPanel.closePanel(); + } + Connections { target: PositionManager function onOpenNewMap() { @@ -71,23 +94,13 @@ Rectangle { Connections { target: CurrentConversation function onIdChanged() { - extrasPanel.restoreState(); MessagesAdapter.loadMoreMessages(); } } - Component.onCompleted: extrasPanel.restoreState() - onVisibleChanged: { if (visible) { chatViewSplitView.resolvePanes(true); - if (root.parent.objectName === "CallViewChatViewContainer") { - if (root.parent.showDetails) { - extrasPanel.switchToPanel(ChatView.SwarmDetailsPanel); - } else { - extrasPanel.closePanel(); - } - } } } @@ -99,9 +112,6 @@ Rectangle { ChatViewHeader { id: chatViewHeader - addParticipantOpened: extrasPanel.currentIndex === ChatView.AddMemberPanel - swarmDetailsOpened: extrasPanel.currentIndex === ChatView.SwarmDetailsPanel - Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true Layout.preferredHeight: JamiTheme.chatViewHeaderPreferredHeight @@ -114,9 +124,6 @@ Rectangle { } onBackClicked: root.dismiss() - onShowDetailsClicked: extrasPanel.switchToPanel(ChatView.SwarmDetailsPanel) - onSearchClicked: extrasPanel.switchToPanel(ChatView.MessagesResearchPanel) - onAddToConversationClicked: extrasPanel.switchToPanel(ChatView.AddMemberPanel) Connections { target: CurrentConversation @@ -190,47 +197,69 @@ Rectangle { Layout.fillWidth: true Layout.fillHeight: true - splitViewStateKey: "Chat" - - property real previousDetailsWidth: extrasPanel.width property real previousWidth: width - onWidthChanged: resolvePanes() - // This function governs the visibility of the chatContents and tracks the - // the width of the SplitView and the details panel. This function should be - // called when the width of the SplitView changes, when the SplitView is shown, - // and when the details panel is shown. When called with force=true, it is being - // called from a visibleChanged event, and we should not update the previous widths. + onWidthChanged: { + resolvePanes(); + // Track the previous width of the split view. + previousWidth = width; + } + + // Track the previous width of the split view. + property real extrasPanelWidth: extrasPanel.width + // The previousExtrasPanelWidth is initialized to the minimum width + // of the extras panel. The value is updated within the "open"-state + // range of the panel (e.g. not 0 or maximized). + property real previousExtrasPanelWidth: JamiTheme.extrasPanelMinWidth + onExtrasPanelWidthChanged: { + resolvePanes(); + // This range should ensure that the panel won't restore to maximized. + if (extrasPanelWidth != 0 && extrasPanelWidth != width) { + console.debug("Saving previous extras panel width: %1".arg(extrasPanelWidth)); + previousExtrasPanelWidth = extrasPanelWidth; + } + } + + // Respond to visibility changes for the extras panel in order to + // determine the structure of the split view. + property bool extrasPanelVisible: extrasPanel.visible + onExtrasPanelVisibleChanged: { + if (extrasPanelVisible) { + extrasPanelWidth = previousExtrasPanelWidth; + } else { + previousExtrasPanelWidth = extrasPanelWidth; + } + resolvePanes(); + } + function resolvePanes(force = false) { + if (!viewNode.visible) { + return; + } + // If the details panel is not visible, then show the chatContents. if (!extrasPanel.visible) { chatContents.visible = true; return; } - // Next we compute whether the SplitView is expanding or shrinking. const isExpanding = width > previousWidth; + // Provide a detailed log here, as this function seems problematic. + console.debug("ChatViewSplitView.resolvePanes: f: %1 w: %2 pw: %3 epw: %4 pepw: %5 ie: %6" + .arg(force).arg(width).arg(previousWidth) + .arg(extrasPanelWidth).arg(previousExtrasPanelWidth).arg(isExpanding)); + + const maximizePredicate = (!isExpanding || force) && chatContents.visible; + const minimizePredicate = (isExpanding || force) && !chatContents.visible; + const mainViewMinWidth = JamiTheme.mainViewPaneMinWidth; + // If the SplitView is not wide enough to show both the chatContents // and the details panel, then hide the chatContents. - if (width < JamiTheme.mainViewPaneMinWidth + extrasPanel.width && (!isExpanding || force) && chatContents.visible) { - if (!force) - previousDetailsWidth = extrasPanel.width; + if (maximizePredicate && width < mainViewMinWidth + extrasPanelWidth) { chatContents.visible = false; - } else if (width >= JamiTheme.mainViewPaneMinWidth + previousDetailsWidth && (isExpanding || force) && !chatContents.visible) { + } else if (minimizePredicate && width >= mainViewMinWidth + previousExtrasPanelWidth) { chatContents.visible = true; } - if (!force) - previousWidth = width; - } - - Connections { - target: viewNode - function onPresented() { - chatViewSplitView.restoreSplitViewState(); - } - function onDismissed() { - chatViewSplitView.saveSplitViewState(); - } } ColumnLayout { @@ -315,19 +344,12 @@ Rectangle { } } - onResizingChanged: if (chatContents.visible) - extrasPanel.previousWidth = extrasPanel.width - ConversationExtrasPanel { id: extrasPanel - property int previousWidth: JamiTheme.extrasPanelMinWidth - SplitView.maximumWidth: root.width SplitView.minimumWidth: JamiTheme.extrasPanelMinWidth SplitView.preferredWidth: JamiTheme.extrasPanelMinWidth - - onVisibleChanged: chatViewSplitView.resolvePanes(true) } } } diff --git a/src/app/mainview/components/ChatViewHeader.qml b/src/app/mainview/components/ChatViewHeader.qml index 52bdcca98..5b89c34cf 100644 --- a/src/app/mainview/components/ChatViewHeader.qml +++ b/src/app/mainview/components/ChatViewHeader.qml @@ -23,16 +23,14 @@ import net.jami.Adapters 1.1 import net.jami.Constants 1.1 import net.jami.Enums 1.1 import net.jami.Models 1.1 + import "../../commoncomponents" Rectangle { id: root signal backClicked - signal addToConversationClicked signal pluginSelector - signal showDetailsClicked - signal searchClicked Connections { target: CurrentConversation @@ -44,7 +42,7 @@ Rectangle { description.eText = CurrentConversation.description; } function onShowSwarmDetails() { - root.showDetailsClicked(); + extrasPanel.switchToPanel(ChatView.SwarmDetailsPanel); } } @@ -60,11 +58,10 @@ Rectangle { return true; } - property bool addParticipantOpened: false - property bool swarmDetailsOpened: false - property bool addMemberVisibility: { - return swarmDetailsVisibility && !CurrentConversation.isCoreDialog && !CurrentConversation.isRequest; + return swarmDetailsVisibility + && !CurrentConversation.isCoreDialog + && !CurrentConversation.isRequest; } property bool swarmDetailsVisibility: { @@ -171,9 +168,7 @@ Rectangle { MessagesAdapter.searchbarPrompt = text; } - onSearchClicked: { - root.searchClicked(); - } + onSearchClicked: extrasPanel.switchToPanel(ChatView.MessagesResearchPanel) Shortcut { sequence: "Ctrl+Shift+F" @@ -209,12 +204,12 @@ Rectangle { id: addParticipantsButton checkable: true - checked: root.addParticipantOpened + checked: extrasPanel.isOpen(ChatView.AddMemberPanel) visible: interactionButtonsVisibility && addMemberVisibility source: JamiResources.add_people_24dp_svg toolTipText: JamiStrings.addParticipants - onClicked: addToConversationClicked() + onClicked: extrasPanel.switchToPanel(ChatView.AddMemberPanel) } JamiPushButton { @@ -241,12 +236,12 @@ Rectangle { id: detailsButton checkable: true - checked: root.swarmDetailsOpened + checked: extrasPanel.isOpen(ChatView.SwarmDetailsPanel) visible: interactionButtonsVisibility && (swarmDetailsVisibility || LRCInstance.currentAccountType === Profile.Type.SIP) // TODO if SIP not a request source: JamiResources.swarm_details_panel_svg toolTipText: JamiStrings.details - onClicked: showDetailsClicked() + onClicked: extrasPanel.switchToPanel(ChatView.SwarmDetailsPanel) } } diff --git a/src/app/mainview/components/ConversationExtrasPanel.qml b/src/app/mainview/components/ConversationExtrasPanel.qml index 9bc2aed81..292133f0d 100644 --- a/src/app/mainview/components/ConversationExtrasPanel.qml +++ b/src/app/mainview/components/ConversationExtrasPanel.qml @@ -21,24 +21,46 @@ import net.jami.Adapters 1.1 StackLayout { id: root + // We need to set the currentIndex to -1 to make sure the + // panel is closed when the application starts. + Component.onCompleted: closePanel() + + // The index of the tab in the swarm details panel. property int detailsIndex: -1 - function isOpen(panel) { - return visible && currentIndex === panel; + // Best to avoid using the visible property directly. + // Pass through the following open/close wrappers instead. + function openPanel(panel) { + currentIndex = panel; + visible = true; } - visible: currentIndex > -1 + function closePanel() { + currentIndex = -1; + visible = false; + } - property bool detailsShouldOpen: false - onVisibleChanged: if (visible) - detailsShouldOpen = true + function isOpen(panel) { + return visible && currentIndex === panel; + } - function restoreState() { - // Only applies to Jami accounts, and we musn't be in a call. - if (detailsShouldOpen && !inCallView && !CurrentConversation.needsSyncing && !CurrentConversation.isRequest) { - switchToPanel(ChatView.SwarmDetailsPanel, false); + // This will open the details panel if it's not already visible. + // Additionally, `toggle` being true (default) will close the panel + // if it is already open to `panel`. + function switchToPanel(panel, toggle = true) { + console.debug("switchToPanel: %1, toggle: %2".arg(panel).arg(toggle)); + if (visible) { + // We need to close the panel if it's open and we're switching to + // the same panel. + if (toggle && currentIndex === panel) { + // Toggle off. + closePanel(); + } else { + // Switch to the new panel. + openPanel(panel); + } } else { - closePanel(); + openPanel(panel); } } @@ -54,24 +76,6 @@ StackLayout { } } - // This will open the details panel if it's not already visible. - // Additionally, `toggle` being true (default) will close the panel - // if it is already open to `panel`. - function switchToPanel(panel, toggle = true) { - if (visible && toggle && currentIndex === panel) { - closePanel(); - } else { - currentIndex = panel; - } - } - - function closePanel() { - // We need to close the panel, but not save it when appropriate. - currentIndex = -1; - if (!inCallView) - detailsShouldOpen = false; - } - SwarmDetailsPanel { id: detailsPanel @@ -81,8 +85,6 @@ StackLayout { // Save it when it changes. onTabBarIndexChanged: root.detailsIndex = tabBarIndex } - MessagesResearchPanel { - } - AddMemberPanel { - } + MessagesResearchPanel {} + AddMemberPanel {} } diff --git a/src/app/mainview/components/OngoingCallPage.qml b/src/app/mainview/components/OngoingCallPage.qml index c5f75426a..ecb247dcb 100644 --- a/src/app/mainview/components/OngoingCallPage.qml +++ b/src/app/mainview/components/OngoingCallPage.qml @@ -39,6 +39,9 @@ Rectangle { property alias chatViewContainer: chatViewContainer property string callPreviewId + // A link to the first child will provide access to the chat view. + property var chatView: chatViewContainer.children[0] + onCallPreviewIdChanged: { controlPreview.start(); } @@ -61,6 +64,20 @@ Rectangle { } } + function setCallChatVisibility(visible) { + if (visible) { + mainColumnLayout.isHorizontal = UtilsAdapter.getAppValue(Settings.Key.ShowChatviewHorizontally); + chatViewContainer.visible = false; + chatViewContainer.visible = true; + } else { + chatViewContainer.visible = false; + } + } + + function toggleCallChatVisibility() { + setCallChatVisibility(!chatViewContainer.visible); + } + function openInCallConversation() { mainColumnLayout.isHorizontal = UtilsAdapter.getAppValue(Settings.Key.ShowChatviewHorizontally); chatViewContainer.visible = false; @@ -291,10 +308,7 @@ Rectangle { anchors.fill: parent function toggleConversation() { - if (inCallMessageWebViewStack.visible) - closeInCallConversation(); - else - openInCallConversation(); + toggleCallChatVisibility(); } Connections { @@ -322,19 +336,13 @@ Rectangle { participantsLayer.hoveredOverVideoMuted = true; } - onChatButtonClicked: { - var detailsVisible = chatViewContainer.showDetails; - chatViewContainer.showDetails = false; - !chatViewContainer.visible || detailsVisible ? openInCallConversation() : closeInCallConversation(); - } - - onFullScreenClicked: { - callStackView.toggleFullScreen(); - } - + onChatButtonClicked: toggleCallChatVisibility() + onFullScreenClicked: callStackView.toggleFullScreen() onSwarmDetailsClicked: { - chatViewContainer.showDetails = !chatViewContainer.showDetails; - chatViewContainer.showDetails ? openInCallConversation() : closeInCallConversation(); + toggleCallChatVisibility(); + if (chatViewContainer.visible) { + chatView.switchToPanel(ChatView.SwarmDetailsPanel); + } } } diff --git a/src/app/mainview/components/SwarmDetailsPanel.qml b/src/app/mainview/components/SwarmDetailsPanel.qml index 09471a6d5..ef8d4e23d 100644 --- a/src/app/mainview/components/SwarmDetailsPanel.qml +++ b/src/app/mainview/components/SwarmDetailsPanel.qml @@ -23,6 +23,7 @@ import Qt5Compat.GraphicalEffects import net.jami.Models 1.1 import net.jami.Adapters 1.1 import net.jami.Constants 1.1 + import "../../commoncomponents" import "../../settingsview/components" -- GitLab