diff --git a/src/app/constant/JamiTheme.qml b/src/app/constant/JamiTheme.qml index 7f2a8abeee403b7b7e9b6ee93b202bfdcadacc05..abdb70e7c7ce264abd71a3eb580573323b56d26a 100644 --- a/src/app/constant/JamiTheme.qml +++ b/src/app/constant/JamiTheme.qml @@ -577,8 +577,8 @@ Item { property real mainViewMargin: 30 - // Details page - property real detailsPageMinWidth: 300 + // Extras panel + property real extrasPanelMinWidth: 300 property int aboutBtnSize: 24 // Messages point size diff --git a/src/app/currentconversation.cpp b/src/app/currentconversation.cpp index 6e2c92edf65b51815da4e0b2129b4ac9861cf4c2..b51eaa1ebc8b6f3f82a405307fb8275908459d53 100644 --- a/src/app/currentconversation.cpp +++ b/src/app/currentconversation.cpp @@ -307,12 +307,6 @@ CurrentConversation::connectModel() Qt::UniqueConnection); } -void -CurrentConversation::showSwarmDetails() -{ - Q_EMIT showDetails(); -} - void CurrentConversation::updateErrors(const QString& convId) { diff --git a/src/app/currentconversation.h b/src/app/currentconversation.h index 08f09c05f82e5b79939a27f106a2857dd7f19fb9..e5553b338be0d86d535fc61892d684f576e9cafb 100644 --- a/src/app/currentconversation.h +++ b/src/app/currentconversation.h @@ -61,7 +61,6 @@ public: explicit CurrentConversation(LRCInstance* lrcInstance, QObject* parent = nullptr); ~CurrentConversation() = default; Q_INVOKABLE void scrollToMsg(const QString& msgId); - Q_INVOKABLE void showSwarmDetails(); Q_INVOKABLE void setPreference(const QString& key, const QString& value); Q_INVOKABLE QString getPreference(const QString& key) const; Q_INVOKABLE MapStringString getPreferences() const; @@ -71,7 +70,7 @@ public: Q_SIGNALS: void reloadInteractions(); void scrollTo(const QString& msgId); - void showDetails(); + void showSwarmDetails(); private Q_SLOTS: void updateData(); diff --git a/src/app/mainview/components/ChatView.qml b/src/app/mainview/components/ChatView.qml index 5ffc835b3e8a2dbfa66feaba8a6ca874b494d8f2..5d9b17533e6f00d0a9fd1506fa806a8a0b626716 100644 --- a/src/app/mainview/components/ChatView.qml +++ b/src/app/mainview/components/ChatView.qml @@ -1,8 +1,5 @@ /* - * Copyright (C) 2020-2022 Savoir-faire Linux Inc. - * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> - * Author: Trevor Tabah <trevor.tabah@savoirfairelinux.com> - * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * Copyright (C) 2020-2023 Savoir-faire Linux Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,11 +18,11 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts -import Qt5Compat.GraphicalEffects 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 @@ -33,13 +30,17 @@ import "../js/pluginhandlerpickercreation.js" as PluginHandlerPickerCreation Rectangle { id: root + // An enum to make the details panels more readable. + enum Panel { + SwarmDetailsPanel, + MessagesResearchPanel, + AddMemberPanel + } + color: JamiTheme.chatviewBgColor property var mapPositions: PositionManager.mapStatus - property int lastContentsSplitSize: JamiTheme.detailsPageMinWidth - property int lastDetailsSplitSize: JamiTheme.detailsPageMinWidth - property int previousWidth: width required property bool inCallView signal dismiss @@ -51,10 +52,6 @@ Rectangle { function resetPanels() { chatViewHeader.showSearch = true - swarmDetailsPanel.visible = false - addMemberPanel.visible = false - chatContents.visible = true - messagesResearchPanel.visible = false } function instanceMapObject() { @@ -79,21 +76,24 @@ Rectangle { Connections { target: CurrentConversation function onIdChanged() { + extrasPanel.restoreState() MessagesAdapter.loadMoreMessages() } } + Component.onCompleted: extrasPanel.restoreState() + onVisibleChanged: { - if (visible){ - chatViewHeader.showSearch = !root.parent.showDetails - addMemberPanel.visible = false - messagesResearchPanel.visible = false - if (root.parent.showDetails) { - chatContents.visible = false - swarmDetailsPanel.visible = true - } else { - chatContents.visible = true - swarmDetailsPanel.visible = false + if (visible) { + chatViewSplitView.resolvePanes(true) + + if (root.parent.objectName === "CallViewChatViewContainer") { + chatViewHeader.showSearch = !root.parent.showDetails + if (root.parent.showDetails) { + extrasPanel.switchToPanel(ChatView.SwarmDetailsPanel) + } else { + extrasPanel.closePanel() + } } } } @@ -118,60 +118,9 @@ Rectangle { } onBackClicked: root.dismiss() - - signal panelsVisibilityChange() - - onPanelsVisibilityChange: { - if (!swarmDetailsPanel.visible && !messagesResearchPanel.visible) { - chatContents.visible = true - } else { - if (chatViewHeader.width - JamiTheme.detailsPageMinWidth < JamiTheme.mainViewPaneMinWidth) - chatContents.visible = false - } - } - - onShowDetailsClicked: { - addMemberPanel.visible = false - messagesResearchPanel.visible = false - swarmDetailsPanel.visible = !swarmDetailsPanel.visible - panelsVisibilityChange() - } - - onSearchBarOpened: { - addMemberPanel.visible = false - swarmDetailsPanel.visible = false - messagesResearchPanel.visible = true - panelsVisibilityChange() - } - - onSearchBarClosed: { - chatContents.visible = true - messagesResearchPanel.visible = false - panelsVisibilityChange() - } - - onWidthChanged: { - if (inCallView) - return - const isExpanding = previousWidth < width - - if (!swarmDetailsPanel.visible && !addMemberPanel.visible && !messagesResearchPanel.visible) - return - if (chatViewHeader.width < JamiTheme.detailsPageMinWidth + JamiTheme.mainViewPaneMinWidth - && !isExpanding && chatContents.visible) { - lastContentsSplitSize = chatContents.width - lastDetailsSplitSize = Math.min(JamiTheme.detailsPageMinWidth, (swarmDetailsPanel.visible - ? swarmDetailsPanel.width - : addMemberPanel.visible - ? addMemberPanel.width - : messagesResearchPanel.width)) - chatContents.visible = false - } else if (chatViewHeader.width >= JamiTheme.mainViewPaneMinWidth + lastDetailsSplitSize - && isExpanding && !layoutManager.isFullScreen && !chatContents.visible) { - chatContents.visible = true - } - previousWidth = width - } + onShowDetailsClicked: extrasPanel.switchToPanel(ChatView.SwarmDetailsPanel) + onSearchClicked: extrasPanel.switchToPanel(ChatView.MessagesResearchPanel) + onAddToConversationClicked: extrasPanel.switchToPanel(ChatView.AddMemberPanel) Connections { target: CurrentConversation @@ -183,28 +132,6 @@ Rectangle { } } - Connections { - target: CurrentConversationMembers - - function onCountChanged() { - if (CurrentConversationMembers.count >= 8 && addMemberPanel.visible) { - swarmDetailsPanel.visible = false - addMemberPanel.visible = !addMemberPanel.visible - } - } - } - - onAddToConversationClicked: { - swarmDetailsPanel.visible = false - if (addMemberPanel.visible) { - chatContents.visible = true - } else { - if (chatViewHeader.width - JamiTheme.detailsPageMinWidth < JamiTheme.mainViewPaneMinWidth) - chatContents.visible = false - } - addMemberPanel.visible = !addMemberPanel.visible - } - onPluginSelector: { // Create plugin handler picker - PLUGINS PluginHandlerPickerCreation.createPluginHandlerPickerObjects( @@ -270,20 +197,50 @@ Rectangle { visible: CurrentConversation.activeCalls.length > 0 && !root.inCallView } - SplitView { - id: chatViewMainRow + JamiSplitView { + id: chatViewSplitView + objectName: "ChatViewSplitView" + Layout.fillWidth: true Layout.fillHeight: true - handle: Rectangle { - implicitWidth: JamiTheme.splitViewHandlePreferredWidth - implicitHeight: root.height - color: JamiTheme.primaryBackgroundColor - Rectangle { - implicitWidth: 1 - implicitHeight: root.height - color: JamiTheme.tabbarBorderColor + 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. + function resolvePanes(force=false) { + // 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 + + // 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 + chatContents.visible = false + } else if (width >= JamiTheme.mainViewPaneMinWidth + previousDetailsWidth + && (isExpanding || force) && !chatContents.visible) { + chatContents.visible = true } + if (!force) previousWidth = width + } + + Connections { + target: viewNode + function onPresented() { chatViewSplitView.restoreSplitViewState() } + function onDismissed() { chatViewSplitView.saveSplitViewState() } } ColumnLayout { @@ -358,31 +315,18 @@ Rectangle { } } - MessagesResearchPanel { - id: messagesResearchPanel + onResizingChanged: if (chatContents.visible) extrasPanel.previousWidth = extrasPanel.width - visible: false - SplitView.maximumWidth: root.width - SplitView.minimumWidth: JamiTheme.detailsPageMinWidth - SplitView.preferredWidth: JamiTheme.detailsPageMinWidth - } + ConversationExtrasPanel { + id: extrasPanel - SwarmDetailsPanel { - id: swarmDetailsPanel - visible: false + property int previousWidth: JamiTheme.extrasPanelMinWidth SplitView.maximumWidth: root.width - SplitView.preferredWidth: JamiTheme.detailsPageMinWidth - SplitView.minimumWidth: JamiTheme.detailsPageMinWidth - } - - AddMemberPanel { - id: addMemberPanel - visible: false + SplitView.minimumWidth: JamiTheme.extrasPanelMinWidth + SplitView.preferredWidth: JamiTheme.extrasPanelMinWidth - SplitView.maximumWidth: root.width - SplitView.preferredWidth: JamiTheme.detailsPageMinWidth - SplitView.minimumWidth: JamiTheme.detailsPageMinWidth + onVisibleChanged: chatViewSplitView.resolvePanes(true) } } } diff --git a/src/app/mainview/components/ChatViewHeader.qml b/src/app/mainview/components/ChatViewHeader.qml index 8ac169d16d5a3d27e67815532e1b6e722d8f451c..1de6afe7c71950e63356ab6b2741dc60949cdf06 100644 --- a/src/app/mainview/components/ChatViewHeader.qml +++ b/src/app/mainview/components/ChatViewHeader.qml @@ -37,15 +37,14 @@ Rectangle { signal addToConversationClicked signal pluginSelector signal showDetailsClicked - signal searchBarOpened - signal searchBarClosed + signal searchClicked Connections { target: CurrentConversation enabled: true function onTitleChanged() { title.eText = CurrentConversation.title } function onDescriptionChanged() { description.eText = CurrentConversation.description } - function onShowDetails() { root.showDetailsClicked() } + function onShowSwarmDetails() { root.showDetailsClicked() } } property bool interactionButtonsVisibility: { diff --git a/src/app/mainview/components/ConversationExtrasPanel.qml b/src/app/mainview/components/ConversationExtrasPanel.qml new file mode 100644 index 0000000000000000000000000000000000000000..f5db3f782d37d228e6f8c9814e8157b8e1421894 --- /dev/null +++ b/src/app/mainview/components/ConversationExtrasPanel.qml @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2023 Savoir-faire Linux Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +import QtQuick +import QtQuick.Layouts + +import net.jami.Adapters 1.1 + +StackLayout { + id: root + + property int detailsIndex: -1 + + function isOpen(panel) { return visible && currentIndex === panel } + + visible: currentIndex > -1 + + property bool detailsShouldOpen: false + onVisibleChanged: if (visible) detailsShouldOpen = true + + function restoreState() { + // Only applies to Jami accounts, and we musn't be in a call. + if (detailsShouldOpen && !inCallView && !CurrentConversation.isSip) { + switchToPanel(ChatView.SwarmDetailsPanel, false) + } else { + closePanel() + } + } + + Connections { + target: CurrentConversationMembers + + function onCountChanged() { + // Close the panel if there are 8 or more members in the + // conversation AND the "Add Member" panel is currently open. + if (CurrentConversationMembers.count >= 8 + && isOpen(ChatView.AddMemberPanel)) { + closePanel(); + } + } + } + + // 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 && !CurrentConversation.isSip) + detailsShouldOpen = false + } + + SwarmDetailsPanel { + id: detailsPanel + + property int parentIndex: root.currentIndex + // When we change to the details panel we should load the tab index. + onParentIndexChanged: tabBarIndex = Math.min(tabBarItemsLength - 1, + Math.max(0, root.detailsIndex)) + // Save it when it changes. + onTabBarIndexChanged: root.detailsIndex = tabBarIndex + } + MessagesResearchPanel {} + AddMemberPanel {} +} diff --git a/src/app/mainview/components/MessagesResearchView.qml b/src/app/mainview/components/MessagesResearchView.qml index ed3d263f48201300666ebb9c2f0c021f02385a09..857bc138d01f660815368992af387242c33c50ca 100644 --- a/src/app/mainview/components/MessagesResearchView.qml +++ b/src/app/mainview/components/MessagesResearchView.qml @@ -41,7 +41,9 @@ ListView { property var messageListModel: MessagesAdapter.mediaMessageListModel readonly property int textType: Interaction.Type.TEXT - onMessageListModelChanged: sourceModel = root.visible ? messageListModel : null + onMessageListModelChanged: sourceModel = root.visible && messageListModel ? + messageListModel : + null filters: ExpressionFilter { expression: Type === proxyModel.textType diff --git a/src/app/mainview/components/OngoingCallPage.qml b/src/app/mainview/components/OngoingCallPage.qml index c66bdb3e8407ee57367e834fcdd438158dd5ac81..d73bfd6b847eb3412918c22af39fbd4d14b0ee9e 100644 --- a/src/app/mainview/components/OngoingCallPage.qml +++ b/src/app/mainview/components/OngoingCallPage.qml @@ -400,6 +400,7 @@ Rectangle { Item { id: chatViewContainer + objectName: "CallViewChatViewContainer" SplitView.preferredHeight: mainColumnLayout.isHorizontal ? root.height : diff --git a/src/app/mainview/components/Searchbar.qml b/src/app/mainview/components/Searchbar.qml index 0bce5434065f7bf465ba8f5bd18cb84e6d154903..6fb1d94ab5d3e8bd57653e26df23722a519dd7d4 100644 --- a/src/app/mainview/components/Searchbar.qml +++ b/src/app/mainview/components/Searchbar.qml @@ -28,48 +28,10 @@ import "../../commoncomponents" RowLayout { id: root - property real messagesResearchPanel: JamiTheme.detailsPageMinWidth - - //TO DO: find a design to set dynamically the size of the searchbar - property real searchBarWidth: JamiTheme.searchbarSize - property string currentConversationId: CurrentConversation.id - property bool isOpened: false - - function openSearchBar() { - if (isOpened) { - textArea.forceActiveFocus() - return - } - searchBarOpened() - rectTextArea.isSearch = true - anim.start() - textArea.forceActiveFocus() - isOpened = true - } - - function closeSearchbar() { - if (!isOpened) - return - searchBarClosed() - rectTextArea.isSearch = false - anim.start() - isOpened = false - } - - Connections { - target: chatViewHeader - function onShowDetailsClicked() { - if (rectTextArea.isSearch) - closeSearchbar() - } - } - - onCurrentConversationIdChanged: { - if (isOpened) - closeSearchbar() - } + property bool isOpen: extrasPanel.isOpen(ChatView.MessagesResearchPanel) + onIsOpenChanged: if (isOpen) textArea.forceActiveFocus() PushButton { id: startSearchMessages @@ -78,66 +40,26 @@ RowLayout { normalColor: JamiTheme.chatviewBgColor imageColor: JamiTheme.chatviewButtonColor - onClicked: { - if (rectTextArea.isSearch) - closeSearchbar() - else - openSearchBar() - } + onClicked: chatViewHeader.searchClicked() } - - SequentialAnimation { - id: anim - - PropertyAnimation { - target: rectTextArea; properties: "visible" - to: true - duration: 0 - } - - ParallelAnimation { - - NumberAnimation { - target: rectTextArea; properties: "opacity" - from: rectTextArea.isSearch ? 0 : 1 - to: rectTextArea.isSearch ? 1 : 0 - duration: 150 - } - - NumberAnimation { - target: rectTextArea; properties: "Layout.preferredWidth" - from: rectTextArea.isSearch ? 0 : root.searchBarWidth - to: rectTextArea.isSearch ? root.searchBarWidth : 0 - duration: 150 - } - } - - PropertyAnimation { - target: rectTextArea; properties: "visible" - to: rectTextArea.isSearch - duration: 0 - } - - } Rectangle { id: rectTextArea - visible: false Layout.preferredHeight: startSearchMessages.height Layout.alignment: Qt.AlignVCenter + color: "transparent" border.color: JamiTheme.chatviewTextColor radius: 10 border.width: 2 - property bool isSearch: false - property int textAreaWidth: 200 - property alias searchBarWidth: root.searchBarWidth + opacity: isOpen + visible: opacity + Behavior on opacity { NumberAnimation { duration: 150 } } - onSearchBarWidthChanged: { - Layout.preferredWidth = root.searchBarWidth - } + Layout.preferredWidth: isOpen ? JamiTheme.searchbarSize : 0 + Behavior on Layout.preferredWidth { NumberAnimation { duration: 150 } } TextField { id: textArea diff --git a/src/app/mainview/components/SwarmDetailsPanel.qml b/src/app/mainview/components/SwarmDetailsPanel.qml index c8f92efa10d9f090b83aa3b82987f2b0bbddf4be..e0ccfd065d46baa58f10a6d926846ed8d3ef560b 100644 --- a/src/app/mainview/components/SwarmDetailsPanel.qml +++ b/src/app/mainview/components/SwarmDetailsPanel.qml @@ -32,6 +32,9 @@ import "../../settingsview/components" Rectangle { id: root + property alias tabBarIndex: tabBar.currentIndex + property int tabBarItemsLength: tabBar.contentChildren.length + color: CurrentConversation.color property var isAdmin: !CurrentConversation.isCoreDialog && UtilsAdapter.getParticipantRole(CurrentAccount.id, @@ -193,74 +196,71 @@ Rectangle { currentIndex: 0 - onVisibleChanged: { - tabBar.currentIndex = 0 - } - Layout.preferredWidth: root.width Layout.preferredHeight: settingsTabButton.height - FilterTabButton { - id: settingsTabButton + property string currentItemName: itemAt(currentIndex).objectName + + component DetailsTabButton: FilterTabButton { backgroundColor: CurrentConversation.color hoverColor: CurrentConversation.color borderWidth: 4 bottomMargin: JamiTheme.settingsMarginSize fontSize: JamiTheme.menuFontSize underlineContentOnly: true - - textColorHovered: UtilsAdapter.luma(root.color) ? JamiTheme.placeholderTextColorWhite : JamiTheme.placeholderTextColor + textColorHovered: UtilsAdapter.luma(root.color) ? + JamiTheme.placeholderTextColorWhite : + JamiTheme.placeholderTextColor textColor: UtilsAdapter.luma(root.color) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark - - down: tabBar.currentIndex === 0 - labelText: JamiStrings.settings Layout.fillWidth: true + down: tabBar.currentIndex === TabBar.index } - FilterTabButton { - id: membersTabButton - visible: !CurrentConversation.isCoreDialog - Layout.fillWidth: true - width: visible ? tabBar.width/3 : 0 - backgroundColor: CurrentConversation.color - hoverColor: CurrentConversation.color - borderWidth: 4 - bottomMargin: JamiTheme.settingsMarginSize - fontSize: JamiTheme.menuFontSize - underlineContentOnly: true + function addRemoveButtons() { + if (CurrentConversation.isCoreDialog) { + if (tabBar.contentChildren.length === 3) + tabBar.removeItem(tabBar.itemAt(1)) + } else { + if (tabBar.contentChildren.length === 2) { + const obj = membersTabButtonComp.createObject(tabBar) + tabBar.insertItem(1, obj) + } + } + } - textColorHovered: UtilsAdapter.luma(root.color) ? JamiTheme.placeholderTextColorWhite : JamiTheme.placeholderTextColor - textColor: UtilsAdapter.luma(root.color) ? - JamiTheme.chatviewTextColorLight : - JamiTheme.chatviewTextColorDark + Component.onCompleted: addRemoveButtons() - down: tabBar.currentIndex === 1 - labelText: { - var membersNb = CurrentConversationMembers.count; - if (membersNb > 1) - return JamiStrings.members.arg(membersNb) - return JamiStrings.member - } + Connections { + target: CurrentConversation + function onIsCoreDialogChanged() { tabBar.addRemoveButtons() } } - FilterTabButton { - id: documentsTabButton - backgroundColor: CurrentConversation.color - hoverColor: CurrentConversation.color - borderWidth: 4 - bottomMargin: JamiTheme.settingsMarginSize - fontSize: JamiTheme.menuFontSize - underlineContentOnly: true + Component { + id: membersTabButtonComp + DetailsTabButton { + id: membersTabButton + objectName: "members" + visible: !CurrentConversation.isCoreDialog + labelText: { + var membersNb = CurrentConversationMembers.count; + if (membersNb > 1) + return JamiStrings.members.arg(membersNb) + return JamiStrings.member + } + } + } - Layout.fillWidth: true - textColorHovered: UtilsAdapter.luma(root.color) ? JamiTheme.placeholderTextColorWhite : JamiTheme.placeholderTextColor - textColor: UtilsAdapter.luma(root.color) ? - JamiTheme.chatviewTextColorLight : - JamiTheme.chatviewTextColorDark + DetailsTabButton { + id: settingsTabButton + objectName: "settings" + labelText: JamiStrings.settings + } - down: tabBar.currentIndex === 2 + DetailsTabButton { + id: documentsTabButton + objectName: "documents" labelText: JamiStrings.documents } } @@ -298,7 +298,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.rightMargin: JamiTheme.settingsMarginSize - visible: tabBar.currentIndex === 0 + visible: tabBar.currentItemName === "settings" Layout.alignment: Qt.AlignTop SwarmDetailsItem { @@ -589,7 +589,7 @@ Rectangle { anchors.bottomMargin: JamiTheme.preferredMarginSize anchors.fill: parent - visible: tabBar.currentIndex === 1 + visible: tabBar.currentItemName === "members" SwarmParticipantContextMenu { id: contextMenu @@ -708,7 +708,7 @@ Rectangle { id: documents clip: true - visible: tabBar.currentIndex === 2 + visible: tabBar.currentItemName === "documents" anchors.fill: parent } }