Skip to content
Snippets Groups Projects
Unverified Commit 76896e79 authored by Sébastien Blin's avatar Sébastien Blin
Browse files

chatview: add the swarm details page in a stackview

This allow the swarm details page to be resizable.

Also adds the add members list into this view.
Presence and filtering for ContactPicker is also
fixed.

GitLab: #670
Change-Id: I4bf4369eba1d30dff3931575cd8ebd7eb2c7aee0
parent f45fda36
No related branches found
No related tags found
No related merge requests found
...@@ -112,6 +112,7 @@ ...@@ -112,6 +112,7 @@
<file>src/mainview/components/CallViewContextMenu.qml</file> <file>src/mainview/components/CallViewContextMenu.qml</file>
<file>src/mainview/components/UserProfile.qml</file> <file>src/mainview/components/UserProfile.qml</file>
<file>src/mainview/components/SwarmDetailsPanel.qml</file> <file>src/mainview/components/SwarmDetailsPanel.qml</file>
<file>src/mainview/components/AddMemberPanel.qml</file>
<file>src/mainview/components/SelectScreen.qml</file> <file>src/mainview/components/SelectScreen.qml</file>
<file>src/mainview/components/ScreenRubberBand.qml</file> <file>src/mainview/components/ScreenRubberBand.qml</file>
<file>src/mainview/components/ContactPicker.qml</file> <file>src/mainview/components/ContactPicker.qml</file>
......
...@@ -368,6 +368,9 @@ Item { ...@@ -368,6 +368,9 @@ Item {
property real mainViewPreferredWidth: 725 property real mainViewPreferredWidth: 725
property real mainViewPreferredHeight: 600 property real mainViewPreferredHeight: 600
// Details page
property real detailsPageMinWidth: 300
function setTheme(dark) { function setTheme(dark) {
darkTheme = dark darkTheme = dark
} }
......
...@@ -32,6 +32,18 @@ ContactAdapter::ContactAdapter(LRCInstance* instance, QObject* parent) ...@@ -32,6 +32,18 @@ ContactAdapter::ContactAdapter(LRCInstance* instance, QObject* parent)
} }
} }
bool
ContactAdapter::hasDifferentMembers(const VectorString& currentMembers,
const VectorString& convMembers) const
{
for (const auto& uri : convMembers) {
if (uri != lrcInstance_->getCurrentAccountInfo().profileInfo.uri
&& !currentMembers.contains(uri))
return true;
}
return false;
}
QVariant QVariant
ContactAdapter::getContactSelectableModel(int type) ContactAdapter::getContactSelectableModel(int type)
{ {
...@@ -54,11 +66,16 @@ ContactAdapter::getContactSelectableModel(int type) ...@@ -54,11 +66,16 @@ ContactAdapter::getContactSelectableModel(int type)
return !defaultModerators_.contains(index.data(Role::URI).toString()); return !defaultModerators_.contains(index.data(Role::URI).toString());
}); });
break; break;
case SmartListModel::Type::ADDCONVMEMBER: case SmartListModel::Type::ADDCONVMEMBER: {
selectableProxyModel_->setPredicate([](const QModelIndex& index, const QRegularExpression&) { auto currentConvID = lrcInstance_->get_selectedConvUid();
return index.data(Role::IsCoreDialog).toBool(); auto* convModel = lrcInstance_->getCurrentConversationModel();
}); auto members = convModel->peersForConversation(currentConvID);
selectableProxyModel_->setPredicate(
[this, members](const QModelIndex& index, const QRegularExpression&) {
return hasDifferentMembers(members, index.data(Role::Uris).toStringList());
});
break; break;
}
case SmartListModel::Type::CONFERENCE: case SmartListModel::Type::CONFERENCE:
selectableProxyModel_->setPredicate([](const QModelIndex& index, const QRegularExpression&) { selectableProxyModel_->setPredicate([](const QModelIndex& index, const QRegularExpression&) {
return index.data(Role::Presence).toBool(); return index.data(Role::Presence).toBool();
...@@ -107,15 +124,18 @@ ContactAdapter::setSearchFilter(const QString& filter) ...@@ -107,15 +124,18 @@ ContactAdapter::setSearchFilter(const QString& filter)
&& index.data(Role::Title).toString().contains(filter)); && index.data(Role::Title).toString().contains(filter));
}); });
} else if (listModeltype_ == SmartListModel::Type::ADDCONVMEMBER) { } else if (listModeltype_ == SmartListModel::Type::ADDCONVMEMBER) {
selectableProxyModel_->setPredicate( auto currentConvID = lrcInstance_->get_selectedConvUid();
[this, filter](const QModelIndex& index, const QRegularExpression&) { auto* convModel = lrcInstance_->getCurrentConversationModel();
return (index.data(Role::Title).toString().contains(filter, Qt::CaseInsensitive) auto members = convModel->peersForConversation(currentConvID);
|| index.data(Role::RegisteredName) selectableProxyModel_->setPredicate([this, filter, members](const QModelIndex& index,
.toString() const QRegularExpression&) {
.contains(filter, Qt::CaseInsensitive) return hasDifferentMembers(members, index.data(Role::Uris).toStringList())
|| index.data(Role::URI).toString().contains(filter, Qt::CaseInsensitive)) && (index.data(Role::Title).toString().contains(filter, Qt::CaseInsensitive)
&& index.data(Role::IsCoreDialog).toBool(); || index.data(Role::RegisteredName)
}); .toString()
.contains(filter, Qt::CaseInsensitive)
|| index.data(Role::Uris).toString().contains(filter, Qt::CaseInsensitive));
});
} }
selectableProxyModel_->setFilterRegularExpression( selectableProxyModel_->setFilterRegularExpression(
QRegularExpression(filter, QRegularExpression::CaseInsensitiveOption)); QRegularExpression(filter, QRegularExpression::CaseInsensitiveOption));
...@@ -132,8 +152,16 @@ ContactAdapter::contactSelected(int index) ...@@ -132,8 +152,16 @@ ContactAdapter::contactSelected(int index)
if (contactIndex.isValid()) { if (contactIndex.isValid()) {
switch (listModeltype_) { switch (listModeltype_) {
case SmartListModel::Type::ADDCONVMEMBER: { case SmartListModel::Type::ADDCONVMEMBER: {
const auto uri = contactIndex.data(Role::URI).value<QString>(); auto members = convModel->peersForConversation(lrcInstance_->get_selectedConvUid());
convModel->addConversationMember(lrcInstance_->get_selectedConvUid(), uri); auto cntMembers = members.size();
const auto uris = contactIndex.data(Role::Uris).toStringList();
for (const auto& uri : uris) {
// TODO remove < 9
if (!members.contains(uri) && cntMembers < 9) {
cntMembers++;
convModel->addConversationMember(lrcInstance_->get_selectedConvUid(), uri);
}
}
break; break;
} }
case SmartListModel::Type::CONFERENCE: { case SmartListModel::Type::CONFERENCE: {
......
...@@ -104,6 +104,8 @@ private: ...@@ -104,6 +104,8 @@ private:
QStringList defaultModerators_; QStringList defaultModerators_;
bool hasDifferentMembers(const VectorString& currentMembers, const VectorString& convMembers) const;
Q_SIGNALS: Q_SIGNALS:
void defaultModeratorsUpdated(); void defaultModeratorsUpdated();
}; };
/*
* Copyright (C) 2022 by Savoir-faire Linux
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* 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.Controls
import QtQuick.Layouts
import net.jami.Models 1.1
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
import "../../commoncomponents"
Rectangle {
id: root
color: JamiTheme.backgroundColor
property int type: ContactList.ADDCONVMEMBER
width: 250
ColumnLayout {
id: contactPickerPopupRectColumnLayout
anchors.top: root.top
anchors.bottom: root.bottom
anchors.margins: 16
ContactSearchBar {
id: contactPickerContactSearchBar
Layout.alignment: Qt.AlignCenter
Layout.margins: 5
Layout.fillWidth: true
Layout.preferredHeight: 35
placeHolderText: JamiStrings.addParticipant
onContactSearchBarTextChanged: {
ContactAdapter.setSearchFilter(text)
}
}
JamiListView {
id: contactPickerListView
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: root.width - 8
Layout.preferredHeight: contactPickerPopupRectColumnLayout.height - contactPickerContactSearchBar.height
model: ContactAdapter.getContactSelectableModel(type)
Connections {
enabled: visible
target: CurrentConversation
onUrisChanged: {
model = ContactAdapter.getContactSelectableModel(type)
}
}
onVisibleChanged: {
if (visible)
model = ContactAdapter.getContactSelectableModel(type)
}
delegate: ContactPickerItemDelegate {
id: contactPickerItemDelegate
showPresenceIndicator: true
}
}
}
}
...@@ -44,6 +44,7 @@ Rectangle { ...@@ -44,6 +44,7 @@ Rectangle {
function focusChatView() { function focusChatView() {
chatViewFooter.textInput.forceActiveFocus() chatViewFooter.textInput.forceActiveFocus()
swarmDetailsPanel.visible = false swarmDetailsPanel.visible = false
addMemberPanel.visible = false
} }
color: JamiTheme.chatviewBgColor color: JamiTheme.chatviewBgColor
...@@ -78,9 +79,26 @@ Rectangle { ...@@ -78,9 +79,26 @@ Rectangle {
} }
onShowDetailsClicked: { onShowDetailsClicked: {
addMemberPanel.visible = false
swarmDetailsPanel.visible = !swarmDetailsPanel.visible swarmDetailsPanel.visible = !swarmDetailsPanel.visible
} }
Connections {
target: CurrentConversation
onUrisChanged: {
if (CurrentConversation.uris.length >= 8 && addMemberPanel.visible) {
swarmDetailsPanel.visible = false
addMemberPanel.visible = !addMemberPanel.visible
}
}
}
onAddToConversationClicked: {
swarmDetailsPanel.visible = false
addMemberPanel.visible = !addMemberPanel.visible
}
onPluginSelector: { onPluginSelector: {
// Create plugin handler picker - PLUGINS // Create plugin handler picker - PLUGINS
PluginHandlerPickerCreation.createPluginHandlerPickerObjects( PluginHandlerPickerCreation.createPluginHandlerPickerObjects(
...@@ -91,14 +109,27 @@ Rectangle { ...@@ -91,14 +109,27 @@ Rectangle {
} }
} }
RowLayout { SplitView {
id: chatViewMainRow id: chatViewMainRow
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
handle: Rectangle {
implicitWidth: JamiTheme.splitViewHandlePreferredWidth
implicitHeight: splitView.height
color: JamiTheme.primaryBackgroundColor
Rectangle {
implicitWidth: 1
implicitHeight: splitView.height
color: JamiTheme.tabbarBorderColor
}
}
ColumnLayout { ColumnLayout {
Layout.fillHeight: true SplitView.maximumWidth: splitView.width
Layout.fillWidth: true // Note, without JamiTheme.detailsPageMinWidth, sometimes the details page is hidden at the right
SplitView.preferredWidth: Math.max(0, 2 * splitView.width / 3 - JamiTheme.detailsPageMinWidth)
SplitView.fillHeight: true
StackLayout { StackLayout {
id: chatViewStack id: chatViewStack
...@@ -162,6 +193,23 @@ Rectangle { ...@@ -162,6 +193,23 @@ Rectangle {
SwarmDetailsPanel { SwarmDetailsPanel {
id: swarmDetailsPanel id: swarmDetailsPanel
visible: false visible: false
SplitView.maximumWidth: splitView.width
SplitView.preferredWidth: Math.max(JamiTheme.detailsPageMinWidth, splitView.width / 3)
SplitView.minimumWidth: JamiTheme.detailsPageMinWidth
SplitView.fillHeight: true
Layout.fillHeight: true
Layout.fillWidth: true
}
AddMemberPanel {
id: addMemberPanel
visible: false
SplitView.maximumWidth: splitView.width
SplitView.preferredWidth: Math.max(JamiTheme.detailsPageMinWidth, splitView.width / 3)
SplitView.minimumWidth: JamiTheme.detailsPageMinWidth
SplitView.fillHeight: true
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
} }
......
...@@ -25,7 +25,6 @@ import net.jami.Constants 1.1 ...@@ -25,7 +25,6 @@ import net.jami.Constants 1.1
import net.jami.Adapters 1.1 import net.jami.Adapters 1.1
import "../../commoncomponents" import "../../commoncomponents"
import "../js/contactpickercreation.js" as ContactPickerCreation
Rectangle { Rectangle {
id: root id: root
...@@ -35,6 +34,7 @@ Rectangle { ...@@ -35,6 +34,7 @@ Rectangle {
signal backClicked signal backClicked
signal needToHideConversationInCall signal needToHideConversationInCall
signal addToConversationClicked
signal pluginSelector signal pluginSelector
signal showDetailsClicked signal showDetailsClicked
...@@ -61,11 +61,6 @@ Rectangle { ...@@ -61,11 +61,6 @@ Rectangle {
color: JamiTheme.chatviewBgColor color: JamiTheme.chatviewBgColor
function addToConversationClicked() {
ContactPickerCreation.createContactPickerObjects(ContactList.ADDCONVMEMBER, root)
ContactPickerCreation.openContactPicker()
}
RowLayout { RowLayout {
id: messagingHeaderRectRowLayout id: messagingHeaderRectRowLayout
...@@ -185,15 +180,15 @@ Rectangle { ...@@ -185,15 +180,15 @@ Rectangle {
PushButton { PushButton {
id: addParticipantsButton id: addParticipantsButton
visible: addMemberVisibility
source: JamiResources.add_people_24dp_svg source: JamiResources.add_people_24dp_svg
toolTipText: JamiStrings.addParticipants toolTipText: JamiStrings.addParticipants
normalColor: JamiTheme.chatviewBgColor normalColor: JamiTheme.chatviewBgColor
imageColor: JamiTheme.chatviewButtonColor imageColor: JamiTheme.chatviewButtonColor
onClicked: root.addToConversationClicked() visible: CurrentConversation.uris.length < 8 && addMemberVisibility
onClicked: addToConversationClicked()
} }
PushButton { PushButton {
......
...@@ -28,7 +28,9 @@ import "../../commoncomponents" ...@@ -28,7 +28,9 @@ import "../../commoncomponents"
ItemDelegate { ItemDelegate {
id: contactPickerItemDelegate id: contactPickerItemDelegate
property alias showPresenceIndicator: avatar.showPresenceIndicator property var showPresenceIndicator: false
signal contactClicked
ConversationAvatar { ConversationAvatar {
id: avatar id: avatar
...@@ -41,6 +43,8 @@ ItemDelegate { ...@@ -41,6 +43,8 @@ ItemDelegate {
height: 40 height: 40
imageId: UID imageId: UID
showPresenceIndicator: contactPickerItemDelegate.showPresenceIndicator && Presence
} }
Rectangle { Rectangle {
...@@ -102,7 +106,7 @@ ItemDelegate { ...@@ -102,7 +106,7 @@ ItemDelegate {
color: JamiTheme.backgroundColor color: JamiTheme.backgroundColor
implicitWidth: contactPickerPopupRect.width implicitWidth: root.width
implicitHeight: Math.max( implicitHeight: Math.max(
contactPickerContactName.height contactPickerContactName.height
+ textMetricsContactPickerContactId.height + 10, + textMetricsContactPickerContactId.height + 10,
...@@ -125,7 +129,10 @@ ItemDelegate { ...@@ -125,7 +129,10 @@ ItemDelegate {
itemSmartListBackground.color = JamiTheme.normalButtonColor itemSmartListBackground.color = JamiTheme.normalButtonColor
ContactAdapter.contactSelected(index) ContactAdapter.contactSelected(index)
contactPickerPopup.close() root.contactClicked()
// TODO remove from there
if (contactPickerPopup)
contactPickerPopup.close()
} }
onEntered: { onEntered: {
......
/* /*
* Copyright (C) 2021 by Savoir-faire Linux * Copyright (C) 2022 by Savoir-faire Linux
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment