From 9f155d9922a38407e0bd7932354dd4675b62b7ef Mon Sep 17 00:00:00 2001 From: agsantos <aline.gondimsantos@savoirfairelinux.com> Date: Tue, 11 May 2021 20:02:43 -0400 Subject: [PATCH] callview: redesign changes in incoming and outcoming call views Lrc verifies if we should call refuse or hangup, so now we can unify the call ending function in client. GitLab: #408 Change-Id: I35f7ca282c6e49e669d849a140772600e501711a --- .vscode/settings.json | 10 + qml.qrc | 5 +- src/calladapter.cpp | 11 +- src/calladapter.h | 1 - src/commoncomponents/AvatarImage.qml | 13 ++ src/commoncomponents/SpinningAnimation.qml | 51 +++++ src/constant/JamiStrings.qml | 5 + src/constant/JamiTheme.qml | 38 ++-- src/mainview/MainView.qml | 4 +- .../components/CallOverlayButtonGroup.qml | 29 ++- src/mainview/components/CallStackView.qml | 67 +++--- src/mainview/components/IncomingCallPage.qml | 164 -------------- src/mainview/components/InitialCallPage.qml | 213 ++++++++++++++++++ src/mainview/components/OutgoingCallPage.qml | 119 ---------- src/mainview/components/UserInfoCallPage.qml | 154 ------------- 15 files changed, 358 insertions(+), 526 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 src/commoncomponents/SpinningAnimation.qml delete mode 100644 src/mainview/components/IncomingCallPage.qml create mode 100644 src/mainview/components/InitialCallPage.qml delete mode 100644 src/mainview/components/OutgoingCallPage.qml delete mode 100644 src/mainview/components/UserInfoCallPage.qml diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..3b42f1b10 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "files.associations": { + "*.tcc": "cpp", + "array": "cpp", + "string": "cpp", + "string_view": "cpp", + "ranges": "cpp", + "thread": "cpp" + } +} \ No newline at end of file diff --git a/qml.qrc b/qml.qrc index 15cbfbd12..64af068e7 100644 --- a/qml.qrc +++ b/qml.qrc @@ -35,6 +35,7 @@ <file>src/commoncomponents/PresenceIndicator.qml</file> <file>src/commoncomponents/AvatarImage.qml</file> <file>src/commoncomponents/DaemonReconnectPopup.qml</file> + <file>src/commoncomponents/SpinningAnimation.qml</file> <file>src/settingsview/SettingsView.qml</file> <file>src/settingsview/components/ChatviewSettings.qml</file> <file>src/settingsview/components/SettingsMenu.qml</file> @@ -103,8 +104,7 @@ <file>src/mainview/components/MessageWebViewHeader.qml</file> <file>src/mainview/components/AccountComboBox.qml</file> <file>src/mainview/components/CallStackView.qml</file> - <file>src/mainview/components/IncomingCallPage.qml</file> - <file>src/mainview/components/OutgoingCallPage.qml</file> + <file>src/mainview/components/InitialCallPage.qml</file> <file>src/mainview/components/AudioCallPage.qml</file> <file>src/mainview/components/CallOverlay.qml</file> <file>src/mainview/components/CallOverlayButtonGroup.qml</file> @@ -127,7 +127,6 @@ <file>src/mainview/components/RecordBox.qml</file> <file>src/mainview/components/SipInputPanel.qml</file> <file>src/mainview/components/ParticipantOverlayMenu.qml</file> - <file>src/mainview/components/UserInfoCallPage.qml</file> <file>src/mainview/js/videodevicecontextmenuitemcreation.js</file> <file>src/mainview/js/incomingcallpagecreation.js</file> <file>src/mainview/js/selectscreenwindowcreation.js</file> diff --git a/src/calladapter.cpp b/src/calladapter.cpp index d968c7f38..f8c6575cc 100644 --- a/src/calladapter.cpp +++ b/src/calladapter.cpp @@ -68,7 +68,7 @@ CallAdapter::CallAdapter(SystemTray* systemTray, LRCInstance* instance, QObject* connect(systemTray_, &SystemTray::declineCallActivated, [this](const QString& accountId, const QString& convUid) { - refuseACall(accountId, convUid); + hangUpACall(accountId, convUid); }); #endif @@ -156,15 +156,6 @@ CallAdapter::hangUpACall(const QString& accountId, const QString& convUid) } } -void -CallAdapter::refuseACall(const QString& accountId, const QString& convUid) -{ - const auto& convInfo = lrcInstance_->getConversationFromConvUid(convUid, accountId); - if (!convInfo.uid.isEmpty()) { - lrcInstance_->getAccountInfo(accountId).callModel->refuse(convInfo.callId); - } -} - void CallAdapter::acceptACall(const QString& accountId, const QString& convUid) { diff --git a/src/calladapter.h b/src/calladapter.h index c110d974e..54b9625aa 100644 --- a/src/calladapter.h +++ b/src/calladapter.h @@ -49,7 +49,6 @@ public: Q_INVOKABLE void placeAudioOnlyCall(); Q_INVOKABLE void placeCall(); Q_INVOKABLE void hangUpACall(const QString& accountId, const QString& convUid); - Q_INVOKABLE void refuseACall(const QString& accountId, const QString& convUid); Q_INVOKABLE void acceptACall(const QString& accountId, const QString& convUid); Q_INVOKABLE void connectCallModel(const QString& accountId); diff --git a/src/commoncomponents/AvatarImage.qml b/src/commoncomponents/AvatarImage.qml index b4f6f2214..4a40cd5fd 100644 --- a/src/commoncomponents/AvatarImage.qml +++ b/src/commoncomponents/AvatarImage.qml @@ -71,6 +71,7 @@ Item { property bool showPresenceIndicator: true property int unreadMessagesCount: 0 property bool enableAnimation: true + property bool showSpinningAnimation: false signal imageIsReady @@ -207,6 +208,18 @@ Item { visible: showPresenceIndicator } + SpinningAnimation { + id: spinningAnimation + + anchors.horizontalCenter: root.horizontalCenter + anchors.verticalCenter: root.verticalCenter + + visible: showSpinningAnimation + width: Math.ceil(root.width * 1.05) + height: Math.ceil(root.height * 1.05) + z: -1 + } + Connections { target: ScreenInfo diff --git a/src/commoncomponents/SpinningAnimation.qml b/src/commoncomponents/SpinningAnimation.qml new file mode 100644 index 000000000..6147893af --- /dev/null +++ b/src/commoncomponents/SpinningAnimation.qml @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2021 by Savoir-faire Linux + * Author: Aline Gondim Santos <aline.gondimsantos@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 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Universal 2.14 +import QtGraphicalEffects 1.12 + +Item { + id: root + + ConicalGradient { + anchors.fill: parent + angle: 0.0 + gradient: Gradient { + GradientStop { position: 0.5; color: "transparent" } + GradientStop { position: 1.0; color: "white" } + } + + RotationAnimation on angle { + loops: Animation.Infinite + duration: 1000 + from: 0 + to: 360 + } + } + layer.enabled: true + layer.effect: OpacityMask { + maskSource: Rectangle { + width: root.height + height: root.height + radius: root.height / 2 + } + } +} \ No newline at end of file diff --git a/src/constant/JamiStrings.qml b/src/constant/JamiStrings.qml index 743f6355f..aa61f241b 100644 --- a/src/constant/JamiStrings.qml +++ b/src/constant/JamiStrings.qml @@ -27,6 +27,11 @@ Item { readonly property string appTitle: "Jami" + (UpdateManager.isCurrentVersionBeta() ? " (BETA)" : "") // Misc + property string accept: qsTr("Accept") + property string refuse: qsTr("Refuse") + property string endCall: qsTr("End call") + property string incomingAudioCallFrom: qsTr("Incoming audio call from {}") + property string incomingVideoCallFrom: qsTr("Incoming video call from {}") property string contactSearchConversation: qsTr("Find a user or search for a conversation") property string contactSearchInvitations: qsTr("Search your invitations") property string invitations: qsTr("Invitations") diff --git a/src/constant/JamiTheme.qml b/src/constant/JamiTheme.qml index 4f8a229c0..f7de36e3b 100644 --- a/src/constant/JamiTheme.qml +++ b/src/constant/JamiTheme.qml @@ -27,6 +27,11 @@ import net.jami.Enums 1.0 Item { property bool darkTheme: SettingsAdapter.getAppValue(Settings.EnableDarkTheme) + // Jami theme colors + function rgba256(r, g, b, a) { + return Qt.rgba(r / 255, g / 255, b / 255, a / 100.) + } + // General property color blackColor: "#000000" property color whiteColor: "#ffffff" @@ -82,6 +87,10 @@ Item { property color buttonTintedRed: "red" property color buttonTintedRedHovered: "#c00" property color buttonTintedRedPressed: "#b00" + property color acceptGreen: rgba256(11, 130, 113, 100) + property color acceptGreenTransparency: rgba256(11, 130, 113, 56) + property color refuseRed: rgba256(204, 0, 34, 100) + property color refuseRedTransparent: rgba256(204, 0, 34, 56) property color closeButtonLighterBlack: "#4c4c4c" @@ -142,22 +151,17 @@ Item { property color faddedFontColor: darkTheme? "#c0c0c0" : "#a0a0a0" property color faddedLastInteractionFontColor: darkTheme ? "#c0c0c0" : "#505050" - // Jami theme colors - function rgb256(r, g, b) { - return Qt.rgba(r / 255, g / 255, b / 255, 1.0) - } - - property color darkGrey: rgb256(63, 63, 63) - property color blueLogo_: darkTheme ? whiteColor : rgb256(0, 7, 71) - property color lightGrey_: rgb256(242, 242, 242) - property color mediumGrey: rgb256(218, 219, 220) - property color grey_: rgb256(160, 160, 160) - property color red_: rgb256(251, 72, 71) - property color urgentOrange_: rgb256(255, 165, 0) - property color green_: rgb256(127, 255, 0) - property color presenceGreen_: rgb256(76, 217, 100) - property color bgSideBarDarkMode_: rgb256(24, 24, 24) - property color bgDarkMode_: rgb256(32, 32, 32) + property color darkGrey: rgba256(63, 63, 63, 100) + property color blueLogo_: darkTheme ? whiteColor : rgba256(0, 7, 71, 100) + property color lightGrey_: rgba256(242, 242, 242, 100) + property color mediumGrey: rgba256(218, 219, 220, 100) + property color grey_: rgba256(160, 160, 160, 100) + property color red_: rgba256(251, 72, 71, 100) + property color urgentOrange_: rgba256(255, 165, 0, 100) + property color green_: rgba256(127, 255, 0, 100) + property color presenceGreen_: rgba256(76, 217, 100, 100) + property color bgSideBarDarkMode_: rgba256(24, 24, 24, 100) + property color bgDarkMode_: rgba256(32, 32, 32, 100) property int fadeDuration: 150 @@ -182,6 +186,8 @@ Item { property real smartListItemHeight: 64 property real smartListAvatarSize: 52 property real smartListTransitionDuration: 120 + property real avatarSizeInitialCall: 130 + property real callButtonPreferredSize: 50 property real maximumWidthSettingsView: 600 property real settingsHeaderpreferredHeight: 64 diff --git a/src/mainview/MainView.qml b/src/mainview/MainView.qml index 0aa36c031..14f73b4ba 100644 --- a/src/mainview/MainView.qml +++ b/src/mainview/MainView.qml @@ -198,10 +198,8 @@ Rectangle { callStackView.showAudioCallPage() else callStackView.showVideoCallPage() - } else if (item.callState === Call.Status.INCOMING_RINGING) { - callStackView.showIncomingCallPage() } else { - callStackView.showOutgoingCallPage(item.callState) + callStackView.showInitialCallPage(item.callState) } pushCallStackView() diff --git a/src/mainview/components/CallOverlayButtonGroup.qml b/src/mainview/components/CallOverlayButtonGroup.qml index 88888e1b9..1e6eee8e3 100644 --- a/src/mainview/components/CallOverlayButtonGroup.qml +++ b/src/mainview/components/CallOverlayButtonGroup.qml @@ -34,7 +34,6 @@ Rectangle { // ButtonCounts here is to make sure that flow layout margin is calculated correctly, // since no other methods can make buttons at the layout center. - property int buttonPreferredSize: 48 property var isModerator: true property var isSip: false @@ -73,11 +72,11 @@ Rectangle { // TODO: refactor with Flow if possible // 6 is the number of button // If ~ 500px, go into wide mode - if (callOverlayButtonGroup.width < (buttonPreferredSize * 6 - + if (callOverlayButtonGroup.width < (JamiTheme.callButtonPreferredSize * 6 - callOverlayButtonGroup.spacing * 6 + 300)) { return 0 } else { - return callOverlayButtonGroup.width / 2 - buttonPreferredSize * 1.5 - + return callOverlayButtonGroup.width / 2 - JamiTheme.callButtonPreferredSize * 1.5 - callOverlayButtonGroup.spacing } } @@ -87,8 +86,8 @@ Rectangle { id: noMicButton Layout.leftMargin: 8 - Layout.preferredWidth: buttonPreferredSize - Layout.preferredHeight: buttonPreferredSize + Layout.preferredWidth: JamiTheme.callButtonPreferredSize + Layout.preferredHeight: JamiTheme.callButtonPreferredSize pressedColor: JamiTheme.invertedPressedButtonColor hoveredColor: JamiTheme.invertedHoveredButtonColor @@ -108,8 +107,8 @@ Rectangle { PushButton { id: hangUpButton - Layout.preferredWidth: buttonPreferredSize - Layout.preferredHeight: buttonPreferredSize + Layout.preferredWidth: JamiTheme.callButtonPreferredSize + Layout.preferredHeight: JamiTheme.callButtonPreferredSize pressedColor: JamiTheme.declineButtonPressedRed hoveredColor: JamiTheme.declineButtonHoverRed @@ -126,8 +125,8 @@ Rectangle { PushButton { id: noVideoButton - Layout.preferredWidth: buttonPreferredSize - Layout.preferredHeight: buttonPreferredSize + Layout.preferredWidth: JamiTheme.callButtonPreferredSize + Layout.preferredHeight: JamiTheme.callButtonPreferredSize pressedColor: JamiTheme.invertedPressedButtonColor hoveredColor: JamiTheme.invertedHoveredButtonColor @@ -151,8 +150,8 @@ Rectangle { PushButton { id: addToConferenceButton - Layout.preferredWidth: buttonPreferredSize - Layout.preferredHeight: buttonPreferredSize + Layout.preferredWidth: JamiTheme.callButtonPreferredSize + Layout.preferredHeight: JamiTheme.callButtonPreferredSize visible: !isModerator && !isSip pressedColor: JamiTheme.invertedPressedButtonColor @@ -170,8 +169,8 @@ Rectangle { PushButton { id: chatButton - Layout.preferredWidth: buttonPreferredSize - Layout.preferredHeight: buttonPreferredSize + Layout.preferredWidth: JamiTheme.callButtonPreferredSize + Layout.preferredHeight: JamiTheme.callButtonPreferredSize pressedColor: JamiTheme.invertedPressedButtonColor hoveredColor: JamiTheme.invertedHoveredButtonColor @@ -188,8 +187,8 @@ Rectangle { PushButton { id: optionsButton - Layout.preferredWidth: buttonPreferredSize - Layout.preferredHeight: buttonPreferredSize + Layout.preferredWidth: JamiTheme.callButtonPreferredSize + Layout.preferredHeight: JamiTheme.callButtonPreferredSize Layout.rightMargin: 8 pressedColor: JamiTheme.invertedPressedButtonColor diff --git a/src/mainview/components/CallStackView.qml b/src/mainview/components/CallStackView.qml index b8b4eabd1..503057ad8 100644 --- a/src/mainview/components/CallStackView.qml +++ b/src/mainview/components/CallStackView.qml @@ -23,6 +23,9 @@ import QtQuick.Controls.Universal 2.14 import net.jami.Models 1.0 import net.jami.Adapters 1.0 +import net.jami.Constants 1.0 + +import "../../commoncomponents" import "../js/incomingcallpagecreation.js" as IncomingCallPageCreation @@ -30,8 +33,7 @@ Rectangle { id: callStackViewWindow enum StackNumber { - IncomingPageStack, - OutgoingPageStack, + InitialPageStack, AudioPageStack, VideoPageStack } @@ -77,34 +79,29 @@ Rectangle { }) } - function showAudioCallPage() { - var itemToFind = getItemFromStack(CallStackView.AudioPageStack) - if (!itemToFind) { - callStackMainView.push(audioCallPage, StackView.Immediate) - } else { - callStackMainView.pop(itemToFind, StackView.Immediate) - } - audioCallPage.updateUI(responsibleAccountId, responsibleConvUid) - } - - function showOutgoingCallPage() { - var itemToFind = getItemFromStack(CallStackView.OutgoingPageStack) + function showInitialCallPage(callState) { + var itemToFind = getItemFromStack(CallStackView.InitialPageStack) if (!itemToFind) { - callStackMainView.push(outgoingCallPage, StackView.Immediate) + callStackMainView.push(initialCallPage, StackView.Immediate) } else { callStackMainView.pop(itemToFind, StackView.Immediate) } - outgoingCallPage.updateUI(responsibleAccountId, responsibleConvUid) + initialCallPage.accountConvPair = [responsibleAccountId, responsibleConvUid] + initialCallPage.callStatus = callState + if (initialCallPage.callStatus === Call.Status.INCOMING_RINGING) + initialCallPage.isIncoming = true + else + initialCallPage.isIncoming = false } - function showIncomingCallPage(accountId, convUid) { - var itemToFind = getItemFromStack(CallStackView.IncomingPageStack) + function showAudioCallPage() { + var itemToFind = getItemFromStack(CallStackView.AudioPageStack) if (!itemToFind) { - callStackMainView.push(incomingCallPage, StackView.Immediate) + callStackMainView.push(audioCallPage, StackView.Immediate) } else { callStackMainView.pop(itemToFind, StackView.Immediate) } - incomingCallPage.updateUI(responsibleAccountId, responsibleConvUid) + audioCallPage.updateUI(responsibleAccountId, responsibleConvUid) } function showVideoCallPage() { @@ -155,9 +152,9 @@ Rectangle { target: CallAdapter function onCallStatusChanged(status, accountId, convUid) { - if (callStackMainView.currentItem.stackNumber === CallStackView.OutgoingPageStack + if (callStackMainView.currentItem.stackNumber === CallStackView.InitialPageStack && responsibleConvUid === convUid && responsibleAccountId === accountId) { - outgoingCallPage.callStatus = status + initialCallPage.callStatus = status } } @@ -179,18 +176,6 @@ Rectangle { visible: callStackMainView.currentItem.stackNumber === stackNumber } - OutgoingCallPage { - id: outgoingCallPage - - property int stackNumber: CallStackView.OutgoingPageStack - - visible: callStackMainView.currentItem.stackNumber === stackNumber - - onCallCancelButtonIsClicked: { - CallAdapter.hangUpACall(responsibleAccountId, responsibleConvUid) - } - } - VideoCallPage { id: videoCallPage @@ -199,19 +184,19 @@ Rectangle { visible: callStackMainView.currentItem.stackNumber === stackNumber } - IncomingCallPage { - id: incomingCallPage + InitialCallPage { + id: initialCallPage - property int stackNumber: CallStackView.IncomingPageStack + property int stackNumber: CallStackView.InitialPageStack - onCallAcceptButtonIsClicked: { + onCallAccepted: { CallAdapter.acceptACall(responsibleAccountId, responsibleConvUid) communicationPageMessageWebView.setSendContactRequestButtonVisible(false) mainViewSidePanel.selectTab(SidePanelTabBar.Conversations) } - onCallCancelButtonIsClicked: { - CallAdapter.refuseACall(responsibleAccountId, responsibleConvUid) + onCallCanceled: { + CallAdapter.hangUpACall(responsibleAccountId, responsibleConvUid) } visible: callStackMainView.currentItem.stackNumber === stackNumber @@ -222,6 +207,6 @@ Rectangle { anchors.fill: parent - initialItem: outgoingCallPage + initialItem: initialCallPage } } diff --git a/src/mainview/components/IncomingCallPage.qml b/src/mainview/components/IncomingCallPage.qml deleted file mode 100644 index a53e63ba8..000000000 --- a/src/mainview/components/IncomingCallPage.qml +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2020 by Savoir-faire Linux - * Author: Mingrui Zhang <mingrui.zhang@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 2.14 -import QtQuick.Controls 2.14 -import QtQuick.Layouts 1.14 -import QtQuick.Controls.Universal 2.14 -import Qt.labs.platform 1.1 - -import net.jami.Models 1.0 -import net.jami.Adapters 1.0 -import net.jami.Constants 1.0 - -import "../../commoncomponents" - -Rectangle { - id: incomingCallPage - - property int buttonPreferredSize: 48 - - signal callCancelButtonIsClicked - signal callAcceptButtonIsClicked - - color: "black" - - function updateUI(accountId, convUid) { - userInfoIncomingCallPage.updateUI(accountId, convUid) - } - - // Prevent right click propagate to VideoCallPage. - MouseArea { - anchors.fill: parent - propagateComposedEvents: false - acceptedButtons: Qt.AllButtons - onDoubleClicked: mouse.accepted = true - } - - ColumnLayout { - id: incomingCallPageColumnLayout - - anchors.fill: parent - - // Common elements with OutgoingCallPage - UserInfoCallPage { - id: userInfoIncomingCallPage - Layout.fillWidth: true - Layout.fillHeight: true - } - - Text { - id: talkToYouText - - Layout.alignment: Qt.AlignCenter - Layout.preferredWidth: incomingCallPage.width - Layout.preferredHeight: 32 - - font.pointSize: JamiTheme.textFontSize - - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - color: "white" - - text: JamiStrings.isCallingYou - } - - RowLayout { - id: incomingCallPageRowLayout - - Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom - Layout.bottomMargin: 48 - Layout.topMargin: 48 - - Layout.preferredWidth: incomingCallPage.width - 200 - Layout.maximumWidth: 200 - Layout.preferredHeight: buttonPreferredSize - - ColumnLayout { - id: callAnswerButtonColumnLayout - - Layout.alignment: Qt.AlignLeft - - PushButton { - id: callAnswerButton - - Layout.alignment: Qt.AlignCenter - - Layout.preferredWidth: buttonPreferredSize - Layout.preferredHeight: buttonPreferredSize - - pressedColor: JamiTheme.acceptButtonPressedGreen - hoveredColor: JamiTheme.acceptButtonHoverGreen - normalColor: JamiTheme.acceptButtonGreen - - source: "qrc:/images/icons/check-24px.svg" - imageColor: JamiTheme.whiteColor - - onClicked: callAcceptButtonIsClicked() - } - } - - ColumnLayout { - id: callDeclineButtonColumnLayout - - Layout.alignment: Qt.AlignRight - - PushButton { - id: callDeclineButton - - Layout.alignment: Qt.AlignCenter - - Layout.preferredWidth: buttonPreferredSize - Layout.preferredHeight: buttonPreferredSize - - pressedColor: JamiTheme.declineButtonPressedRed - hoveredColor: JamiTheme.declineButtonHoverRed - normalColor: JamiTheme.declineButtonRed - - source: "qrc:/images/icons/round-close-24px.svg" - imageColor: JamiTheme.whiteColor - - toolTipText: JamiStrings.hangup - - onClicked: callCancelButtonIsClicked() - } - } - } - } - - Shortcut { - sequence: "Ctrl+Y" - context: Qt.ApplicationShortcut - onActivated: { - incomingCallPage.close() - CallAdapter.acceptACall(responsibleAccountId, - responsibleConvUid) - communicationPageMessageWebView.setSendContactRequestButtonVisible(false) - } - } - - Shortcut { - sequence: "Ctrl+Shift+D" - context: Qt.ApplicationShortcut - onActivated: { - incomingCallPage.close() - CallAdapter.refuseACall(responsibleAccountId, - responsibleConvUid) - } - } -} diff --git a/src/mainview/components/InitialCallPage.qml b/src/mainview/components/InitialCallPage.qml new file mode 100644 index 000000000..19b934f26 --- /dev/null +++ b/src/mainview/components/InitialCallPage.qml @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2020-2021 by Savoir-faire Linux + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * Aline Gondim Santos <aline.gondimsantos@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 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Universal 2.14 +import Qt.labs.platform 1.1 + +import net.jami.Models 1.0 +import net.jami.Adapters 1.0 +import net.jami.Constants 1.0 + +import "../../commoncomponents" + +Rectangle { + id: root + + property bool isIncoming: false + property bool isAudioOnly: false + property var accountConvPair: ["",""] + property int callStatus: 0 + property string bestName: "" + + signal callCanceled + signal callAccepted + + color: "black" + + ListModel { + id: incomingControlsModel + ListElement { type: "refuse"; image: "qrc:/images/icons/round-close-24px.svg"} + ListElement { type: "accept"; image: "qrc:/images/icons/check-24px.svg"} + } + ListModel { + id: outgoingControlsModel + ListElement { type: "cancel"; image: "qrc:/images/icons/round-close-24px.svg"} + } + + onAccountConvPairChanged: { + if (accountConvPair[1]) { + contactImg.updateImage(accountConvPair[1]) + root.bestName = UtilsAdapter.getBestName(accountConvPair[0], accountConvPair[1]) + } + } + + // Prevent right click propagate to VideoCallPage. + MouseArea { + anchors.fill: parent + propagateComposedEvents: false + acceptedButtons: Qt.AllButtons + onDoubleClicked: mouse.accepted = true + } + + ColumnLayout { + anchors.horizontalCenter: root.horizontalCenter + anchors.verticalCenter: root.verticalCenter + + AvatarImage { + id: contactImg + + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: JamiTheme.avatarSizeInitialCall + Layout.preferredHeight: JamiTheme.avatarSizeInitialCall + + mode: AvatarImage.Mode.FromConvUid + showPresenceIndicator: false + showSpinningAnimation: true + } + + Text { + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: JamiTheme.preferredFieldWidth + Layout.topMargin: 32 + + font.pointSize: JamiTheme.titleFontSize + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: { + if (root.isIncoming) + return root.isAudioOnly ? JamiStrings.incomingAudioCallFrom.replace("{}", root.bestName) : JamiStrings.incomingVideoCallFrom.replace("{}", root.bestName) + else + return root.bestName + } + wrapMode: Text.WordWrap + elide: Text.ElideRight + maximumLineCount: root.isIncoming ? 2 : 1 + color: "white" + } + + Text { + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: root.width + Layout.topMargin: 8 + + font.pointSize: JamiTheme.smartlistItemFontSize + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: UtilsAdapter.getCallStatusStr(callStatus) + "…" + color: JamiTheme.whiteColor + visible: !root.isIncoming + } + + RowLayout { + Layout.alignment: Qt.AlignHCenter + Layout.topMargin: 32 + + Repeater { + id: controlButtons + model: root.isIncoming ? incomingControlsModel : outgoingControlsModel + + delegate: ColumnLayout { + PushButton { + Layout.leftMargin: 10 + Layout.rightMargin: 10 + Layout.alignment: Qt.AlignHCenter + implicitWidth: JamiTheme.callButtonPreferredSize + implicitHeight: JamiTheme.callButtonPreferredSize + + pressedColor: { + if (type === "accept" ) + return JamiTheme.acceptGreen + return JamiTheme.refuseRed + } + hoveredColor: { + if (type === "accept" ) + return JamiTheme.acceptGreen + return JamiTheme.refuseRed + } + normalColor: { + if (type === "accept" ) + return JamiTheme.acceptGreenTransparency + return JamiTheme.refuseRedTransparent + } + + source: image + imageColor: JamiTheme.whiteColor + + onClicked: { + if (type === "accept") + callAccepted() + else + callCanceled() + } + } + + Label { + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: JamiTheme.callButtonPreferredSize + Layout.preferredHeight: JamiTheme.preferredFieldHeight + + font.pointSize: JamiTheme.smartlistItemInfoFontSize + font.kerning: true + color: JamiTheme.whiteColor + + text: { + if (type === "refuse") + return JamiStrings.refuse + else if (type === "accept") + return JamiStrings.accept + else if (type === "cancel") + return JamiStrings.endCall + return "" + } + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + wrapMode: Text.WordWrap + } + } + } + } + } + + Shortcut { + sequence: "Ctrl+Y" + context: Qt.ApplicationShortcut + onActivated: { + CallAdapter.acceptACall(root.accountConvPair[0], + root.accountConvPair[1]) + communicationPageMessageWebView.setSendContactRequestButtonVisible(false) + } + } + + Shortcut { + sequence: "Ctrl+Shift+D" + context: Qt.ApplicationShortcut + onActivated: { + CallAdapter.hangUpACall(root.accountConvPair[0], + root.accountConvPair[1]) + } + } +} diff --git a/src/mainview/components/OutgoingCallPage.qml b/src/mainview/components/OutgoingCallPage.qml deleted file mode 100644 index 72023a0dc..000000000 --- a/src/mainview/components/OutgoingCallPage.qml +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2020 by Savoir-faire Linux - * Author: Mingrui Zhang <mingrui.zhang@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 2.14 -import QtQuick.Controls 2.14 -import QtQuick.Layouts 1.14 -import QtQuick.Controls.Universal 2.14 - -import net.jami.Models 1.0 -import net.jami.Adapters 1.0 -import net.jami.Constants 1.0 - -import "../../commoncomponents" - -Rectangle { - id: outgoingCallPageRect - - property int buttonPreferredSize: 50 - property int callStatus: 0 - signal callCancelButtonIsClicked - - function updateUI(accountId, convUid) { - userInfoCallPage.updateUI(accountId, convUid) - } - - anchors.fill: parent - - color: "black" - - // Prevent right click propagate to VideoCallPage. - MouseArea { - anchors.fill: parent - propagateComposedEvents: false - acceptedButtons: Qt.AllButtons - onDoubleClicked: mouse.accepted = true - } - - ColumnLayout { - id: outgoingCallPageRectColumnLayout - - anchors.fill: parent - - UserInfoCallPage { - id: userInfoCallPage - Layout.fillHeight: true - Layout.fillWidth: true - } - - AnimatedImage { - id: spinnerImage - - Layout.alignment: Qt.AlignCenter - Layout.preferredWidth: 24 - Layout.preferredHeight: 8 - - source: "qrc:/images/waiting.gif" - } - - Text { - id: callStatusText - - Layout.alignment: Qt.AlignCenter - Layout.preferredWidth: outgoingCallPageRect.width - Layout.preferredHeight: 30 - - font.pointSize: JamiTheme.textFontSize - - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - - text: UtilsAdapter.getCallStatusStr(callStatus) + "…" - color: Qt.lighter("white", 1.5) - } - - ColumnLayout { - id: callCancelButtonColumnLayout - - Layout.alignment: Qt.AlignCenter - Layout.bottomMargin: 48 - - PushButton { - id: callCancelButton - - Layout.alignment: Qt.AlignCenter - - Layout.preferredWidth: buttonPreferredSize - Layout.preferredHeight: buttonPreferredSize - - pressedColor: JamiTheme.declineButtonPressedRed - hoveredColor: JamiTheme.declineButtonHoverRed - normalColor: JamiTheme.declineButtonRed - - source: "qrc:/images/icons/round-close-24px.svg" - imageColor: JamiTheme.whiteColor - - toolTipText: JamiStrings.hangup - - onClicked: { - callCancelButtonIsClicked() - } - } - } - } -} diff --git a/src/mainview/components/UserInfoCallPage.qml b/src/mainview/components/UserInfoCallPage.qml deleted file mode 100644 index 133d8a0d7..000000000 --- a/src/mainview/components/UserInfoCallPage.qml +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2020 by Savoir-faire Linux - * Author: Albert Babà <albert.babi@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 2.14 -import QtQuick.Controls 2.14 -import QtQuick.Layouts 1.14 -import QtQuick.Controls.Universal 2.14 - -import net.jami.Models 1.0 -import net.jami.Adapters 1.0 -import net.jami.Constants 1.0 - -import "../../commoncomponents" - -// Common element for IncomingCallPage and OutgoingCallPage -Rectangle { - id: userInfoCallRect - - property int buttonPreferredSize: 48 - property string bestName: "Best Name" - property string bestId: "Best Id" - - function updateUI(accountId, convUid) { - contactImg.updateImage(convUid) - bestName = UtilsAdapter.getBestName(accountId, convUid) - var id = UtilsAdapter.getBestId(accountId, convUid) - bestId = (bestName !== id) ? id : "" - } - - color: "black" - - ColumnLayout { - id: userInfoCallColumnLayout - - anchors.fill: parent - - PushButton { - id: backButton - - Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft - Layout.preferredWidth: JamiTheme.preferredFieldHeight - Layout.preferredHeight: JamiTheme.preferredFieldHeight - Layout.rightMargin: JamiTheme.preferredMarginSize - Layout.topMargin: JamiTheme.preferredMarginSize - Layout.leftMargin: JamiTheme.preferredMarginSize - - source: "qrc:/images/icons/ic_arrow_back_24px.svg" - - pressedColor: JamiTheme.invertedPressedButtonColor - hoveredColor: JamiTheme.invertedHoveredButtonColor - normalColor: JamiTheme.invertedNormalButtonColor - - imageColor: JamiTheme.whiteColor - - toolTipText: qsTr("Toggle to display side panel") - - visible: mainView.sidePanelOnly - - onClicked: mainView.showWelcomeView() - } - - AvatarImage { - id: contactImg - - Layout.alignment: Qt.AlignCenter - Layout.topMargin: 48 - - Layout.preferredWidth: 100 - Layout.preferredHeight: 100 - - mode: AvatarImage.Mode.FromConvUid - showPresenceIndicator: false - } - - Rectangle { - id: userInfoCallPageTextRect - - Layout.alignment: Qt.AlignCenter - Layout.topMargin: 8 - - Layout.preferredWidth: userInfoCallRect.width - Layout.preferredHeight: jamiBestNameText.height + jamiBestIdText.height + 100 - - color: "transparent" - - ColumnLayout { - id: userInfoCallPageTextRectColumnLayout - - Text { - id: jamiBestNameText - - Layout.alignment: Qt.AlignCenter - Layout.preferredWidth: userInfoCallPageTextRect.width - Layout.preferredHeight: 48 - - font.pointSize: JamiTheme.headerFontSize - - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - - text: textMetricsjamiBestNameText.elidedText - color: "white" - - TextMetrics { - id: textMetricsjamiBestNameText - font: jamiBestNameText.font - text: bestName - elideWidth: userInfoCallPageTextRect.width - 48 - elide: Qt.ElideMiddle - } - } - - Text { - id: jamiBestIdText - - Layout.alignment: Qt.AlignCenter - Layout.preferredWidth: userInfoCallPageTextRect.width - Layout.preferredHeight: 32 - - font.pointSize: JamiTheme.textFontSize - - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - - text: textMetricsjamiBestIdText.elidedText - color: Qt.lighter("white", 1.5) - - TextMetrics { - id: textMetricsjamiBestIdText - font: jamiBestIdText.font - text: bestId - elideWidth: userInfoCallPageTextRect.width - 48 - elide: Qt.ElideMiddle - } - } - } - } - } -} -- GitLab