diff --git a/images/icons/check_box-24px.svg b/images/icons/check_box-24px.svg new file mode 100644 index 0000000000000000000000000000000000000000..3fb385f48f298a76ba1ffba59a63e8d7b9afb56b --- /dev/null +++ b/images/icons/check_box-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg> \ No newline at end of file diff --git a/images/icons/check_box_outline_blank-24px.svg b/images/icons/check_box_outline_blank-24px.svg new file mode 100644 index 0000000000000000000000000000000000000000..60c321cd321e2060540f6f57b9744df996f4833a --- /dev/null +++ b/images/icons/check_box_outline_blank-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/></svg> \ No newline at end of file diff --git a/images/icons/close_fullscreen-24px.svg b/images/icons/close_fullscreen-24px.svg new file mode 100644 index 0000000000000000000000000000000000000000..d9208f73175b6f29903efa5480080ba2af8d29ff --- /dev/null +++ b/images/icons/close_fullscreen-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24" viewBox="0 0 24 24" width="24"><rect fill="none" height="24" width="24"/><path d="M22,3.41l-5.29,5.29L20,12h-8V4l3.29,3.29L20.59,2L22,3.41z M3.41,22l5.29-5.29L12,20v-8H4l3.29,3.29L2,20.59L3.41,22z"/></svg> \ No newline at end of file diff --git a/images/icons/ic_call_end_white_24px.svg b/images/icons/ic_call_end_white_24px.svg new file mode 100644 index 0000000000000000000000000000000000000000..9c90cb39c2c30c6a239a203bd4ee77035700c5af --- /dev/null +++ b/images/icons/ic_call_end_white_24px.svg @@ -0,0 +1,4 @@ +<svg fill="#ffffff" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M0 0h24v24H0z" fill="none"/> + <path d="M12 9c-1.6 0-3.15.25-4.6.72v3.1c0 .39-.23.74-.56.9-.98.49-1.87 1.12-2.66 1.85-.18.18-.43.28-.7.28-.28 0-.53-.11-.71-.29L.29 13.08c-.18-.17-.29-.42-.29-.7 0-.28.11-.53.29-.71C3.34 8.78 7.46 7 12 7s8.66 1.78 11.71 4.67c.18.18.29.43.29.71 0 .28-.11.53-.29.71l-2.48 2.48c-.18.18-.43.29-.71.29-.27 0-.52-.11-.7-.28-.79-.74-1.69-1.36-2.67-1.85-.33-.16-.56-.5-.56-.9v-3.1C15.15 9.25 13.6 9 12 9z"/> +</svg> diff --git a/images/icons/ic_call_transfer_white_24px.png b/images/icons/ic_call_transfer_white_24px.png deleted file mode 100644 index a43dbb4be9d54a6be42b89d03488487b86ed2613..0000000000000000000000000000000000000000 Binary files a/images/icons/ic_call_transfer_white_24px.png and /dev/null differ diff --git a/images/icons/ic_high_quality_24px.svg b/images/icons/ic_high_quality_24px.svg new file mode 100644 index 0000000000000000000000000000000000000000..41de4d148dc6aba70bfdbd1c420a8b0970feca92 --- /dev/null +++ b/images/icons/ic_high_quality_24px.svg @@ -0,0 +1,4 @@ +<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> + <path d="M0 0h24v24H0z" fill="none"/> + <path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 11H9.5v-2h-2v2H6V9h1.5v2.5h2V9H11v6zm7-1c0 .55-.45 1-1 1h-.75v1.5h-1.5V15H14c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v4zm-3.5-.5h2v-3h-2v3z"/> +</svg> diff --git a/images/icons/ic_high_quality_white_24dp.png b/images/icons/ic_high_quality_white_24dp.png deleted file mode 100644 index 6d2d87d21b5f22f29f5dc56f5317e05bf59b4bea..0000000000000000000000000000000000000000 Binary files a/images/icons/ic_high_quality_white_24dp.png and /dev/null differ diff --git a/images/icons/ic_pause_white_24dp.png b/images/icons/ic_pause_white_24dp.png deleted file mode 100644 index f49aed757118a941b567629ec217cde1aaf257e8..0000000000000000000000000000000000000000 Binary files a/images/icons/ic_pause_white_24dp.png and /dev/null differ diff --git a/images/icons/insert_photo-24px.svg b/images/icons/insert_photo-24px.svg new file mode 100644 index 0000000000000000000000000000000000000000..5d4bac103a29d3ae0ef7cb0e10c467d8ab7e317a --- /dev/null +++ b/images/icons/insert_photo-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></svg> \ No newline at end of file diff --git a/images/icons/more_vert-24px.svg b/images/icons/more_vert-24px.svg new file mode 100644 index 0000000000000000000000000000000000000000..3a1e4ed2eeaece6f0eaaf4e65b535420cb7654ba --- /dev/null +++ b/images/icons/more_vert-24px.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/> + <path fill="white" d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/> +</svg> \ No newline at end of file diff --git a/images/icons/open_in_full-24px.svg b/images/icons/open_in_full-24px.svg new file mode 100644 index 0000000000000000000000000000000000000000..5c293a0f10271d5356595767f0d46c23d203638c --- /dev/null +++ b/images/icons/open_in_full-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24" viewBox="0 0 24 24" width="24"><rect fill="none" height="24" width="24"/><polygon points="21,11 21,3 13,3 16.29,6.29 6.29,16.29 3,13 3,21 11,21 7.71,17.71 17.71,7.71"/></svg> \ No newline at end of file diff --git a/images/icons/pause_circle_outline-24px.svg b/images/icons/pause_circle_outline-24px.svg new file mode 100644 index 0000000000000000000000000000000000000000..cb476dd842b7311f84d28809941bce3f02577cdd --- /dev/null +++ b/images/icons/pause_circle_outline-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M9 16h2V8H9v8zm3-14C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm1-4h2V8h-2v8z"/></svg> \ No newline at end of file diff --git a/images/icons/phone_forwarded-24px.svg b/images/icons/phone_forwarded-24px.svg new file mode 100644 index 0000000000000000000000000000000000000000..0ae16379552260d11766e63d635c46380f7a03a9 --- /dev/null +++ b/images/icons/phone_forwarded-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M18 11l5-5-5-5v3h-4v4h4v3zm2 4.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1z"/></svg> \ No newline at end of file diff --git a/images/icons/play_circle_outline-24px.svg b/images/icons/play_circle_outline-24px.svg new file mode 100644 index 0000000000000000000000000000000000000000..a845a76c4658e23c8e58655e6772a8183170826a --- /dev/null +++ b/images/icons/play_circle_outline-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M10 16.5l6-4.5-6-4.5v9zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></svg> \ No newline at end of file diff --git a/images/icons/screen_share-24px.svg b/images/icons/screen_share-24px.svg new file mode 100644 index 0000000000000000000000000000000000000000..c3e3baad8e7aaceb535d0549a854d80a01da5e68 --- /dev/null +++ b/images/icons/screen_share-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-1.11-.9-2-2-2H4c-1.11 0-2 .89-2 2v10c0 1.1.89 2 2 2H0v2h24v-2h-4zm-7-3.53v-2.19c-2.78 0-4.61.85-6 2.72.56-2.67 2.11-5.33 6-5.87V7l4 3.73-4 3.74z"/></svg> \ No newline at end of file diff --git a/images/icons/videocam-24px.svg b/images/icons/videocam-24px.svg new file mode 100644 index 0000000000000000000000000000000000000000..49a20acb064bd1d02d2399b120a5b5f59773c6b0 --- /dev/null +++ b/images/icons/videocam-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z"/></svg> \ No newline at end of file diff --git a/qml.qrc b/qml.qrc index d939b564aef9de7bb861b40ed9f5aaad7a35da6d..b8483b66dd24d25e03ef747482045caba2f9d4fe 100644 --- a/qml.qrc +++ b/qml.qrc @@ -66,6 +66,7 @@ <file>src/mainview/js/incomingcallpagecreation.js</file> <file>src/mainview/components/ContactSearchBar.qml</file> <file>src/mainview/components/VideoCallPage.qml</file> + <file>src/mainview/components/CallAdvancedOptions.qml</file> <file>src/mainview/components/ChangeLogScrollView.qml</file> <file>src/mainview/components/ProjectCreditsScrollView.qml</file> <file>src/mainview/components/AccountComboBoxPopup.qml</file> @@ -75,9 +76,9 @@ <file>src/mainview/components/WelcomePageQrDialog.qml</file> <file>src/commoncomponents/GeneralMenuItem.qml</file> <file>src/mainview/components/ConversationSmartListContextMenu.qml</file> + <file>src/mainview/components/CallViewContextMenu.qml</file> <file>src/commoncomponents/GeneralMenuSeparator.qml</file> <file>src/mainview/components/UserProfile.qml</file> - <file>src/mainview/components/VideoCallPageContextMenu.qml</file> <file>src/mainview/js/videodevicecontextmenuitemcreation.js</file> <file>src/mainview/components/VideoCallPageContextMenuDeviceItem.qml</file> <file>src/mainview/components/SelectScreen.qml</file> diff --git a/ressources.qrc b/ressources.qrc index a0e1547f51fe736464a825558b4e1142fab8aeb7..c691689a4fc4131f9b581d612f8c549ec69252d3 100644 --- a/ressources.qrc +++ b/ressources.qrc @@ -32,22 +32,23 @@ <file>images/icons/ic_arrow_tab_next_black_9dp_2x.png</file> <file>images/icons/ic_arrow_tab_previous_black_9dp_2x.png</file> <file>images/icons/ic_block_24px.svg</file> - <file>images/icons/ic_call_transfer_white_24px.png</file> + <file>images/icons/phone_forwarded-24px.svg</file> <file>images/icons/ic_chat_black_24dp_2x.png</file> <file>images/icons/ic_chat_white_24dp.png</file> + <file>images/icons/more_vert-24px.svg</file> <file>images/icons/ic_check_white_18dp_2x.png</file> <file>images/icons/ic_clear_24px.svg</file> <file>images/icons/ic_close_white_24dp.png</file> <file>images/icons/ic_content_copy.svg</file> <file>images/icons/ic_delete_black_18dp_2x.png</file> <file>images/icons/ic_done_white_24dp.png</file> - <file>images/icons/ic_exit_full_screen_black.png</file> <file>images/icons/ic_folder_black_18dp_2x.png</file> - <file>images/icons/ic_full_screen_black.png</file> + <file>images/icons/open_in_full-24px.svg</file> + <file>images/icons/close_fullscreen-24px.svg</file> <file>images/icons/ic_group_add_white_24dp.png</file> - <file>images/icons/ic_high_quality_white_24dp.png</file> <file>images/icons/ic_mic_off_white_24dp.png</file> - <file>images/icons/ic_pause_white_24dp.png</file> + <file>images/icons/pause_circle_outline-24px.svg</file> + <file>images/icons/play_circle_outline-24px.svg</file> <file>images/icons/ic_pause_white_100px.png</file> <file>images/icons/ic_person_add_black_24dp_2x.png</file> <file>images/icons/ic_person_add_white_24dp.png</file> @@ -62,6 +63,7 @@ <file>images/icons/ic_videocam_off_white_24dp.png</file> <file>images/icons/ic_videocam_white.png</file> <file>images/icons/ic_voicemail_white_24dp_2x.png</file> + <file>images/icons/ic_call_end_white_24px.svg</file> <file>images/icons/round-add-24px.svg</file> <file>images/icons/round-arrow_drop_down-24px.svg</file> <file>images/icons/round-arrow_drop_up-24px.svg</file> @@ -89,6 +91,9 @@ <file>images/icons/ic_show_password.png</file> <file>images/icons/baseline-desktop_windows-24px.svg</file> <file>images/icons/baseline-people-24px.svg</file> + <file>images/icons/ic_high_quality_24px.svg</file> + <file>images/icons/insert_photo-24px.svg</file> + <file>images/icons/screen_share-24px.svg</file> <file>images/icons/round-add_a_photo-24px.svg</file> <file>images/icons/ic_mic_white_24dp.png</file> <file>images/icons/icon-keypad-24.png</file> @@ -104,6 +109,8 @@ <file>images/icons/av_icons/send-24px.svg</file> <file>images/icons/av_icons/stop-24px.svg</file> <file>images/icons/av_icons/mic-24px.svg</file> + <file>images/icons/check_box-24px.svg</file> + <file>images/icons/check_box_outline_blank-24px.svg</file> <file>images/icons/ic_close_black_24dp.png</file> <file>images/icons/extension_24dp.svg</file> <file>images/icons/settings_backup_restore-black-18dp.svg</file> diff --git a/src/calladapter.cpp b/src/calladapter.cpp index 6955434a17326ce961c1609bd2a7b1307bfe8f30..8cd968231d768d4b168a12a97e8e408b8c30ef87 100644 --- a/src/calladapter.cpp +++ b/src/calladapter.cpp @@ -1,11 +1,12 @@ /* * Copyright (C) 2020 by Savoir-faire Linux * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com> - * Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> + * Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * 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 @@ -333,7 +334,6 @@ CallAdapter::updateCallOverlay(const lrc::api::conversation::Info &convInfo) QObject::disconnect(oneSecondTimer_); QObject::connect(oneSecondTimer_, &QTimer::timeout, [this] { setTime(accountId_, convUid_); }); oneSecondTimer_->start(20); - auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId_); auto call = LRCInstance::getCallInfoForConversation(convInfo); @@ -384,6 +384,15 @@ CallAdapter::hangUpThisCall() } } +bool +CallAdapter::isRecordingThisCall() +{ + auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId_); + auto convInfo = LRCInstance::getConversationFromConvUid(convUid_, accountId_); + return accInfo.callModel->isRecording(convInfo.confId) + || accInfo.callModel->isRecording(convInfo.callId); +} + void CallAdapter::holdThisCallToggle() { diff --git a/src/calladapter.h b/src/calladapter.h index 288ab0afc96101d04e997dd532b04e96043b0158..b68e08a6ef22ff4947412b6b427eef5797607d1d 100644 --- a/src/calladapter.h +++ b/src/calladapter.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2020 by Savoir-faire Linux * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * 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 @@ -53,6 +54,7 @@ public: Q_INVOKABLE void muteThisCallToggle(); Q_INVOKABLE void recordThisCallToggle(); Q_INVOKABLE void videoPauseThisCallToggle(); + Q_INVOKABLE bool isRecordingThisCall(); signals: void showOutgoingCallPage(const QString &accountId, const QString &convUid); @@ -106,8 +108,7 @@ private: /* * For Call Overlay */ - void setTime(const QString &accountId, const QString &convUid); void updateCallOverlay(const lrc::api::conversation::Info &convInfo); - + void setTime(const QString &accountId, const QString &convUid); QTimer *oneSecondTimer_; }; diff --git a/src/commoncomponents/HoverableButton.qml b/src/commoncomponents/HoverableButton.qml index a7a4aaf92c8bbd133e625ca47d8003dacccd2e24..2b04f9b13dce76b3bbbd1c7e7d540f99b934eeca 100644 --- a/src/commoncomponents/HoverableButton.qml +++ b/src/commoncomponents/HoverableButton.qml @@ -19,6 +19,7 @@ import QtQuick 2.14 import QtQuick.Controls 2.14 import net.jami.Models 1.0 +import QtGraphicalEffects 1.15 /* @@ -31,6 +32,9 @@ import net.jami.Models 1.0 Button { id: hoverableButton + checkable: true + checked: false + property int fontPointSize: 9 property int buttonImageHeight: hoverableButtonBackground.height - 10 property int buttonImageWidth: hoverableButtonBackground.width - 10 @@ -43,6 +47,11 @@ Button { property alias radius: hoverableButtonBackground.radius property alias source: hoverableButtonImage.source + property var checkedImage: null + property var baseImage: null + property var checkedColor: null + property var baseColor: null + property alias color: hoverableButton.baseColor font.pointSize: fontPointSize @@ -64,18 +73,31 @@ Button { fillMode: Image.PreserveAspectFit mipmap: true asynchronous: true + + source: hoverableButton.checked && checkedImage? checkedImage : baseImage + + layer { + enabled: true + effect: ColorOverlay { + id: overlay + color: hoverableButton.checked && checkedColor? + checkedColor : + (baseColor? baseColor : "transparent") + } + } } MouseArea { anchors.fill: parent - hoverEnabled: true + hoverEnabled: false onPressed: { hoverableButtonBackground.color = onPressColor } onReleased: { hoverableButtonBackground.color = onReleaseColor + hoverableButton.toggle() hoverableButton.clicked() } onEntered: { diff --git a/src/mainview/MainView.qml b/src/mainview/MainView.qml index 20ac177040f31256c4b97fb186866f6861bff947..e948cd0bf5df78e33de410d3c67e30b65b6076e8 100644 --- a/src/mainview/MainView.qml +++ b/src/mainview/MainView.qml @@ -113,12 +113,14 @@ Window { function onCloseCallStack(accountId, convUid) { - + var responsibleCallId = ClientWrapper.utilsAdaptor.getCallId( + callStackView.responsibleAccountId, callStackView.responsibleConvUid) + var callId = ClientWrapper.utilsAdaptor.getCallId( + callStackView.responsibleAccountId, convUid) /* * Check if call stack view is on any of the stackview. */ - if (callStackView.responsibleAccountId === accountId - && callStackView.responsibleConvUid === convUid) { + if (responsibleCallId === callId || responsibleCallId.length === 0) { if (welcomeViewStack.find(function (item, index) { return item.objectName === "callStackViewObject" }) || sidePanelViewStack.find(function (item, index) { @@ -156,7 +158,7 @@ Window { communicationPageMessageWebView.headerUserUserNameLabelText = (name !== id) ? id : "" callStackView.needToCloseInCallConversationAndPotentialWindow() - callStackView.setCorrspondingMessageWebView( + callStackView.setLinkedWebview( communicationPageMessageWebView) callStackView.responsibleAccountId = accountId @@ -283,7 +285,7 @@ Window { * Set up chatview. */ MessagesAdapter.setupChatView(currentUID) - callStackView.setCorrspondingMessageWebView( + callStackView.setLinkedWebview( communicationPageMessageWebView) if (welcomeViewStack.find(function (item, index) { @@ -363,22 +365,6 @@ Window { visible: false objectName: "callStackViewObject" - - onCallPageBackButtonIsClicked: { - mainViewWindowSidePanel.deselectConversationSmartList() - if (welcomeViewStack.visible) - welcomeViewStack.pop(welcomePage) - else if (sidePanelViewStack.visible) - sidePanelViewStack.pop(mainViewWindowSidePanel) - } - - onOutgoingCallPageBackButtonIsClicked: { - mainViewWindowSidePanel.deselectConversationSmartList() - if (welcomeViewStack.visible) - welcomeViewStack.pop(welcomePage) - else if (sidePanelViewStack.visible) - sidePanelViewStack.pop(mainViewWindowSidePanel) - } } WelcomePage { diff --git a/src/mainview/components/AudioCallPage.qml b/src/mainview/components/AudioCallPage.qml index 1292f30aa5a0405477bf357c337058716c1b25a9..9c3f46c00056f2881ed3281d0dc967ade023c381 100644 --- a/src/mainview/components/AudioCallPage.qml +++ b/src/mainview/components/AudioCallPage.qml @@ -31,9 +31,7 @@ Rectangle { property string bestName: "Best Name" property string bestId: "Best Id" - property var corrspondingMessageWebView: null - - signal audioCallPageBackButtonIsClicked + property var linkedWebview: null function updateUI(accountId, convUid) { contactImgSource = "data:image/png;base64," + ClientWrapper.utilsAdaptor.getContactImageString( @@ -44,19 +42,19 @@ Rectangle { bestId = (bestName !== id) ? id : "" } - function setAudioCallPageCorrspondingMessageWebView(webViewId) { - corrspondingMessageWebView = webViewId - corrspondingMessageWebView.needToHideConversationInCall.disconnect( + function setLinkedWebview(webViewId) { + linkedWebview = webViewId + linkedWebview.needToHideConversationInCall.disconnect( closeInCallConversation) - corrspondingMessageWebView.needToHideConversationInCall.connect( + linkedWebview.needToHideConversationInCall.connect( closeInCallConversation) } function closeInCallConversation() { if (inAudioCallMessageWebViewStack.visible) { - corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( + linkedWebview.resetMessagingHeaderBackButtonSource( true) - corrspondingMessageWebView.setMessagingHeaderButtonsVisible(true) + linkedWebview.setMessagingHeaderButtonsVisible(true) inAudioCallMessageWebViewStack.visible = false inAudioCallMessageWebViewStack.clear() } @@ -109,7 +107,7 @@ Rectangle { isVideoMuted, isRecording, isSIP, isConferenceCall) - audioCallOverlay.bestName = bestName + audioCallPageRect.bestName = bestName } function onShowOnHoldLabel(isPaused) { @@ -118,34 +116,22 @@ Rectangle { } } - onBackButtonIsClicked: { - if (inAudioCallMessageWebViewStack.visible) { - corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( - true) - corrspondingMessageWebView.setMessagingHeaderButtonsVisible( - true) - inAudioCallMessageWebViewStack.visible = false - inAudioCallMessageWebViewStack.clear() - } - audioCallPageRect.audioCallPageBackButtonIsClicked() - } - onOverlayChatButtonClicked: { if (inAudioCallMessageWebViewStack.visible) { - corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( + linkedWebview.resetMessagingHeaderBackButtonSource( true) - corrspondingMessageWebView.setMessagingHeaderButtonsVisible( + linkedWebview.setMessagingHeaderButtonsVisible( true) inAudioCallMessageWebViewStack.visible = false inAudioCallMessageWebViewStack.clear() } else { - corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( + linkedWebview.resetMessagingHeaderBackButtonSource( false) - corrspondingMessageWebView.setMessagingHeaderButtonsVisible( + linkedWebview.setMessagingHeaderButtonsVisible( false) inAudioCallMessageWebViewStack.visible = true inAudioCallMessageWebViewStack.push( - corrspondingMessageWebView) + linkedWebview) } } } diff --git a/src/mainview/components/CallAdvancedOptions.qml b/src/mainview/components/CallAdvancedOptions.qml new file mode 100644 index 0000000000000000000000000000000000000000..7a9b4e9729ca951f47ba984993b80b851861e83b --- /dev/null +++ b/src/mainview/components/CallAdvancedOptions.qml @@ -0,0 +1,146 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * 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.12 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Popup { + id: contactPickerPopup + + property int type: ContactPicker.ContactPickerType.JAMICONFERENCE + + + /* + * Important to keep it one, since enum in c++ starts at one for conferences. + */ + enum ContactPickerType { + JAMICONFERENCE = 1, + SIPTRANSFER + } + + contentWidth: 250 + contentHeight: contactPickerPopupRectColumnLayout.height + 50 + + padding: 0 + + modal: true + + contentItem: Rectangle { + id: contactPickerPopupRect + + width: 250 + + HoverableButton { + id: closeButton + + anchors.top: contactPickerPopupRect.top + anchors.topMargin: 5 + anchors.right: contactPickerPopupRect.right + anchors.rightMargin: 5 + + width: 30 + height: 30 + + radius: 30 + source: "qrc:/images/icons/ic_close_black_24dp.png" + + onClicked: { + contactPickerPopup.close() + } + } + + ColumnLayout { + id: contactPickerPopupRectColumnLayout + + anchors.top: contactPickerPopupRect.top + anchors.topMargin: 15 + + Text { + id: contactPickerTitle + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: contactPickerPopupRect.width + Layout.preferredHeight: 30 + + font.pointSize: JamiTheme.textFontSize + font.bold: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: type === ContactPicker.ContactPickerType.JAMICONFERENCE ? qsTr("Add to conference") : qsTr("Transfer this call") + } + + ContactSearchBar { + id: contactPickerContactSearchBar + + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 5 + Layout.bottomMargin: 5 + Layout.preferredWidth: contactPickerPopupRect.width - 10 + Layout.preferredHeight: 35 + + onContactSearchBarTextChanged: { + ContactAdapter.setSearchFilter(text) + } + + Component.onCompleted: { + contactPickerContactSearchBar.setPlaceholderString( + qsTr("Search contacts")) + } + } + + ListView { + id: contactPickerListView + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: contactPickerPopupRect.width + Layout.preferredHeight: 200 + + model: ContactAdapter.getContactSelectableModel(type) + + clip: true + + delegate: ContactPickerItemDelegate { + id: contactPickerItemDelegate + } + + ScrollIndicator.vertical: ScrollIndicator {} + } + } + + radius: 10 + color: "white" + } + + onAboutToShow: { + // Reset the model on each show. + contactPickerListView.model = ContactAdapter.getContactSelectableModel( + type) + } + + background: Rectangle { + color: "transparent" + } +} diff --git a/src/mainview/components/CallOverlay.qml b/src/mainview/components/CallOverlay.qml index dfd599afdb607827907f5b62370057cd29dd6e7c..7a6b3f1e1a4eb5da209807349c45f02d5f2571c7 100644 --- a/src/mainview/components/CallOverlay.qml +++ b/src/mainview/components/CallOverlay.qml @@ -2,6 +2,7 @@ /* * Copyright (C) 2020 by Savoir-faire Linux * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * 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 @@ -30,13 +31,21 @@ import "../../commoncomponents" Rectangle { id: callOverlayRect - property string bestName: "Best Name" property string timeText: "00:00" - signal backButtonIsClicked signal overlayChatButtonClicked + function setRecording(isRecording) { + callViewContextMenu.isRecording = isRecording + recordingRect.visible = isRecording + } + function updateButtonStatus(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall) { + callViewContextMenu.isSIP = isSIP + callViewContextMenu.isPaused = isPaused + callViewContextMenu.isAudioOnly = isAudioOnly + callViewContextMenu.isRecording = isRecording + recordingRect.visible = isRecording callOverlayButtonGroup.setButtonStatus(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, @@ -51,10 +60,6 @@ Rectangle { ContactPickerCreation.closeContactPicker() } - function setBackTintedButtonVisible(visible) { - backTintedButton.visible = visible - } - anchors.fill: parent @@ -88,37 +93,17 @@ Rectangle { anchors.fill: parent - TintedButton { - id: backTintedButton - - Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft - Layout.leftMargin: 5 - Layout.preferredWidth: 30 - Layout.preferredHeight: 30 - - tintColor: JamiTheme.buttonTintedBlue - normalPixmapSource: "qrc:/images/icons/ic_arrow_back_white_24dp.png" - selectedPixmapSource: "qrc:/images/icons/ic_arrow_back_white_24dp.png" - - onClicked: { - callOverlayRect.backButtonIsClicked() - } - - onButtonEntered: { - callOverlayRectMouseArea.entered() - } - } - Text { id: jamiBestNameText Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft Layout.preferredWidth: overlayUpperPartRect.width / 3 Layout.preferredHeight: 50 + leftPadding: 16 font.pointSize: JamiTheme.textFontSize - horizontalAlignment: Text.AlignHCenter + horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter text: textMetricsjamiBestNameText.elidedText @@ -127,35 +112,50 @@ Rectangle { TextMetrics { id: textMetricsjamiBestNameText font: jamiBestNameText.font - text: bestName + text: videoCallPageRect.bestName elideWidth: overlayUpperPartRect.width / 3 - elide: Qt.ElideMiddle + elide: Qt.ElideRight } } Text { id: callTimerText - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight Layout.preferredWidth: overlayUpperPartRect.width / 3 - Layout.preferredHeight: 50 - + Layout.preferredHeight: 48 font.pointSize: JamiTheme.textFontSize - - horizontalAlignment: Text.AlignHCenter + horizontalAlignment: Text.AlignRight verticalAlignment: Text.AlignVCenter - text: textMetricscallTimerText.elidedText color: "white" - TextMetrics { id: textMetricscallTimerText font: callTimerText.font text: timeText elideWidth: overlayUpperPartRect.width / 3 - elide: Qt.ElideMiddle + elide: Qt.ElideRight + } + } + + Rectangle { + id: recordingRect + Layout.alignment: Qt.AlignVCenter | Qt.AlignRight + height: 16 + width: 16 + radius: height / 2 + color: "red" + + SequentialAnimation on color { + loops: Animation.Infinite + running: true + ColorAnimation { from: "red"; to: "transparent"; duration: 500 } + ColorAnimation { from: "transparent"; to: "red"; duration: 500 } } } + + Item { + width: 8 + } } color: "transparent" @@ -215,8 +215,8 @@ Rectangle { anchors.bottomMargin: 10 anchors.horizontalCenter: callOverlayRect.horizontalCenter - width: callOverlayRect.width / 3 * 2 - height: 60 + height: 56 + width: callOverlayRect.width opacity: 0 onChatButtonClicked: { @@ -224,8 +224,6 @@ Rectangle { } onAddToConferenceButtonClicked: { - - /* * Create contact picker - conference. */ @@ -237,24 +235,6 @@ Rectangle { ContactPickerCreation.openContactPicker() } - onTransferCallButtonClicked: { - - - /* - * Create contact picker - sip transfer. - */ - ContactPickerCreation.createContactPickerObjects( - ContactPicker.ContactPickerType.SIPTRANSFER, - callOverlayRect) - ContactPickerCreation.calculateCurrentGeo( - callOverlayRect.width / 2, callOverlayRect.height / 2) - ContactPickerCreation.openContactPicker() - } - - onButtonEntered: { - callOverlayRectMouseArea.entered() - } - states: [ State { name: "entered" @@ -365,10 +345,6 @@ Rectangle { color: "transparent" - onBestNameChanged: { - ContactAdapter.setCalleeDisplayName(bestName) - } - onWidthChanged: { ContactPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2, callOverlayRect.height / 2) @@ -378,4 +354,20 @@ Rectangle { ContactPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2, callOverlayRect.height / 2) } + + CallViewContextMenu { + id: callViewContextMenu + + onTransferCallButtonClicked: { + /* + * Create contact picker - sip transfer. + */ + ContactPickerCreation.createContactPickerObjects( + ContactPicker.ContactPickerType.SIPTRANSFER, + callOverlayRect) + ContactPickerCreation.calculateCurrentGeo( + callOverlayRect.width / 2, callOverlayRect.height / 2) + ContactPickerCreation.openContactPicker() + } + } } diff --git a/src/mainview/components/CallOverlayButtonGroup.qml b/src/mainview/components/CallOverlayButtonGroup.qml index 4309fa1b1b10dcf378489268f652a9d795cf8259..cddc0ea854e3450fc1641f94a22687abf91c4031 100644 --- a/src/mainview/components/CallOverlayButtonGroup.qml +++ b/src/mainview/components/CallOverlayButtonGroup.qml @@ -1,6 +1,7 @@ /* * Copyright (C) 2020 by Savoir-faire Linux + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify @@ -26,286 +27,193 @@ import net.jami.Models 1.0 import "../../commoncomponents" Rectangle { - id: callOverlayButtonGroupRect - + id: root /* * 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 buttonCounts: 9 - property int buttonPreferredSize: 30 + property int buttonPreferredSize: 24 - signal buttonEntered signal chatButtonClicked signal addToConferenceButtonClicked - signal transferCallButtonClicked function setButtonStatus(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall) { noVideoButton.visible = !isAudioOnly addToConferenceButton.visible = !isSIP - transferCallButton.visible = isSIP - sipInputPanelButton.visible = isSIP - - noMicButton.setChecked(isAudioMuted) - noVideoButton.setChecked(isVideoMuted) - recButton.setChecked(isRecording) - holdButton.setChecked(isPaused) - holdButton.visible = !isConferenceCall + noMicButton.checked = isAudioMuted + noVideoButton.checked = isVideoMuted } - function calculateFlowMargin() { - return (callOverlayButtonGroupRect.width - buttonCounts * buttonPreferredSize - - callOverlayButtonGroupRectFlow.spacing * (buttonCounts - 1)) / 2 - } - - Flow { - id: callOverlayButtonGroupRectFlow - - anchors.fill: parent - - - /* - * Minus 1 is to make sure that button will not flick when doing flow layout. - */ - anchors.leftMargin: calculateFlowMargin( - ) < 0 ? 0 : calculateFlowMargin() - 1 - anchors.rightMargin: calculateFlowMargin( - ) < 0 ? 0 : calculateFlowMargin() - 1 - - spacing: 10 - - TintedButton { - id: hangUpButton - - width: buttonPreferredSize - height: buttonPreferredSize + color: "transparent" + z: 2 - tintColor: JamiTheme.hangUpButtonTintedRed - normalPixmapSource: "qrc:/images/icons/ic_close_white_24dp.png" - selectedPixmapSource: "qrc:/images/icons/ic_close_white_24dp.png" + RowLayout { + id: callOverlayButtonGroup - onButtonEntered: { - callOverlayButtonGroupRect.buttonEntered() - } + spacing: 8 + height: 56 - onClicked: { - CallAdapter.hangUpThisCall() - } + anchors.fill: parent - onVisibleChanged: { - if (this.visible) - buttonCounts++ - else - buttonCounts-- + Item { + Layout.preferredWidth: { + // 6 is the number of button + // If ~ 500px, go into wide mode + (callOverlayButtonGroup.width < buttonPreferredSize * 12 - callOverlayButtonGroup.spacing * 6 + 300)? + 0 : callOverlayButtonGroup.width / 2 - buttonPreferredSize * 3 - callOverlayButtonGroup.spacing } } - TintedButton { - id: holdButton + HoverableButton { + id: noMicButton - width: buttonPreferredSize - height: buttonPreferredSize + Layout.preferredWidth: buttonPreferredSize * 2 + Layout.preferredHeight: buttonPreferredSize * 2 - tintColor: JamiTheme.buttonTintedBlue - normalPixmapSource: "qrc:/images/icons/ic_pause_white_24dp.png" - selectedPixmapSource: "qrc:/images/icons/ic_play_white_24dp.png" + backgroundColor: Qt.rgba(0, 0, 0, 0.75) + onEnterColor: Qt.rgba(0, 0, 0, 0.6) + onPressColor: Qt.rgba(0, 0, 0, 0.5) + onReleaseColor: Qt.rgba(0, 0, 0, 0.6) + onExitColor: Qt.rgba(0, 0, 0, 0.75) - onClicked: { - CallAdapter.holdThisCallToggle() - } - - onButtonEntered: { - callOverlayButtonGroupRect.buttonEntered() - } + buttonImageHeight: buttonPreferredSize + buttonImageWidth: buttonPreferredSize + baseImage: "qrc:/images/icons/ic_mic_white_24dp.png" + checkedImage: "qrc:/images/icons/ic_mic_off_white_24dp.png" + baseColor: "white" + checkedColor: JamiTheme.declineButtonPressedRed + radius: 30 - onVisibleChanged: { - if (this.visible) - buttonCounts++ - else - buttonCounts-- + onClicked: { + CallAdapter.muteThisCallToggle() } } - TintedButton { - id: addToConferenceButton + HoverableButton { + id: hangUpButton - width: buttonPreferredSize - height: buttonPreferredSize + Layout.preferredWidth: buttonPreferredSize * 2 + Layout.preferredHeight: buttonPreferredSize * 2 - tintColor: JamiTheme.buttonTintedBlue - normalPixmapSource: "qrc:/images/icons/ic_group_add_white_24dp.png" - selectedPixmapSource: "qrc:/images/icons/ic_group_add_white_24dp.png" + backgroundColor: JamiTheme.declineButtonRed + onEnterColor: JamiTheme.declineButtonHoverRed + onPressColor: JamiTheme.declineButtonPressedRed + onReleaseColor: JamiTheme.declineButtonHoverRed + onExitColor: JamiTheme.declineButtonRed - onButtonEntered: { - callOverlayButtonGroupRect.buttonEntered() - } + buttonImageHeight: buttonPreferredSize + buttonImageWidth: buttonPreferredSize + source: "qrc:/images/icons/ic_call_end_white_24px.svg" + color: "white" + radius: 30 onClicked: { - callOverlayButtonGroupRect.addToConferenceButtonClicked() - } - - onVisibleChanged: { - if (this.visible) - buttonCounts++ - else - buttonCounts-- + CallAdapter.hangUpThisCall() } } - TintedButton { - id: transferCallButton + HoverableButton { + id: noVideoButton - width: buttonPreferredSize - height: buttonPreferredSize + Layout.preferredWidth: buttonPreferredSize * 2 + Layout.preferredHeight: buttonPreferredSize * 2 - tintColor: JamiTheme.buttonTintedBlue - normalPixmapSource: "qrc:/images/icons/ic_call_transfer_white_24px.png" - selectedPixmapSource: "qrc:/images/icons/ic_call_transfer_white_24px.png" + backgroundColor: Qt.rgba(0, 0, 0, 0.75) + onEnterColor: Qt.rgba(0, 0, 0, 0.6) + onPressColor: Qt.rgba(0, 0, 0, 0.5) + onReleaseColor: Qt.rgba(0, 0, 0, 0.6) + onExitColor: Qt.rgba(0, 0, 0, 0.75) - onButtonEntered: { - callOverlayButtonGroupRect.buttonEntered() - } + buttonImageHeight: buttonPreferredSize + buttonImageWidth: buttonPreferredSize + baseImage: "qrc:/images/icons/ic_videocam_white.png" + checkedImage: "qrc:/images/icons/ic_videocam_off_white_24dp.png" + baseColor: "white" + checkedColor: JamiTheme.declineButtonPressedRed + radius: 30 onClicked: { - callOverlayButtonGroupRect.transferCallButtonClicked() - } - - onVisibleChanged: { - if (this.visible) - buttonCounts++ - else - buttonCounts-- + CallAdapter.videoPauseThisCallToggle() } } - TintedButton { - id: chatButton - - width: buttonPreferredSize - height: buttonPreferredSize - - tintColor: JamiTheme.buttonTintedBlue - normalPixmapSource: "qrc:/images/icons/ic_chat_white_24dp.png" - selectedPixmapSource: "qrc:/images/icons/ic_chat_white_24dp.png" - - onClicked: { - callOverlayButtonGroupRect.chatButtonClicked() - } - - onButtonEntered: { - callOverlayButtonGroupRect.buttonEntered() - } - - onVisibleChanged: { - if (this.visible) - buttonCounts++ - else - buttonCounts-- - } + Item { + Layout.fillWidth: true } - TintedButton { - id: noMicButton + HoverableButton { + id: addToConferenceButton - width: buttonPreferredSize - height: buttonPreferredSize + Layout.preferredWidth: buttonPreferredSize * 2 + Layout.preferredHeight: buttonPreferredSize * 2 - tintColor: JamiTheme.buttonTintedBlue - normalPixmapSource: "qrc:/images/icons/ic_mic_white_24dp.png" - selectedPixmapSource: "qrc:/images/icons/ic_mic_off_white_24dp.png" + backgroundColor: Qt.rgba(0, 0, 0, 0.75) + onEnterColor: Qt.rgba(0, 0, 0, 0.6) + onPressColor: Qt.rgba(0, 0, 0, 0.5) + onReleaseColor: Qt.rgba(0, 0, 0, 0.6) + onExitColor: Qt.rgba(0, 0, 0, 0.75) - onClicked: { - CallAdapter.muteThisCallToggle() - } - - onButtonEntered: { - callOverlayButtonGroupRect.buttonEntered() - } + buttonImageHeight: buttonPreferredSize + buttonImageWidth: buttonPreferredSize + color: "white" + source: "qrc:/images/icons/ic_group_add_white_24dp.png" + radius: 30 - onVisibleChanged: { - if (this.visible) - buttonCounts++ - else - buttonCounts-- + onClicked: { + root.addToConferenceButtonClicked() } } - TintedButton { - id: noVideoButton + HoverableButton { + id: chatButton - width: buttonPreferredSize - height: buttonPreferredSize + Layout.preferredWidth: buttonPreferredSize * 2 + Layout.preferredHeight: buttonPreferredSize * 2 - tintColor: JamiTheme.buttonTintedBlue - normalPixmapSource: "qrc:/images/icons/ic_videocam_white.png" - selectedPixmapSource: "qrc:/images/icons/ic_videocam_off_white_24dp.png" + backgroundColor: Qt.rgba(0, 0, 0, 0.75) + onEnterColor: Qt.rgba(0, 0, 0, 0.6) + onPressColor: Qt.rgba(0, 0, 0, 0.5) + onReleaseColor: Qt.rgba(0, 0, 0, 0.6) + onExitColor: Qt.rgba(0, 0, 0, 0.75) - onButtonEntered: { - callOverlayButtonGroupRect.buttonEntered() - } + buttonImageHeight: buttonPreferredSize + buttonImageWidth: buttonPreferredSize + color: "white" + source: "qrc:/images/icons/ic_chat_white_24dp.png" + radius: 30 onClicked: { - CallAdapter.videoPauseThisCallToggle() - } - - onVisibleChanged: { - if (this.visible) - buttonCounts++ - else - buttonCounts-- + root.chatButtonClicked() } } - TintedButton { - id: recButton + HoverableButton { + id: optionsButton - width: buttonPreferredSize - height: buttonPreferredSize + Layout.preferredWidth: buttonPreferredSize * 2 + Layout.preferredHeight: buttonPreferredSize * 2 - tintColor: JamiTheme.buttonTintedBlue - normalPixmapSource: "qrc:/images/icons/ic_voicemail_white_24dp_2x.png" - selectedPixmapSource: "qrc:/images/icons/ic_voicemail_white_24dp_2x.png" + backgroundColor: Qt.rgba(0, 0, 0, 0.75) + onEnterColor: Qt.rgba(0, 0, 0, 0.6) + onPressColor: Qt.rgba(0, 0, 0, 0.5) + onReleaseColor: Qt.rgba(0, 0, 0, 0.6) + onExitColor: Qt.rgba(0, 0, 0, 0.75) - onButtonEntered: { - callOverlayButtonGroupRect.buttonEntered() - } + buttonImageHeight: buttonPreferredSize + buttonImageWidth: buttonPreferredSize + source: "qrc:/images/icons/more_vert-24px.svg" + radius: 30 onClicked: { - CallAdapter.recordThisCallToggle() - } - - onVisibleChanged: { - if (this.visible) - buttonCounts++ - else - buttonCounts-- + var rectPos = mapToItem(callStackViewWindow, optionsButton.x, optionsButton.y) + callViewContextMenu.activate() + callViewContextMenu.x = rectPos.x + optionsButton.width/2 - callViewContextMenu.width/2 + callViewContextMenu.y = rectPos.y - 12 - callViewContextMenu.height } } - TintedButton { - id: sipInputPanelButton - - width: buttonPreferredSize - height: buttonPreferredSize - - tintColor: JamiTheme.buttonTintedBlue - normalPixmapSource: "qrc:/images/icons/icon-keypad-24-2x.png" - selectedPixmapSource: "qrc:/images/icons/icon-keypad-24-2x.png" - - onButtonEntered: { - callOverlayButtonGroupRect.buttonEntered() - } - - onVisibleChanged: { - if (this.visible) - buttonCounts++ - else - buttonCounts-- - } - } + Item { Layout.preferredWidth: 8 } } - - color: "transparent" } diff --git a/src/mainview/components/CallStackView.qml b/src/mainview/components/CallStackView.qml index 61df06e3ec17d51750b73ee59ddd8180b35d7a2c..27a2b55e8eb1b0575e355950b4e3bcdb46a52903 100644 --- a/src/mainview/components/CallStackView.qml +++ b/src/mainview/components/CallStackView.qml @@ -44,9 +44,6 @@ Rectangle { property string responsibleConvUid: "" property string responsibleAccountId: "" - signal outgoingCallPageBackButtonIsClicked - signal callPageBackButtonIsClicked - function needToCloseInCallConversationAndPotentialWindow() { audioCallPage.closeInCallConversation() videoCallPage.closeInCallConversation() @@ -58,13 +55,12 @@ Rectangle { audioCallPage.closeContextMenuAndRelatedWindows() VideoCallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer() - videoCallPage.setCallOverlayBackButtonVisible(true) videoCallPage.closeContextMenuAndRelatedWindows() } - function setCorrspondingMessageWebView(webViewId) { - audioCallPage.setAudioCallPageCorrspondingMessageWebView(webViewId) - videoCallPage.setVideoCallPageCorrspondingMessageWebView(webViewId) + function setLinkedWebview(webViewId) { + audioCallPage.setLinkedWebview(webViewId) + videoCallPage.setLinkedWebview(webViewId) } function updateCorrspondingUI() { @@ -172,10 +168,6 @@ Rectangle { id: audioCallPage property int stackNumber: 0 - - onAudioCallPageBackButtonIsClicked: { - callStackViewWindow.callPageBackButtonIsClicked() - } } OutgoingCallPage { @@ -186,32 +178,24 @@ Rectangle { onCallCancelButtonIsClicked: { CallAdapter.hangUpACall(responsibleAccountId, responsibleConvUid) } - - onBackButtonIsClicked: { - callStackViewWindow.outgoingCallPageBackButtonIsClicked() - } } VideoCallPage { id: videoCallPage property int stackNumber: 2 - - onVideoCallPageBackButtonIsClicked: { - callStackViewWindow.callPageBackButtonIsClicked() - } + property bool isFullscreen: false onNeedToShowInFullScreen: { + isFullscreen = !isFullscreen VideoCallFullScreenWindowContainerCreation.createvideoCallFullScreenWindowContainerObject() if (!VideoCallFullScreenWindowContainerCreation.checkIfVisible()) { VideoCallFullScreenWindowContainerCreation.setAsContainerChild( videoCallPage) - videoCallPage.setCallOverlayBackButtonVisible(false) VideoCallFullScreenWindowContainerCreation.showVideoCallFullScreenWindowContainer() } else { videoCallPage.parent = callStackMainView - videoCallPage.setCallOverlayBackButtonVisible(true) VideoCallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer() } } diff --git a/src/mainview/components/VideoCallPageContextMenu.qml b/src/mainview/components/CallViewContextMenu.qml similarity index 52% rename from src/mainview/components/VideoCallPageContextMenu.qml rename to src/mainview/components/CallViewContextMenu.qml index 642ec2444421404a278d8aa915894ab2280adcf8..93b008f1db281c895b07281cb445dab20955ce4d 100644 --- a/src/mainview/components/VideoCallPageContextMenu.qml +++ b/src/mainview/components/CallViewContextMenu.qml @@ -1,7 +1,7 @@ - /* * Copyright (C) 2020 by Savoir-faire Linux * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * 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 @@ -18,44 +18,45 @@ */ import QtQuick 2.14 import QtQuick.Controls 2.14 +import QtGraphicalEffects 1.12 import net.jami.Models 1.0 import "../../commoncomponents" import "../js/videodevicecontextmenuitemcreation.js" as VideoDeviceContextMenuItemCreation import "../js/selectscreenwindowcreation.js" as SelectScreenWindowCreation -import "../js/screenrubberbandcreation.js" as ScreenRubberBandCreation Menu { - id: contextMenu - - property string responsibleAccountId: "" - property string responsibleConvUid: "" + id: root property int generalMenuSeparatorCount: 0 - property int commonBorderWidth: 2 + property int commonBorderWidth: 1 + font.pointSize: JamiTheme.textFontSize+3 + + property bool isSIP: false + property bool isPaused: false + property bool isAudioOnly: false + property bool isRecording: false - signal fullScreenNeeded + signal transferCallButtonClicked function activate() { var deviceContextMenuInfoMap = AvAdapter.populateVideoDeviceContextMenuItem() - - /* * Somehow, the map size is undefined, so use this instead. */ var mapSize = deviceContextMenuInfoMap["size"] - var count = 1 + var count = 2 for (var deviceName in deviceContextMenuInfoMap) { - if (deviceName === "size") + if (deviceName === "size" || root.isAudioOnly) continue if (videoDeviceItem.itemName === "No video device") { videoDeviceItem.checkable = true videoDeviceItem.itemName = deviceName videoDeviceItem.checked = deviceContextMenuInfoMap[deviceName] if (count === mapSize) - contextMenu.open() + root.open() } else { VideoDeviceContextMenuItemCreation.createVideoDeviceContextMenuItemObjects( deviceName, deviceContextMenuInfoMap[deviceName], @@ -63,14 +64,18 @@ Menu { } count++ } + root.open() } - function closePotentialWindows() { - SelectScreenWindowCreation.destorySelectScreenWindow() - ScreenRubberBandCreation.destoryScreenRubberBandWindow() + Component.onCompleted: { + VideoDeviceContextMenuItemCreation.setVideoContextMenuObject(root) } - implicitWidth: 200 + + onClosed: { + videoDeviceItem.itemName = "No video device" + VideoDeviceContextMenuItemCreation.removeCreatedItems() + } JamiFileDialog { id: jamiFileDialog @@ -78,31 +83,111 @@ Menu { mode: JamiFileDialog.Mode.OpenFile onAccepted: { - var filePath = jamiFileDialog.file - - - /* - * No need to trim file:///. - */ - AvAdapter.shareFile(filePath) + // No need to trim file:///. + AvAdapter.shareFile(jamiFileDialog.file) } } - /* * All GeneralMenuItems should remain the same width / height. - * The first videoDeviceItem is to make sure the border is correct. */ + GeneralMenuItem { + id: holdCallButton + + visible: isSIP + height: isSIP? undefined : 0 + + itemName: isPaused? qsTr("Resume call") : qsTr("Hold call") + iconSource: isPaused? "qrc:/images/icons/play_circle_outline-24px.svg" : "qrc:/images/icons/pause_circle_outline-24px.svg" + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + + onClicked: { + CallAdapter.holdThisCallToggle() + root.close() + } + } + + GeneralMenuItem { + id: transferCallButton + + visible: isSIP + height: isSIP? undefined : 0 + + itemName: qsTr("Transfer call") + iconSource: "qrc:/images/icons/phone_forwarded-24px.svg" + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + + onClicked: { + root.transferCallButtonClicked() + root.close() + } + } + + GeneralMenuSeparator { + preferredWidth: startRecordingItem.preferredWidth + preferredHeight: commonBorderWidth + + visible: isSIP + height: isSIP? undefined : 0 + + Component.onCompleted: { + generalMenuSeparatorCount++ + } + } + + GeneralMenuItem { + id: startRecordingItem + + itemName: isRecording? qsTr("Stop recording") : qsTr("Start recording") + iconSource: "qrc:/images/icons/ic_video_call_24px.svg" + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + + onClicked: { + root.close() + CallAdapter.recordThisCallToggle() + } + } + + GeneralMenuItem { + id: fullScreenItem + + itemName: videoCallPage.isFullscreen ? qsTr("Exit full screen") : qsTr( + "Full screen mode") + iconSource: videoCallPage.isFullscreen ? "qrc:/images/icons/close_fullscreen-24px.svg" : "qrc:/images/icons/open_in_full-24px.svg" + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + + onClicked: { + root.close() + videoCallPageRect.needToShowInFullScreen() + } + } + + GeneralMenuSeparator { + preferredWidth: startRecordingItem.preferredWidth + preferredHeight: commonBorderWidth + + Component.onCompleted: { + generalMenuSeparatorCount++ + } + } + VideoCallPageContextMenuDeviceItem { id: videoDeviceItem + visible: !isAudioOnly + height: !isAudioOnly? undefined : 0 - topBorderWidth: commonBorderWidth - contextMenuPreferredWidth: contextMenu.implicitWidth + contextMenuPreferredWidth: root.implicitWidth } GeneralMenuSeparator { - preferredWidth: videoDeviceItem.preferredWidth + preferredWidth: startRecordingItem.preferredWidth preferredHeight: commonBorderWidth + visible: !isAudioOnly + height: !isAudioOnly? undefined : 0 Component.onCompleted: { generalMenuSeparatorCount++ @@ -113,11 +198,14 @@ Menu { id: shareEntireScreenItem itemName: qsTr("Share entire screen") + iconSource: "qrc:/images/icons/screen_share-24px.svg" leftBorderWidth: commonBorderWidth rightBorderWidth: commonBorderWidth + visible: !isAudioOnly + height: !isAudioOnly? undefined : 0 onClicked: { - contextMenu.close() + root.close() if (Qt.application.screens.length === 1) { AvAdapter.shareEntireScreen(0) } else { @@ -131,11 +219,14 @@ Menu { id: shareScreenAreaItem itemName: qsTr("Share screen area") + iconSource: "qrc:/images/icons/screen_share-24px.svg" leftBorderWidth: commonBorderWidth rightBorderWidth: commonBorderWidth + visible: !isAudioOnly + height: !isAudioOnly? undefined : 0 onClicked: { - contextMenu.close() + root.close() if (Qt.application.screens.length === 1) { ScreenRubberBandCreation.createScreenRubberBandWindowObject( null, 0) @@ -151,59 +242,56 @@ Menu { id: shareFileItem itemName: qsTr("Share file") + iconSource: "qrc:/images/icons/insert_photo-24px.svg" leftBorderWidth: commonBorderWidth rightBorderWidth: commonBorderWidth + visible: !isAudioOnly + height: !isAudioOnly? undefined : 0 onClicked: { - contextMenu.close() + root.close() jamiFileDialog.open() } } - GeneralMenuSeparator { - preferredWidth: videoDeviceItem.preferredWidth - preferredHeight: commonBorderWidth - - Component.onCompleted: { - generalMenuSeparatorCount++ - } - } + /* TODO: In the future we want to implement this GeneralMenuItem { - id: fullScreenItem - - property bool isFullScreen: false + id: advancedInfosItem - itemName: isFullScreen ? qsTr("Exit full screen") : qsTr( - "Full screen mode") - iconSource: isFullScreen ? "qrc:/images/icons/ic_exit_full_screen_black.png" : "qrc:/images/icons/ic_full_screen_black.png" + itemName: qsTr("Advanced informations") + iconSource: "qrc:/images/icons/info-24px.svg" leftBorderWidth: commonBorderWidth rightBorderWidth: commonBorderWidth - bottomBorderWidth: commonBorderWidth onClicked: { - contextMenu.close() - contextMenu.fullScreenNeeded() - isFullScreen = !isFullScreen + root.close() } } - onClosed: { - videoDeviceItem.itemName = "No video device" - VideoDeviceContextMenuItemCreation.removeCreatedItems() - } + GeneralMenuItem { + id: pluginItem - Component.onCompleted: { - VideoDeviceContextMenuItemCreation.setVideoContextMenuObject( - contextMenu) - } + itemName: qsTr("Toggle plugin") + iconSource: "qrc:/images/icons/extension_24dp.svg" + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + + onClicked: { + root.close() + } + }*/ background: Rectangle { - implicitWidth: contextMenu.implicitWidth - implicitHeight: videoDeviceItem.preferredHeight - * (contextMenu.count - generalMenuSeparatorCount) + implicitWidth: startRecordingItem.preferredWidth + implicitHeight: startRecordingItem.preferredHeight + * (root.count + - (isSIP? 0 : 2) + - (isAudioOnly? 6 : 0) + - generalMenuSeparatorCount) border.width: commonBorderWidth border.color: JamiTheme.tabbarBorderColor } } + diff --git a/src/mainview/components/OutgoingCallPage.qml b/src/mainview/components/OutgoingCallPage.qml index 6148d46eee34535acf9c580ff6a56bf29d6c0b31..79866183a7a56235f2a74f2bcf5931ba2871f239 100644 --- a/src/mainview/components/OutgoingCallPage.qml +++ b/src/mainview/components/OutgoingCallPage.qml @@ -34,7 +34,6 @@ Rectangle { property string bestId: "Best Id" signal callCancelButtonIsClicked - signal backButtonIsClicked function updateUI(accountId, convUid) { contactImgSource = "data:image/png;base64," + ClientWrapper.utilsAdaptor.getContactImageString( @@ -58,26 +57,6 @@ Rectangle { acceptedButtons: Qt.RightButton } - TintedButton { - id: backTintedButton - - anchors.top: outgoingCallPageRect.top - anchors.topMargin: 10 - anchors.left: outgoingCallPageRect.left - anchors.leftMargin: 5 - - width: 30 - height: 30 - - tintColor: JamiTheme.buttonTintedBlue - normalPixmapSource: "qrc:/images/icons/ic_arrow_back_white_24dp.png" - selectedPixmapSource: "qrc:/images/icons/ic_arrow_back_white_24dp.png" - - onClicked: { - outgoingCallPageRect.backButtonIsClicked() - } - } - ColumnLayout { id: outgoingCallPageRectColumnLayout diff --git a/src/mainview/components/VideoCallPage.qml b/src/mainview/components/VideoCallPage.qml index e1f29b9bedf5486d81a7febe77bed79c461dbcab..4657a7ed3c99a9cc2ee08c3c3381688262b674f4 100644 --- a/src/mainview/components/VideoCallPage.qml +++ b/src/mainview/components/VideoCallPage.qml @@ -2,6 +2,7 @@ /* * Copyright (C) 2020 by Savoir-faire Linux * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * 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 @@ -32,12 +33,12 @@ Rectangle { property string bestId: "Best Id" property variant clickPos: "1,1" property int previewMargin: 15 + property int previewMarginY: previewMargin + 56 property int previewToX: 0 property int previewToY: 0 - property var corrspondingMessageWebView: null + property var linkedWebview: null - signal videoCallPageBackButtonIsClicked signal needToShowInFullScreen function updateUI(accountId, convUid) { @@ -51,27 +52,25 @@ Rectangle { distantRenderer.setRendererId(id) } - function setVideoCallPageCorrspondingMessageWebView(webViewId) { - corrspondingMessageWebView = webViewId - corrspondingMessageWebView.needToHideConversationInCall.disconnect( + function setLinkedWebview(webViewId) { + linkedWebview = webViewId + linkedWebview.needToHideConversationInCall.disconnect( closeInCallConversation) - corrspondingMessageWebView.needToHideConversationInCall.connect( + linkedWebview.needToHideConversationInCall.connect( closeInCallConversation) } function closeInCallConversation() { if (inVideoCallMessageWebViewStack.visible) { - corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( + linkedWebview.resetMessagingHeaderBackButtonSource( true) - corrspondingMessageWebView.setMessagingHeaderButtonsVisible(true) + linkedWebview.setMessagingHeaderButtonsVisible(true) inVideoCallMessageWebViewStack.visible = false inVideoCallMessageWebViewStack.clear() } } function closeContextMenuAndRelatedWindows() { - videoCallPageContextMenu.closePotentialWindows() - videoCallPageContextMenu.close() videoCallOverlay.closePotentialContactPicker() } @@ -99,7 +98,7 @@ Rectangle { return videoCallPageMainRect.width - previewRenderer.width - previewMargin }) previewToY = Qt.binding(function () { - return videoCallPageMainRect.height - previewRenderer.height - previewMargin + return videoCallPageMainRect.height - previewRenderer.height - previewMarginY }) } else { @@ -110,7 +109,7 @@ Rectangle { previewToX = Qt.binding(function () { return videoCallPageMainRect.width - previewRenderer.width - previewMargin }) - previewToY = previewMargin + previewToY = previewMarginY } } else { if (previewRendererCenter.y >= distantRendererCenter.y) { @@ -121,7 +120,7 @@ Rectangle { */ previewToX = previewMargin previewToY = Qt.binding(function () { - return videoCallPageMainRect.height - previewRenderer.height - previewMargin + return videoCallPageMainRect.height - previewRenderer.height - previewMarginY }) } else { @@ -130,16 +129,12 @@ Rectangle { * Top left. */ previewToX = previewMargin - previewToY = previewMargin + previewToY = previewMarginY } } previewRenderer.state = "geoChanging" } - function setCallOverlayBackButtonVisible(visible) { - videoCallOverlay.setBackTintedButtonVisible(visible) - } - anchors.fill: parent SplitView { @@ -155,182 +150,182 @@ Rectangle { color: SplitHandle.pressed ? JamiTheme.pressColor : (SplitHandle.hovered ? JamiTheme.hoverColor : JamiTheme.tabbarBorderColor) } + Rectangle { id: videoCallPageMainRect - SplitView.preferredHeight: (videoCallPageRect.height / 3) * 2 SplitView.minimumHeight: videoCallPageRect.height / 2 + 20 SplitView.fillWidth: true - CallOverlay { - id: videoCallOverlay - + MouseArea { anchors.fill: parent + hoverEnabled: true + propagateComposedEvents: true - Connections { - target: CallAdapter + acceptedButtons: Qt.LeftButton - function onUpdateTimeText(time) { - videoCallOverlay.timeText = time - } + onDoubleClicked: { + needToShowInFullScreen() + } - function onUpdateOverlay(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall, bestName) { - videoCallOverlay.showOnHoldImage(isPaused) - videoCallOverlay.updateButtonStatus(isPaused, - isAudioOnly, - isAudioMuted, - isVideoMuted, - isRecording, isSIP, - isConferenceCall) - videoCallOverlay.bestName = bestName - } + CallOverlay { + id: videoCallOverlay - function onShowOnHoldLabel(isPaused) { - videoCallOverlay.showOnHoldImage(isPaused) - } - } + anchors.fill: parent + + Connections { + target: CallAdapter + + function onUpdateTimeText(time) { + videoCallOverlay.timeText = time + videoCallOverlay.setRecording(CallAdapter.isRecordingThisCall()) + } + + function onUpdateOverlay(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall, bestName) { + videoCallOverlay.showOnHoldImage(isPaused) + videoCallOverlay.updateButtonStatus(isPaused, + isAudioOnly, + isAudioMuted, + isVideoMuted, + isRecording, isSIP, + isConferenceCall) + videoCallPageRect.bestName = bestName + } - onBackButtonIsClicked: { - if (inVideoCallMessageWebViewStack.visible) { - corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( - true) - corrspondingMessageWebView.setMessagingHeaderButtonsVisible( - true) - inVideoCallMessageWebViewStack.visible = false - inVideoCallMessageWebViewStack.clear() + function onShowOnHoldLabel(isPaused) { + videoCallOverlay.showOnHoldImage(isPaused) + } } - videoCallPageRect.videoCallPageBackButtonIsClicked() - } - onOverlayChatButtonClicked: { - if (inVideoCallMessageWebViewStack.visible) { - corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( - true) - corrspondingMessageWebView.setMessagingHeaderButtonsVisible( - true) - inVideoCallMessageWebViewStack.visible = false - inVideoCallMessageWebViewStack.clear() - } else { - corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( - false) - corrspondingMessageWebView.setMessagingHeaderButtonsVisible( - false) - inVideoCallMessageWebViewStack.visible = true - inVideoCallMessageWebViewStack.push( - corrspondingMessageWebView) + onOverlayChatButtonClicked: { + if (inVideoCallMessageWebViewStack.visible) { + linkedWebview.resetMessagingHeaderBackButtonSource( + true) + linkedWebview.setMessagingHeaderButtonsVisible( + true) + inVideoCallMessageWebViewStack.visible = false + inVideoCallMessageWebViewStack.clear() + } else { + linkedWebview.resetMessagingHeaderBackButtonSource( + false) + linkedWebview.setMessagingHeaderButtonsVisible( + false) + inVideoCallMessageWebViewStack.visible = true + inVideoCallMessageWebViewStack.push( + linkedWebview) + } } } - } - DistantRenderer { - id: distantRenderer + DistantRenderer { + id: distantRenderer - anchors.centerIn: videoCallPageMainRect - z: -1 + anchors.centerIn: videoCallPageMainRect + z: -1 - width: videoCallPageMainRect.width - height: videoCallPageMainRect.height - } + width: videoCallPageMainRect.width + height: videoCallPageMainRect.height + } - VideoCallPreviewRenderer { - id: previewRenderer + VideoCallPreviewRenderer { + id: previewRenderer - /* - * Property is used in the {} expression for height (extra dependency), - * it will not affect the true height expression, since expression - * at last will be taken only, but it will force the height to update - * and reevaluate getPreviewImageScalingFactor(). - */ - property int previewImageScalingFactorUpdated: 0 + /* + * Property is used in the {} expression for height (extra dependency), + * it will not affect the true height expression, since expression + * at last will be taken only, but it will force the height to update + * and reevaluate getPreviewImageScalingFactor(). + */ + property int previewImageScalingFactorUpdated: 0 - Connections { - target: CallAdapter + Connections { + target: CallAdapter - function onPreviewVisibilityNeedToChange(visible) { - previewRenderer.visible = visible + onPreviewVisibilityNeedToChange: previewRenderer.visible = visible } - } - width: videoCallPageMainRect.width / 4 - height: { - previewImageScalingFactorUpdated - return previewRenderer.width * previewRenderer.getPreviewImageScalingFactor() - } - x: videoCallPageMainRect.width - previewRenderer.width - previewMargin - y: videoCallPageMainRect.height - previewRenderer.height - previewMargin - z: -1 - - states: [ - State { - name: "geoChanging" - PropertyChanges { - target: previewRenderer - x: previewToX - y: previewToY - } + width: videoCallPageMainRect.width / 4 + height: { + previewImageScalingFactorUpdated + return previewRenderer.width * previewRenderer.getPreviewImageScalingFactor() } - ] + x: videoCallPageMainRect.width - previewRenderer.width - previewMargin + y: videoCallPageMainRect.height - previewRenderer.height - previewMargin - 56 /* Avoid overlay */ + z: -1 + + states: [ + State { + name: "geoChanging" + PropertyChanges { + target: previewRenderer + x: previewToX + y: previewToY + } + } + ] - transitions: Transition { - PropertyAnimation { - properties: "x,y" - easing.type: Easing.OutExpo - duration: 250 + transitions: Transition { + PropertyAnimation { + properties: "x,y" + easing.type: Easing.OutExpo + duration: 250 - onStopped: { - previewRenderer.state = "" + onStopped: { + previewRenderer.state = "" + } } } - } - MouseArea { - id: dragMouseArea + MouseArea { + id: dragMouseArea - anchors.fill: previewRenderer + anchors.fill: previewRenderer - onPressed: { - clickPos = Qt.point(mouse.x, mouse.y) - } + onPressed: { + clickPos = Qt.point(mouse.x, mouse.y) + } - onReleased: { - previewRenderer.state = "" - previewMagneticSnap() - } + onReleased: { + previewRenderer.state = "" + previewMagneticSnap() + } - onPositionChanged: { + onPositionChanged: { - /* - * Calculate mouse position relative change. - */ - var delta = Qt.point(mouse.x - clickPos.x, - mouse.y - clickPos.y) - var deltaW = previewRenderer.x + delta.x + previewRenderer.width - var deltaH = previewRenderer.y + delta.y + previewRenderer.height + /* + * Calculate mouse position relative change. + */ + var delta = Qt.point(mouse.x - clickPos.x, + mouse.y - clickPos.y) + var deltaW = previewRenderer.x + delta.x + previewRenderer.width + var deltaH = previewRenderer.y + delta.y + previewRenderer.height - /* - * Check if the previewRenderer exceeds the border of videoCallPageMainRect. - */ - if (deltaW < videoCallPageMainRect.width - && previewRenderer.x + delta.x > 1) - previewRenderer.x += delta.x - if (deltaH < videoCallPageMainRect.height - && previewRenderer.y + delta.y > 1) - previewRenderer.y += delta.y + /* + * Check if the previewRenderer exceeds the border of videoCallPageMainRect. + */ + if (deltaW < videoCallPageMainRect.width + && previewRenderer.x + delta.x > 1) + previewRenderer.x += delta.x + if (deltaH < videoCallPageMainRect.height + && previewRenderer.y + delta.y > 1) + previewRenderer.y += delta.y + } } - } - onPreviewImageAvailable: { - previewImageScalingFactorUpdated++ - previewImageScalingFactorUpdated-- + onPreviewImageAvailable: { + previewImageScalingFactorUpdated++ + previewImageScalingFactorUpdated-- + } } } color: "transparent" } + StackView { id: inVideoCallMessageWebViewStack @@ -343,32 +338,8 @@ Rectangle { } } - VideoCallPageContextMenu { - id: videoCallPageContextMenu - - onFullScreenNeeded: { - videoCallPageRect.needToShowInFullScreen() - } - } - - MouseArea { - anchors.fill: parent - - propagateComposedEvents: true - acceptedButtons: Qt.RightButton - - onClicked: { - - - /* - * Make menu pos at mouse. - */ - var relativeMousePos = mapToItem(videoCallPageRect, - mouse.x, mouse.y) - videoCallPageContextMenu.x = relativeMousePos.x - videoCallPageContextMenu.y = relativeMousePos.y - videoCallPageContextMenu.activate() - } + onBestNameChanged: { + ContactAdapter.setCalleeDisplayName(bestName) } color: "black" diff --git a/src/mainview/components/VideoCallPageContextMenuDeviceItem.qml b/src/mainview/components/VideoCallPageContextMenuDeviceItem.qml index f94a99794e43662c4173f1fce941f82ca35d984f..73e692b7d790507eeb2b4255a3dc799b66ead7ef 100644 --- a/src/mainview/components/VideoCallPageContextMenuDeviceItem.qml +++ b/src/mainview/components/VideoCallPageContextMenuDeviceItem.qml @@ -31,60 +31,26 @@ GeneralMenuItem { property int contextMenuPreferredWidth: 250 - itemName: qsTr("No video device") leftBorderWidth: commonBorderWidth rightBorderWidth: commonBorderWidth TextMetrics { id: textMetrics - font: deviceNameText.font elide: Text.ElideMiddle elideWidth: contextMenuPreferredWidth - videoCallPageContextMenuDeviceItem.implicitIndicatorWidth text: videoCallPageContextMenuDeviceItem.itemName } - contentItem: Text { - id: deviceNameText + itemName: textMetrics.elidedText.length !== 0 ? + textMetrics.elidedText : + qsTr("No video device") - leftPadding: 30 - rightPadding: videoCallPageContextMenuDeviceItem.arrow.width + indicator: null - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - - font.pointSize: JamiTheme.textFontSize - 3 - text: textMetrics.elidedText - } - - indicator: Item { - id: selectItem - - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - - implicitWidth: 32 - implicitHeight: 32 - - Rectangle { - id: selectRect - - width: selectItem.width / 2 - height: selectItem.height / 2 - anchors.centerIn: parent - visible: videoCallPageContextMenuDeviceItem.checkable - border.color: JamiTheme.selectionGreen - radius: 3 - Rectangle { - width: selectRect.width / 2 - height: selectRect.height / 2 - anchors.centerIn: parent - visible: videoCallPageContextMenuDeviceItem.checked - color: JamiTheme.selectionGreen - radius: 2 - } - } - } + iconSource: videoCallPageContextMenuDeviceItem.checked ? + "qrc:/images/icons/check_box-24px.svg" : + "qrc:/images/icons/check_box_outline_blank-24px.svg" onClicked: { var deviceName = videoCallPageContextMenuDeviceItem.itemName diff --git a/src/mainview/js/videodevicecontextmenuitemcreation.js b/src/mainview/js/videodevicecontextmenuitemcreation.js index 2bab369ac6c4f8b284986863fb5c7315364f0505..02aa292538d83a23f54d0aad341a0bd34d99bbbf 100644 --- a/src/mainview/js/videodevicecontextmenuitemcreation.js +++ b/src/mainview/js/videodevicecontextmenuitemcreation.js @@ -54,11 +54,7 @@ function createVideoDeviceContextMenuItemObjects(deviceName, setChecked, last) { function finishCreation(deviceName, setChecked, last) { videoDeviceContextMenuItemObject = videoDeviceContextMenuItemComponent.createObject() if (videoDeviceContextMenuItemObject === null) { - - - /* - * Error Handling. - */ + // Error Handling. console.log("Error creating video context menu object") } @@ -72,7 +68,7 @@ function finishCreation(deviceName, setChecked, last) { * Push into the storage array, and insert it into context menu. */ itemArray.push(videoDeviceContextMenuItemObject) - videoContextMenuObject.insertItem(1, videoDeviceContextMenuItemObject) + videoContextMenuObject.insertItem(3 /* The button is at pos 3 in the menu */, videoDeviceContextMenuItemObject) /*