From a79ea5fd3f25bfea9e13f7696363634b442b659f Mon Sep 17 00:00:00 2001 From: agsantos <aline.gondimsantos@savoirfairelinux.com> Date: Tue, 26 Oct 2021 11:42:35 -0400 Subject: [PATCH] conference: add handsUp feature GitLab: jami-project#855 Change-Id: Ic76b717fb70f5c8aec332f92ed38ecb57fbaaa16 --- resources/icons/hand_black_24dp.svg | 14 ++++++++++ src/calladapter.cpp | 26 +++++++++++++++++++ src/calladapter.h | 2 ++ src/constant/JamiStrings.qml | 2 ++ src/mainview/components/CallActionBar.qml | 17 ++++++++++++ src/mainview/components/CallOverlay.qml | 2 ++ .../components/ParticipantControlLayout.qml | 12 +++++++++ .../components/ParticipantOverlay.qml | 18 +++++++++++++ .../components/ParticipantOverlayMenu.qml | 1 + 9 files changed, 94 insertions(+) create mode 100644 resources/icons/hand_black_24dp.svg diff --git a/resources/icons/hand_black_24dp.svg b/resources/icons/hand_black_24dp.svg new file mode 100644 index 000000000..17cdd0281 --- /dev/null +++ b/resources/icons/hand_black_24dp.svg @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve"> +<path d="M18,6.7L18,6.7c-0.2,0-0.7,0.1-0.8,0.2V5.5c0-1-0.5-1.9-1.5-1.9c-0.2,0-0.7,0-0.8,0.1C15,2.9,14.3,2,13.4,2l0,0 + c-0.7,0-1.3,0.4-1.6,0.9C11,2.6,10,2.8,9.5,3.6c-0.2,0.3-0.3,0.6-0.3,1v9.8l-1-1c-0.8-0.8-2-1.1-3.1-0.7c-0.4,0.1-0.6,0.4-0.8,0.7 + c-0.2,0.3-0.2,0.7-0.1,1.1c0,0.1,0.1,0.2,0.2,0.3l2.3,4c0.4,0.6,0.9,1.1,1.4,1.6c1,1.1,2.8,1.6,4.3,1.6l0,0h2c2.3,0,3.8-1.4,4.7-3.5 + c0.2-0.6,0.4-1.2,0.4-1.9V8.5C19.5,7.8,19.2,6.9,18,6.7z M12.2,11.5c0.3,0,0.6-0.3,0.6-0.6v-7c0-0.3,0.2-0.5,0.5-0.5 + s0.5,0.2,0.5,0.5v7.4c0,0.3,0.3,0.6,0.6,0.6s0.6-0.3,0.6-0.6V5.4c0-0.3,0.2-0.5,0.5-0.5S16,5.1,16,5.4V12c0,0.3,0.3,0.6,0.6,0.6 + c0.3,0,0.6-0.3,0.6-0.6V8.5c0-0.3,0.2-0.5,0.5-0.5s0.5,0.2,0.5,0.5v8.1c0,0.5-0.1,0.9-0.3,1.4c-0.7,1.7-2.2,2.7-4,2.7l0,0H12 + c-1.1,0-2.3-0.5-3.1-1.3c-0.5-0.5-0.9-1-1.2-1.6L5.5,14v-0.1c0,0,0-0.1,0.1-0.1c0.2-0.1,0.4-0.1,0.5-0.1c0.5,0,0.9,0.2,1.2,0.5 + l1.2,1.2c0.4,0.4,1.2,0.4,1.6,0c0.2-0.2,0.3-0.5,0.3-0.8v-10C10.5,4.3,10.7,4,11,4s0.5,0.2,0.5,0.5v6.2 + C11.5,11.2,11.8,11.5,12.2,11.5z M18,6.9L18,6.9L18,6.9L18,6.9z"/> +</svg> diff --git a/src/calladapter.cpp b/src/calladapter.cpp index 42b2cc4aa..73547d455 100644 --- a/src/calladapter.cpp +++ b/src/calladapter.cpp @@ -842,6 +842,32 @@ CallAdapter::isModerator(const QString& uri) const return false; } +bool +CallAdapter::isHandRaised(const QString& uri) const +{ + auto* callModel = lrcInstance_->getAccountInfo(accountId_).callModel.get(); + const auto& convInfo = lrcInstance_->getConversationFromConvUid(convUid_); + auto confId = convInfo.confId; + + if (confId.isEmpty()) + confId = convInfo.callId; + return callModel->isHandRaised(confId, uri); +} + +void +CallAdapter::setHandRaised(const QString& uri, bool state) +{ + auto* callModel = lrcInstance_->getAccountInfo(accountId_).callModel.get(); + const auto& convInfo = lrcInstance_->getConversationFromConvUid(convUid_); + auto confId = convInfo.confId; + if (confId.isEmpty()) + confId = convInfo.callId; + try { + callModel->setHandRaised(accountId_, confId, uri, state); + } catch (...) { + } +} + bool CallAdapter::isCurrentModerator() const { diff --git a/src/calladapter.h b/src/calladapter.h index 1187ef6c8..804e0dab3 100644 --- a/src/calladapter.h +++ b/src/calladapter.h @@ -67,6 +67,8 @@ public: Q_INVOKABLE bool participantIsHost(const QString& uri) const; Q_INVOKABLE void setModerator(const QString& uri, const bool state); Q_INVOKABLE bool isModerator(const QString& uri = {}) const; + Q_INVOKABLE bool isHandRaised(const QString& uri = {}) const; + Q_INVOKABLE void setHandRaised(const QString& uri, bool state); Q_INVOKABLE bool isCurrentModerator() const; Q_INVOKABLE void holdThisCallToggle(); Q_INVOKABLE void muteThisCallToggle(bool mute); diff --git a/src/constant/JamiStrings.qml b/src/constant/JamiStrings.qml index 5e6cb5bd4..a54d991f1 100644 --- a/src/constant/JamiStrings.qml +++ b/src/constant/JamiStrings.qml @@ -247,6 +247,8 @@ Item { property string viewPlugin: qsTr("View plugin") property string noVideoDevice: qsTr("No video device") property string notAvailable: qsTr("N/A") + property string lowerHand: qsTr("Lower hand") + property string raiseHand: qsTr("Raise hand") // Chatview header property string hideChatView: qsTr("Hide chat view") diff --git a/src/mainview/components/CallActionBar.qml b/src/mainview/components/CallActionBar.qml index 4d3e56535..3dcece673 100644 --- a/src/mainview/components/CallActionBar.qml +++ b/src/mainview/components/CallActionBar.qml @@ -253,6 +253,17 @@ Control { property real size: 34 property var menuAction: shareMenuAction }, + Action { + id: raiseHandAction + onTriggered: CallAdapter.setHandRaised("", !CallAdapter.isHandRaised()) + checkable: true + icon.source: JamiResources.hand_black_24dp_svg + icon.color: checked ? "red" : "white" + text: checked ? + JamiStrings.lowerHand : + JamiStrings.raiseHand + property real size: 34 + }, Action { id: recordAction onTriggered: CallAdapter.recordThisCallToggle() @@ -288,6 +299,8 @@ Control { function onIsAudioMutedChanged() { reset() } function onIsVideoMutedChanged() { reset() } function onIsRecordingChanged() { reset() } + function onLocalHandRaisedChanged() { reset() } + function onIsConferenceCallChanged() { reset() } } function reset() { @@ -300,6 +313,10 @@ Control { // overflow controls CallOverlayModel.addSecondaryControl(audioOutputAction) + if (isConferenceCall) { + CallOverlayModel.addSecondaryControl(raiseHandAction) + raiseHandAction.checked = CallAdapter.isHandRaised() + } if (isModerator && !isSIP) CallOverlayModel.addSecondaryControl(addPersonAction) if (isSIP) { diff --git a/src/mainview/components/CallOverlay.qml b/src/mainview/components/CallOverlay.qml index f5334aa5d..5ffec761e 100644 --- a/src/mainview/components/CallOverlay.qml +++ b/src/mainview/components/CallOverlay.qml @@ -45,6 +45,7 @@ Item { property bool isModerator property bool isConferenceCall property bool isGrid + property bool localHandRaised signal chatButtonClicked @@ -73,6 +74,7 @@ Item { root.isConferenceCall = isConferenceCall root.isGrid = isGrid mainOverlay.recordingVisible = isRecording + root.localHandRaised = CallAdapter.isHandRaised() } root.isModerator = CallAdapter.isCurrentModerator() } diff --git a/src/mainview/components/ParticipantControlLayout.qml b/src/mainview/components/ParticipantControlLayout.qml index e88061257..c88b092de 100644 --- a/src/mainview/components/ParticipantControlLayout.qml +++ b/src/mainview/components/ParticipantControlLayout.qml @@ -84,6 +84,18 @@ RowLayout { toolTipText: JamiStrings.minimizeParticipant } + ParticipantOverlayButton { + id: lowerHandParticipant + + visible: showLowerHand + preferredSize: iconButtonPreferredSize + Layout.preferredHeight: buttonPreferredSize + Layout.preferredWidth: buttonPreferredSize + source: JamiResources.hand_black_24dp_svg + onClicked: CallAdapter.setHandRaised(uri, false) + toolTipText: JamiStrings.lowerHand + } + ParticipantOverlayButton { id: hangupParticipant diff --git a/src/mainview/components/ParticipantOverlay.qml b/src/mainview/components/ParticipantOverlay.qml index dd6ea64a2..42bd9e0bc 100644 --- a/src/mainview/components/ParticipantOverlay.qml +++ b/src/mainview/components/ParticipantOverlay.qml @@ -46,6 +46,7 @@ Item { property bool participantIsModerator: false property bool participantIsMuted: false property bool participantIsModeratorMuted: false + property bool participantHandIsRaised: false z: 1 @@ -69,6 +70,7 @@ Item { participantIsHost = CallAdapter.participantIsHost(overlayMenu.uri) participantIsModerator = CallAdapter.isModerator(overlayMenu.uri) participantIsActive = isActive + participantHandIsRaised = CallAdapter.isHandRaised(overlayMenu.uri) overlayMenu.showSetModerator = isHost && !isLocal && !participantIsModerator overlayMenu.showUnsetModerator = isHost && !isLocal && participantIsModerator @@ -85,6 +87,7 @@ Item { overlayMenu.showMaximize = isModerator && showMax overlayMenu.showMinimize = isModerator && participantIsActive overlayMenu.showHangup = isModerator && !isLocal && !participantIsHost + overlayMenu.showLowerHand = isModerator && participantHandIsRaised } // Participant header with host, moderator and mute indicators @@ -156,6 +159,21 @@ Item { source: JamiResources.mic_off_24dp_svg color: JamiTheme.whiteColor } + + ResponsiveImage { + id: isHandRaisedIndicator + + Layout.alignment: Qt.AlignVCenter + Layout.leftMargin: 6 + + containerHeight: 12 + containerWidth: 12 + + visible: participantHandIsRaised + + source: JamiResources.hand_black_24dp_svg + color: JamiTheme.whiteColor + } } } diff --git a/src/mainview/components/ParticipantOverlayMenu.qml b/src/mainview/components/ParticipantOverlayMenu.qml index c72aeee51..a69608716 100644 --- a/src/mainview/components/ParticipantOverlayMenu.qml +++ b/src/mainview/components/ParticipantOverlayMenu.qml @@ -40,6 +40,7 @@ Item { property bool showMaximize: false property bool showMinimize: false property bool showHangup: false + property bool showLowerHand: false property int shapeHeight: 30 property int shapeRadius: 8 -- GitLab