From c52d288c769b9aa5fdfc755a0df731aa51069dcf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
 <sebastien.blin@savoirfairelinux.com>
Date: Fri, 17 Dec 2021 15:52:30 -0500
Subject: [PATCH] messagesadapter: add kick member

GitLab: #340
Change-Id: I4cfdc6392c8b6de573f8d4471b7b5501f393379b
---
 qml.qrc                                       |   1 +
 src/constant/JamiStrings.qml                  |   5 +
 src/mainview/components/SwarmDetailsPanel.qml | 121 ++++++++++++------
 .../SwarmParticipantContextMenu.qml           |  76 +++++++++++
 src/messagesadapter.cpp                       |   7 +
 src/messagesadapter.h                         |   1 +
 6 files changed, 175 insertions(+), 36 deletions(-)
 create mode 100644 src/mainview/components/SwarmParticipantContextMenu.qml

diff --git a/qml.qrc b/qml.qrc
index fd9a00373..2d10eef93 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -109,6 +109,7 @@
         <file>src/mainview/components/SidePanelTabBar.qml</file>
         <file>src/mainview/components/WelcomePageQrDialog.qml</file>
         <file>src/mainview/components/ConversationSmartListContextMenu.qml</file>
+        <file>src/mainview/components/SwarmParticipantContextMenu.qml</file>
         <file>src/mainview/components/CallViewContextMenu.qml</file>
         <file>src/mainview/components/UserProfile.qml</file>
         <file>src/mainview/components/SwarmDetailsPanel.qml</file>
diff --git a/src/constant/JamiStrings.qml b/src/constant/JamiStrings.qml
index 4a88a1ed8..bb1a7917e 100644
--- a/src/constant/JamiStrings.qml
+++ b/src/constant/JamiStrings.qml
@@ -623,4 +623,9 @@ Item {
     // NewSwarmPage
 
     property string createTheSwarm: qsTr("Create the swarm")
+    property string goToConversation: qsTr("Go to conversation")
+    property string promoteAdministrator: qsTr("Promote to administrator")
+    property string kickMember: qsTr("Kick member")
+    property string administrator: qsTr("Administrator")
+    property string invited: qsTr("Invited")
 }
