From e47fa5830e962bf95014a586fb65d6cb80b14dd2 Mon Sep 17 00:00:00 2001
From: agsantos <aline.gondimsantos@savoirfairelinux.com>
Date: Tue, 26 Oct 2021 11:42:24 -0400
Subject: [PATCH] conference: add handsUp feature

GitLab: jami-project#855
Change-Id: I7b2b2b76310743b7b330bfa4c1f123306288b1fa
---
 src/api/newcallmodel.h           | 23 ++++++++++++++-
 src/newcallmodel.cpp             | 49 +++++++++++++++++++++++++++++---
 src/qtwrapper/callmanager_wrap.h |  8 ++++++
 3 files changed, 75 insertions(+), 5 deletions(-)

diff --git a/src/api/newcallmodel.h b/src/api/newcallmodel.h
index 47df435a..327462b3 100644
--- a/src/api/newcallmodel.h
+++ b/src/api/newcallmodel.h
@@ -80,7 +80,9 @@ public:
      * @param  isAudioOnly, set to false by default
      * @return the call uid created. Empty string is returned if call couldn't be created.
      */
-    QString createCall(const QString& uri, bool isAudioOnly = false, VectorMapStringString mediaList = {});
+    QString createCall(const QString& uri,
+                       bool isAudioOnly = false,
+                       VectorMapStringString mediaList = {});
 
     /**
      * Request a media change in a ongoing call.
@@ -286,6 +288,25 @@ public:
      */
     void setModerator(const QString& confId, const QString& peerId, const bool& state);
 
+    /**
+     * Check if a participant has raised hand
+     * @param confId        The conference to check
+     * @param uri           Uri of the participant to check (if empty, check current account)
+     * @return if hand is raised
+     */
+    bool isHandRaised(const QString& confId, const QString& uri = "") noexcept;
+
+    /**
+     * Set/unset a moderator
+     * @param confId        The conference to change
+     * @param peerId        Uri of the participant to change
+     * @param state         State of the change (true set hand raised / false unset hand raised)
+     */
+    void setHandRaised(const QString& accountId,
+                       const QString& confId,
+                       const QString& peerId,
+                       bool state);
+
     /**
      * Mute/unmute participant
      * @param confId        The conference to change
diff --git a/src/newcallmodel.cpp b/src/newcallmodel.cpp
index 0d26ae6f..886fdc7d 100644
--- a/src/newcallmodel.cpp
+++ b/src/newcallmodel.cpp
@@ -358,7 +358,11 @@ NewCallModel::createCall(const QString& uri, bool isAudioOnly, VectorMapStringSt
 }
 
 void
-NewCallModel::requestMediaChange(const QString& callId, const QString& mediaLabel, const QString& uri, MediaRequestType type, bool mute)
+NewCallModel::requestMediaChange(const QString& callId,
+                                 const QString& mediaLabel,
+                                 const QString& uri,
+                                 MediaRequestType type,
+                                 bool mute)
 {
     // Main audio: audio_0
     // Main video: video_0
@@ -434,7 +438,8 @@ NewCallModel::requestMediaChange(const QString& callId, const QString& mediaLabe
             item[MediaAttributeKey::ENABLED] = "true";
             item[MediaAttributeKey::MUTED] = mute ? "true" : "false";
             item[MediaAttributeKey::SOURCE_TYPE] = srctype;
-            item[MediaAttributeKey::SOURCE] = resource.isEmpty() ? item[MediaAttributeKey::SOURCE] : resource;
+            item[MediaAttributeKey::SOURCE] = resource.isEmpty() ? item[MediaAttributeKey::SOURCE]
+                                                                 : resource;
 
             break;
         }
@@ -446,8 +451,7 @@ NewCallModel::requestMediaChange(const QString& callId, const QString& mediaLabe
         MapStringString mediaAttribute = {{MediaAttributeKey::MEDIA_TYPE,
                                            MediaAttributeValue::VIDEO},
                                           {MediaAttributeKey::ENABLED, "true"},
-                                          {MediaAttributeKey::MUTED,
-                                           mute ? "true" : "false"},
+                                          {MediaAttributeKey::MUTED, mute ? "true" : "false"},
                                           {MediaAttributeKey::SOURCE_TYPE, srctype},
                                           {MediaAttributeKey::SOURCE, resource},
                                           {MediaAttributeKey::LABEL, mediaLabel}};
@@ -981,6 +985,43 @@ NewCallModel::setModerator(const QString& confId, const QString& peerId, const b
     CallManager::instance().setModerator(confId, peerId, state);
 }
 
+bool
+NewCallModel::isHandRaised(const QString& confId, const QString& uri) noexcept
+{
+    auto call = pimpl_->calls.find(confId);
+    if (call == pimpl_->calls.end() or not call->second)
+        return false;
+    auto ownerUri = owner.profileInfo.uri;
+    auto uriToCheck = uri;
+    if (uriToCheck.isEmpty()) {
+        uriToCheck = ownerUri;
+    }
+    auto handRaised = false;
+    for (const auto& participant : call->second->participantsInfos) {
+        auto itUri = participant.find("uri");
+        auto itHand = participant.find("handRaised");
+        if (itUri != participant.end() && itHand != participant.end() && *itUri == uriToCheck) {
+            handRaised = participant["handRaised"] == "true";
+            break;
+        }
+    }
+    return handRaised;
+}
+
+void
+NewCallModel::setHandRaised(const QString& accountId,
+                            const QString& confId,
+                            const QString& peerId,
+                            bool state)
+{
+    auto ownerUri = owner.profileInfo.uri;
+    auto uriToCheck = peerId;
+    if (uriToCheck.isEmpty()) {
+        uriToCheck = ownerUri;
+    }
+    CallManager::instance().raiseParticipantHand(accountId, confId, uriToCheck, state);
+}
+
 void
 NewCallModel::muteParticipant(const QString& confId, const QString& peerId, const bool& state)
 {
diff --git a/src/qtwrapper/callmanager_wrap.h b/src/qtwrapper/callmanager_wrap.h
index 6fa93798..36759b0a 100644
--- a/src/qtwrapper/callmanager_wrap.h
+++ b/src/qtwrapper/callmanager_wrap.h
@@ -450,6 +450,14 @@ public Q_SLOTS: // METHODS
         DRing::setModerator(confId.toStdString(), peerId.toStdString(), state);
     }
 
+    void raiseParticipantHand(const QString& accountId,
+                              const QString& confId,
+                              const QString& peerId,
+                              const bool& state)
+    {
+        DRing::raiseParticipantHand(accountId.toStdString(), confId.toStdString(), peerId.toStdString(), state);
+    }
+
     void muteParticipant(const QString& confId, const QString& peerId, const bool& state)
     {
         DRing::muteParticipant(confId.toStdString(), peerId.toStdString(), state);
-- 
GitLab