diff --git a/src/mainview/components/SwarmDetailsPanel.qml b/src/mainview/components/SwarmDetailsPanel.qml
index 12bab5f76..8cac190c8 100644
--- a/src/mainview/components/SwarmDetailsPanel.qml
+++ b/src/mainview/components/SwarmDetailsPanel.qml
@@ -48,6 +48,8 @@ Rectangle {
                 Layout.alignment: Qt.AlignCenter
                 Layout.preferredWidth: JamiTheme.avatarSizeInCall
                 Layout.preferredHeight: JamiTheme.avatarSizeInCall
+                Layout.topMargin: JamiTheme.swarmDetailsPageTopMargin
+                Layout.bottomMargin: JamiTheme.preferredMarginSize
 
                 imageId: LRCInstance.selectedConvUid
 
@@ -164,50 +166,97 @@ Rectangle {
                 spacing: JamiTheme.preferredMarginSize
                 anchors.topMargin: JamiTheme.preferredMarginSize
 
-                model: CurrentConversation.uris
-                delegate: RowLayout {
-                    spacing: 10
+                SwarmParticipantContextMenu {
+                    id: contextMenu
 
-                    Avatar {
-                        width: JamiTheme.smartListAvatarSize
-                        height: JamiTheme.smartListAvatarSize
-                        z: -index
+                    function openMenuAt(x, y, participantUri) {
+                        contextMenu.x = x
+                        contextMenu.y = y
+                        contextMenu.conversationId = CurrentConversation.id
+                        contextMenu.participantUri = participantUri
 
-                        imageId: CurrentAccount.uri == modelData ? CurrentAccount.id : modelData
-                        showPresenceIndicator: UtilsAdapter.getContactPresence(CurrentAccount.id, modelData)
-                        mode: CurrentAccount.uri == modelData ? Avatar.Mode.Account : Avatar.Mode.Contact
+                        openMenu()
                     }
+                }
 
-                    ElidedTextLabel {
-                        id: bestName
-
-                        Layout.preferredWidth: JamiTheme.preferredFieldWidth
-                        Layout.preferredHeight: JamiTheme.preferredFieldHeight
-
-                        eText: UtilsAdapter.getContactBestName(CurrentAccount.id, modelData)
-                        maxWidth: JamiTheme.preferredFieldWidth
+                model: CurrentConversation.uris
+                delegate: Item {
 
-                        font.pointSize: JamiTheme.participantFontSize
-                        color: JamiTheme.primaryForegroundColor
-                        font.kerning: true
+                    width: members.width
+                    height: JamiTheme.smartListItemHeight
 
-                        verticalAlignment: Text.AlignVCenter
+                    MouseArea {
+                        anchors.fill: parent
+                        acceptedButtons: Qt.RightButton
+                        onClicked: function (mouse) {
+                            contextMenu.openMenuAt(x + mouse.x, y + mouse.y, modelData)
+                        }
                     }
 
-                    ElidedTextLabel {
-                        id: role
-
-                        Layout.preferredHeight: JamiTheme.preferredFieldHeight
-
-                        eText: UtilsAdapter.getParticipantRole(CurrentAccount.id, CurrentConversation.id, modelData)
-                        maxWidth: JamiTheme.preferredFieldWidth
-
-                        font.pointSize: JamiTheme.participantFontSize
-                        color: JamiTheme.textColorHovered
-                        font.kerning: true
-
-                        horizontalAlignment: Text.AlignRight
-                        verticalAlignment: Text.AlignVCenter
+                    RowLayout {
+                        spacing: 10
+
+                        Avatar {
+                            width: JamiTheme.smartListAvatarSize
+                            height: JamiTheme.smartListAvatarSize
+                            Layout.leftMargin: JamiTheme.preferredMarginSize
+                            z: -index
+                            opacity: {
+                                var role = UtilsAdapter.getParticipantRole(CurrentAccount.id, CurrentConversation.id, modelData)
+                                return role === Member.Role.INVITED ? 0.5 : 1
+                            }
+
+                            imageId: CurrentAccount.uri == modelData ? CurrentAccount.id : modelData
+                            showPresenceIndicator: UtilsAdapter.getContactPresence(CurrentAccount.id, modelData)
+                            mode: CurrentAccount.uri == modelData ? Avatar.Mode.Account : Avatar.Mode.Contact
+                        }
+
+                        ElidedTextLabel {
+                            id: bestName
+
+                            Layout.preferredWidth: JamiTheme.preferredFieldWidth
+                            Layout.preferredHeight: JamiTheme.preferredFieldHeight
+
+                            eText: UtilsAdapter.getContactBestName(CurrentAccount.id, modelData)
+                            maxWidth: JamiTheme.preferredFieldWidth
+
+                            font.pointSize: JamiTheme.participantFontSize
+                            color: JamiTheme.primaryForegroundColor
+                            opacity: {
+                                var role = UtilsAdapter.getParticipantRole(CurrentAccount.id, CurrentConversation.id, modelData)
+                                return role === Member.Role.INVITED ? 0.5 : 1
+                            }
+                            font.kerning: true
+
+                            verticalAlignment: Text.AlignVCenter
+                        }
+
+                        ElidedTextLabel {
+                            id: role
+
+                            Layout.preferredHeight: JamiTheme.preferredFieldHeight
+
+                            eText: {
+                                var role = UtilsAdapter.getParticipantRole(CurrentAccount.id, CurrentConversation.id, modelData)
+                                if (role === Member.Role.ADMIN)
+                                    return JamiStrings.administrator
+                                if (role === Member.Role.INVITED)
+                                    return JamiStrings.invited
+                                return ""
+                            }
+                            maxWidth: JamiTheme.preferredFieldWidth
+
+                            font.pointSize: JamiTheme.participantFontSize
+                            color: JamiTheme.textColorHovered
+                            opacity: {
+                                var role = UtilsAdapter.getParticipantRole(CurrentAccount.id, CurrentConversation.id, modelData)
+                                return role === Member.Role.INVITED ? 0.5 : 1
+                            }
+                            font.kerning: true
+
+                            horizontalAlignment: Text.AlignRight
+                            verticalAlignment: Text.AlignVCenter
+                        }
                     }
                 }
             }
diff --git a/src/mainview/components/SwarmParticipantContextMenu.qml b/src/mainview/components/SwarmParticipantContextMenu.qml
new file mode 100644
index 000000000..17f0df985
--- /dev/null
+++ b/src/mainview/components/SwarmParticipantContextMenu.qml
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2021 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 net.jami.Models 1.1
+import net.jami.Adapters 1.1
+import net.jami.Constants 1.1
+
+import "../../commoncomponents"
+import "../../commoncomponents/contextmenu"
+
+ContextMenuAutoLoader {
+    id: root
+    property var conversationId: ""
+    property var participantUri: ""
+
+    // TODO get authorization
+
+    property list<GeneralMenuItem> menuItems: [
+        GeneralMenuItem {
+            id: startVideoCallItem
+            itemName: JamiStrings.startVideoCall
+            onClicked: {
+            }
+        },
+        GeneralMenuItem {
+            id: startAudioCall
+            itemName: JamiStrings.startAudioCall
+            onClicked: {
+            }
+        },
+        GeneralMenuItem {
+            id: goToConversation
+
+            itemName: JamiStrings.goToConversation
+            onClicked: {
+            }
+        },
+        GeneralMenuItem {
+            id: promoteAdministrator
+            itemName: JamiStrings.promoteAdministrator
+        },
+        GeneralMenuItem {
+            id: blockContact
+            itemName: JamiStrings.blockContact
+            iconSource: JamiResources.block_black_24dp_svg
+        },
+        GeneralMenuItem {
+            id: kickMember
+            itemName: JamiStrings.kickMember
+
+            // TODO can trigger (enough permission for self and member accepted)
+            onClicked: {
+                MessagesAdapter.removeConversationMember(conversationId, participantUri)
+            }
+        }
+    ]
+
+    Component.onCompleted: menuItemsToLoad = menuItems
+}
diff --git a/src/messagesadapter.cpp b/src/messagesadapter.cpp
index 64ed54c7f..fb4a4c0a8 100644
--- a/src/messagesadapter.cpp
+++ b/src/messagesadapter.cpp
@@ -384,6 +384,13 @@ MessagesAdapter::removeConversation(const QString& convUid)
     accInfo.conversationModel->removeConversation(convUid);
 }
 
+void
+MessagesAdapter::removeConversationMember(const QString& convUid, const QString& memberUri)
+{
+    auto& accInfo = lrcInstance_->getCurrentAccountInfo();
+    accInfo.conversationModel->removeConversationMember(convUid, memberUri);
+}
+
 void
 MessagesAdapter::removeContact(const QString& convUid, bool banContact)
 {
diff --git a/src/messagesadapter.h b/src/messagesadapter.h
index c64cef545..1840cb6aa 100644
--- a/src/messagesadapter.h
+++ b/src/messagesadapter.h
@@ -85,6 +85,7 @@ protected:
     Q_INVOKABLE void connectConversationModel();
     Q_INVOKABLE void sendConversationRequest();
     Q_INVOKABLE void removeConversation(const QString& convUid);
+    Q_INVOKABLE void removeConversationMember(const QString& convUid, const QString& participantUri);
     Q_INVOKABLE void removeContact(const QString& convUid, bool banContact = false);
     Q_INVOKABLE void clearConversationHistory(const QString& accountId, const QString& convUid);
     Q_INVOKABLE void acceptInvitation(const QString& convId = {});
-- 
GitLab