callview: redesign
Change-Id: I8ce1e02be798104aaca9d09d9dc5d931133ada6d
1
images/icons/check_box-24px.svg
Normal file
|
@ -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>
|
After Width: | Height: | Size: 269 B |
1
images/icons/check_box_outline_blank-24px.svg
Normal file
|
@ -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>
|
After Width: | Height: | Size: 228 B |
1
images/icons/close_fullscreen-24px.svg
Normal file
|
@ -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>
|
After Width: | Height: | Size: 291 B |
4
images/icons/ic_call_end_white_24px.svg
Normal file
|
@ -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>
|
After Width: | Height: | Size: 553 B |
Before Width: | Height: | Size: 1.3 KiB |
4
images/icons/ic_high_quality_24px.svg
Normal file
|
@ -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>
|
After Width: | Height: | Size: 398 B |
Before Width: | Height: | Size: 218 B |
Before Width: | Height: | Size: 90 B |
1
images/icons/insert_photo-24px.svg
Normal file
|
@ -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>
|
After Width: | Height: | Size: 258 B |
3
images/icons/more_vert-24px.svg
Normal file
|
@ -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>
|
After Width: | Height: | Size: 302 B |
1
images/icons/open_in_full-24px.svg
Normal file
|
@ -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>
|
After Width: | Height: | Size: 260 B |
1
images/icons/pause_circle_outline-24px.svg
Normal file
|
@ -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>
|
After Width: | Height: | Size: 290 B |
1
images/icons/phone_forwarded-24px.svg
Normal file
|
@ -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>
|
After Width: | Height: | Size: 406 B |
1
images/icons/play_circle_outline-24px.svg
Normal file
|
@ -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>
|
After Width: | Height: | Size: 285 B |
1
images/icons/screen_share-24px.svg
Normal file
|
@ -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>
|
After Width: | Height: | Size: 319 B |
1
images/icons/videocam-24px.svg
Normal file
|
@ -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>
|
After Width: | Height: | Size: 239 B |
3
qml.qrc
|
@ -66,6 +66,7 @@
|
||||||
<file>src/mainview/js/incomingcallpagecreation.js</file>
|
<file>src/mainview/js/incomingcallpagecreation.js</file>
|
||||||
<file>src/mainview/components/ContactSearchBar.qml</file>
|
<file>src/mainview/components/ContactSearchBar.qml</file>
|
||||||
<file>src/mainview/components/VideoCallPage.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/ChangeLogScrollView.qml</file>
|
||||||
<file>src/mainview/components/ProjectCreditsScrollView.qml</file>
|
<file>src/mainview/components/ProjectCreditsScrollView.qml</file>
|
||||||
<file>src/mainview/components/AccountComboBoxPopup.qml</file>
|
<file>src/mainview/components/AccountComboBoxPopup.qml</file>
|
||||||
|
@ -75,9 +76,9 @@
|
||||||
<file>src/mainview/components/WelcomePageQrDialog.qml</file>
|
<file>src/mainview/components/WelcomePageQrDialog.qml</file>
|
||||||
<file>src/commoncomponents/GeneralMenuItem.qml</file>
|
<file>src/commoncomponents/GeneralMenuItem.qml</file>
|
||||||
<file>src/mainview/components/ConversationSmartListContextMenu.qml</file>
|
<file>src/mainview/components/ConversationSmartListContextMenu.qml</file>
|
||||||
|
<file>src/mainview/components/CallViewContextMenu.qml</file>
|
||||||
<file>src/commoncomponents/GeneralMenuSeparator.qml</file>
|
<file>src/commoncomponents/GeneralMenuSeparator.qml</file>
|
||||||
<file>src/mainview/components/UserProfile.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/js/videodevicecontextmenuitemcreation.js</file>
|
||||||
<file>src/mainview/components/VideoCallPageContextMenuDeviceItem.qml</file>
|
<file>src/mainview/components/VideoCallPageContextMenuDeviceItem.qml</file>
|
||||||
<file>src/mainview/components/SelectScreen.qml</file>
|
<file>src/mainview/components/SelectScreen.qml</file>
|
||||||
|
|
|
@ -32,22 +32,23 @@
|
||||||
<file>images/icons/ic_arrow_tab_next_black_9dp_2x.png</file>
|
<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_arrow_tab_previous_black_9dp_2x.png</file>
|
||||||
<file>images/icons/ic_block_24px.svg</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_black_24dp_2x.png</file>
|
||||||
<file>images/icons/ic_chat_white_24dp.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_check_white_18dp_2x.png</file>
|
||||||
<file>images/icons/ic_clear_24px.svg</file>
|
<file>images/icons/ic_clear_24px.svg</file>
|
||||||
<file>images/icons/ic_close_white_24dp.png</file>
|
<file>images/icons/ic_close_white_24dp.png</file>
|
||||||
<file>images/icons/ic_content_copy.svg</file>
|
<file>images/icons/ic_content_copy.svg</file>
|
||||||
<file>images/icons/ic_delete_black_18dp_2x.png</file>
|
<file>images/icons/ic_delete_black_18dp_2x.png</file>
|
||||||
<file>images/icons/ic_done_white_24dp.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_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_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_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_pause_white_100px.png</file>
|
||||||
<file>images/icons/ic_person_add_black_24dp_2x.png</file>
|
<file>images/icons/ic_person_add_black_24dp_2x.png</file>
|
||||||
<file>images/icons/ic_person_add_white_24dp.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_off_white_24dp.png</file>
|
||||||
<file>images/icons/ic_videocam_white.png</file>
|
<file>images/icons/ic_videocam_white.png</file>
|
||||||
<file>images/icons/ic_voicemail_white_24dp_2x.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-add-24px.svg</file>
|
||||||
<file>images/icons/round-arrow_drop_down-24px.svg</file>
|
<file>images/icons/round-arrow_drop_down-24px.svg</file>
|
||||||
<file>images/icons/round-arrow_drop_up-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/ic_show_password.png</file>
|
||||||
<file>images/icons/baseline-desktop_windows-24px.svg</file>
|
<file>images/icons/baseline-desktop_windows-24px.svg</file>
|
||||||
<file>images/icons/baseline-people-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/round-add_a_photo-24px.svg</file>
|
||||||
<file>images/icons/ic_mic_white_24dp.png</file>
|
<file>images/icons/ic_mic_white_24dp.png</file>
|
||||||
<file>images/icons/icon-keypad-24.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/send-24px.svg</file>
|
||||||
<file>images/icons/av_icons/stop-24px.svg</file>
|
<file>images/icons/av_icons/stop-24px.svg</file>
|
||||||
<file>images/icons/av_icons/mic-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/ic_close_black_24dp.png</file>
|
||||||
<file>images/icons/extension_24dp.svg</file>
|
<file>images/icons/extension_24dp.svg</file>
|
||||||
<file>images/icons/settings_backup_restore-black-18dp.svg</file>
|
<file>images/icons/settings_backup_restore-black-18dp.svg</file>
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 by Savoir-faire Linux
|
* Copyright (C) 2020 by Savoir-faire Linux
|
||||||
* Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>
|
* 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: Olivier Soldano <olivier.soldano@savoirfairelinux.com>
|
||||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||||
* Author: Isa Nanic <isa.nanic@savoirfairelinux.com>
|
* Author: Isa Nanic <isa.nanic@savoirfairelinux.com>
|
||||||
* Author: Mingrui Zhang <mingrui.zhang@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
|
* 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
|
* 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::disconnect(oneSecondTimer_);
|
||||||
QObject::connect(oneSecondTimer_, &QTimer::timeout, [this] { setTime(accountId_, convUid_); });
|
QObject::connect(oneSecondTimer_, &QTimer::timeout, [this] { setTime(accountId_, convUid_); });
|
||||||
oneSecondTimer_->start(20);
|
oneSecondTimer_->start(20);
|
||||||
|
|
||||||
auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId_);
|
auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId_);
|
||||||
|
|
||||||
auto call = LRCInstance::getCallInfoForConversation(convInfo);
|
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
|
void
|
||||||
CallAdapter::holdThisCallToggle()
|
CallAdapter::holdThisCallToggle()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 by Savoir-faire Linux
|
* Copyright (C) 2020 by Savoir-faire Linux
|
||||||
* Author: Mingrui Zhang <mingrui.zhang@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
|
* 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
|
* 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 muteThisCallToggle();
|
||||||
Q_INVOKABLE void recordThisCallToggle();
|
Q_INVOKABLE void recordThisCallToggle();
|
||||||
Q_INVOKABLE void videoPauseThisCallToggle();
|
Q_INVOKABLE void videoPauseThisCallToggle();
|
||||||
|
Q_INVOKABLE bool isRecordingThisCall();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void showOutgoingCallPage(const QString &accountId, const QString &convUid);
|
void showOutgoingCallPage(const QString &accountId, const QString &convUid);
|
||||||
|
@ -106,8 +108,7 @@ private:
|
||||||
/*
|
/*
|
||||||
* For Call Overlay
|
* For Call Overlay
|
||||||
*/
|
*/
|
||||||
void setTime(const QString &accountId, const QString &convUid);
|
|
||||||
void updateCallOverlay(const lrc::api::conversation::Info &convInfo);
|
void updateCallOverlay(const lrc::api::conversation::Info &convInfo);
|
||||||
|
void setTime(const QString &accountId, const QString &convUid);
|
||||||
QTimer *oneSecondTimer_;
|
QTimer *oneSecondTimer_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
import QtQuick 2.14
|
import QtQuick 2.14
|
||||||
import QtQuick.Controls 2.14
|
import QtQuick.Controls 2.14
|
||||||
import net.jami.Models 1.0
|
import net.jami.Models 1.0
|
||||||
|
import QtGraphicalEffects 1.15
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -31,6 +32,9 @@ import net.jami.Models 1.0
|
||||||
Button {
|
Button {
|
||||||
id: hoverableButton
|
id: hoverableButton
|
||||||
|
|
||||||
|
checkable: true
|
||||||
|
checked: false
|
||||||
|
|
||||||
property int fontPointSize: 9
|
property int fontPointSize: 9
|
||||||
property int buttonImageHeight: hoverableButtonBackground.height - 10
|
property int buttonImageHeight: hoverableButtonBackground.height - 10
|
||||||
property int buttonImageWidth: hoverableButtonBackground.width - 10
|
property int buttonImageWidth: hoverableButtonBackground.width - 10
|
||||||
|
@ -43,6 +47,11 @@ Button {
|
||||||
|
|
||||||
property alias radius: hoverableButtonBackground.radius
|
property alias radius: hoverableButtonBackground.radius
|
||||||
property alias source: hoverableButtonImage.source
|
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
|
font.pointSize: fontPointSize
|
||||||
|
|
||||||
|
@ -64,18 +73,31 @@ Button {
|
||||||
fillMode: Image.PreserveAspectFit
|
fillMode: Image.PreserveAspectFit
|
||||||
mipmap: true
|
mipmap: true
|
||||||
asynchronous: 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 {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
hoverEnabled: true
|
hoverEnabled: false
|
||||||
|
|
||||||
onPressed: {
|
onPressed: {
|
||||||
hoverableButtonBackground.color = onPressColor
|
hoverableButtonBackground.color = onPressColor
|
||||||
}
|
}
|
||||||
onReleased: {
|
onReleased: {
|
||||||
hoverableButtonBackground.color = onReleaseColor
|
hoverableButtonBackground.color = onReleaseColor
|
||||||
|
hoverableButton.toggle()
|
||||||
hoverableButton.clicked()
|
hoverableButton.clicked()
|
||||||
}
|
}
|
||||||
onEntered: {
|
onEntered: {
|
||||||
|
|
|
@ -113,12 +113,14 @@ Window {
|
||||||
|
|
||||||
function onCloseCallStack(accountId, convUid) {
|
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.
|
* Check if call stack view is on any of the stackview.
|
||||||
*/
|
*/
|
||||||
if (callStackView.responsibleAccountId === accountId
|
if (responsibleCallId === callId || responsibleCallId.length === 0) {
|
||||||
&& callStackView.responsibleConvUid === convUid) {
|
|
||||||
if (welcomeViewStack.find(function (item, index) {
|
if (welcomeViewStack.find(function (item, index) {
|
||||||
return item.objectName === "callStackViewObject"
|
return item.objectName === "callStackViewObject"
|
||||||
}) || sidePanelViewStack.find(function (item, index) {
|
}) || sidePanelViewStack.find(function (item, index) {
|
||||||
|
@ -156,7 +158,7 @@ Window {
|
||||||
communicationPageMessageWebView.headerUserUserNameLabelText = (name !== id) ? id : ""
|
communicationPageMessageWebView.headerUserUserNameLabelText = (name !== id) ? id : ""
|
||||||
|
|
||||||
callStackView.needToCloseInCallConversationAndPotentialWindow()
|
callStackView.needToCloseInCallConversationAndPotentialWindow()
|
||||||
callStackView.setCorrspondingMessageWebView(
|
callStackView.setLinkedWebview(
|
||||||
communicationPageMessageWebView)
|
communicationPageMessageWebView)
|
||||||
|
|
||||||
callStackView.responsibleAccountId = accountId
|
callStackView.responsibleAccountId = accountId
|
||||||
|
@ -283,7 +285,7 @@ Window {
|
||||||
* Set up chatview.
|
* Set up chatview.
|
||||||
*/
|
*/
|
||||||
MessagesAdapter.setupChatView(currentUID)
|
MessagesAdapter.setupChatView(currentUID)
|
||||||
callStackView.setCorrspondingMessageWebView(
|
callStackView.setLinkedWebview(
|
||||||
communicationPageMessageWebView)
|
communicationPageMessageWebView)
|
||||||
|
|
||||||
if (welcomeViewStack.find(function (item, index) {
|
if (welcomeViewStack.find(function (item, index) {
|
||||||
|
@ -363,22 +365,6 @@ Window {
|
||||||
visible: false
|
visible: false
|
||||||
|
|
||||||
objectName: "callStackViewObject"
|
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 {
|
WelcomePage {
|
||||||
|
|
|
@ -31,9 +31,7 @@ Rectangle {
|
||||||
property string bestName: "Best Name"
|
property string bestName: "Best Name"
|
||||||
property string bestId: "Best Id"
|
property string bestId: "Best Id"
|
||||||
|
|
||||||
property var corrspondingMessageWebView: null
|
property var linkedWebview: null
|
||||||
|
|
||||||
signal audioCallPageBackButtonIsClicked
|
|
||||||
|
|
||||||
function updateUI(accountId, convUid) {
|
function updateUI(accountId, convUid) {
|
||||||
contactImgSource = "data:image/png;base64," + ClientWrapper.utilsAdaptor.getContactImageString(
|
contactImgSource = "data:image/png;base64," + ClientWrapper.utilsAdaptor.getContactImageString(
|
||||||
|
@ -44,19 +42,19 @@ Rectangle {
|
||||||
bestId = (bestName !== id) ? id : ""
|
bestId = (bestName !== id) ? id : ""
|
||||||
}
|
}
|
||||||
|
|
||||||
function setAudioCallPageCorrspondingMessageWebView(webViewId) {
|
function setLinkedWebview(webViewId) {
|
||||||
corrspondingMessageWebView = webViewId
|
linkedWebview = webViewId
|
||||||
corrspondingMessageWebView.needToHideConversationInCall.disconnect(
|
linkedWebview.needToHideConversationInCall.disconnect(
|
||||||
closeInCallConversation)
|
closeInCallConversation)
|
||||||
corrspondingMessageWebView.needToHideConversationInCall.connect(
|
linkedWebview.needToHideConversationInCall.connect(
|
||||||
closeInCallConversation)
|
closeInCallConversation)
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeInCallConversation() {
|
function closeInCallConversation() {
|
||||||
if (inAudioCallMessageWebViewStack.visible) {
|
if (inAudioCallMessageWebViewStack.visible) {
|
||||||
corrspondingMessageWebView.resetMessagingHeaderBackButtonSource(
|
linkedWebview.resetMessagingHeaderBackButtonSource(
|
||||||
true)
|
true)
|
||||||
corrspondingMessageWebView.setMessagingHeaderButtonsVisible(true)
|
linkedWebview.setMessagingHeaderButtonsVisible(true)
|
||||||
inAudioCallMessageWebViewStack.visible = false
|
inAudioCallMessageWebViewStack.visible = false
|
||||||
inAudioCallMessageWebViewStack.clear()
|
inAudioCallMessageWebViewStack.clear()
|
||||||
}
|
}
|
||||||
|
@ -109,7 +107,7 @@ Rectangle {
|
||||||
isVideoMuted,
|
isVideoMuted,
|
||||||
isRecording, isSIP,
|
isRecording, isSIP,
|
||||||
isConferenceCall)
|
isConferenceCall)
|
||||||
audioCallOverlay.bestName = bestName
|
audioCallPageRect.bestName = bestName
|
||||||
}
|
}
|
||||||
|
|
||||||
function onShowOnHoldLabel(isPaused) {
|
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: {
|
onOverlayChatButtonClicked: {
|
||||||
if (inAudioCallMessageWebViewStack.visible) {
|
if (inAudioCallMessageWebViewStack.visible) {
|
||||||
corrspondingMessageWebView.resetMessagingHeaderBackButtonSource(
|
linkedWebview.resetMessagingHeaderBackButtonSource(
|
||||||
true)
|
true)
|
||||||
corrspondingMessageWebView.setMessagingHeaderButtonsVisible(
|
linkedWebview.setMessagingHeaderButtonsVisible(
|
||||||
true)
|
true)
|
||||||
inAudioCallMessageWebViewStack.visible = false
|
inAudioCallMessageWebViewStack.visible = false
|
||||||
inAudioCallMessageWebViewStack.clear()
|
inAudioCallMessageWebViewStack.clear()
|
||||||
} else {
|
} else {
|
||||||
corrspondingMessageWebView.resetMessagingHeaderBackButtonSource(
|
linkedWebview.resetMessagingHeaderBackButtonSource(
|
||||||
false)
|
false)
|
||||||
corrspondingMessageWebView.setMessagingHeaderButtonsVisible(
|
linkedWebview.setMessagingHeaderButtonsVisible(
|
||||||
false)
|
false)
|
||||||
inAudioCallMessageWebViewStack.visible = true
|
inAudioCallMessageWebViewStack.visible = true
|
||||||
inAudioCallMessageWebViewStack.push(
|
inAudioCallMessageWebViewStack.push(
|
||||||
corrspondingMessageWebView)
|
linkedWebview)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
146
src/mainview/components/CallAdvancedOptions.qml
Normal file
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 by Savoir-faire Linux
|
* Copyright (C) 2020 by Savoir-faire Linux
|
||||||
* Author: Mingrui Zhang <mingrui.zhang@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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -30,13 +31,21 @@ import "../../commoncomponents"
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: callOverlayRect
|
id: callOverlayRect
|
||||||
|
|
||||||
property string bestName: "Best Name"
|
|
||||||
property string timeText: "00:00"
|
property string timeText: "00:00"
|
||||||
|
|
||||||
signal backButtonIsClicked
|
|
||||||
signal overlayChatButtonClicked
|
signal overlayChatButtonClicked
|
||||||
|
|
||||||
|
function setRecording(isRecording) {
|
||||||
|
callViewContextMenu.isRecording = isRecording
|
||||||
|
recordingRect.visible = isRecording
|
||||||
|
}
|
||||||
|
|
||||||
function updateButtonStatus(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall) {
|
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,
|
callOverlayButtonGroup.setButtonStatus(isPaused, isAudioOnly,
|
||||||
isAudioMuted, isVideoMuted,
|
isAudioMuted, isVideoMuted,
|
||||||
isRecording, isSIP,
|
isRecording, isSIP,
|
||||||
|
@ -51,10 +60,6 @@ Rectangle {
|
||||||
ContactPickerCreation.closeContactPicker()
|
ContactPickerCreation.closeContactPicker()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setBackTintedButtonVisible(visible) {
|
|
||||||
backTintedButton.visible = visible
|
|
||||||
}
|
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,37 +93,17 @@ Rectangle {
|
||||||
|
|
||||||
anchors.fill: parent
|
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 {
|
Text {
|
||||||
id: jamiBestNameText
|
id: jamiBestNameText
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||||
Layout.preferredWidth: overlayUpperPartRect.width / 3
|
Layout.preferredWidth: overlayUpperPartRect.width / 3
|
||||||
Layout.preferredHeight: 50
|
Layout.preferredHeight: 50
|
||||||
|
leftPadding: 16
|
||||||
|
|
||||||
font.pointSize: JamiTheme.textFontSize
|
font.pointSize: JamiTheme.textFontSize
|
||||||
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignLeft
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
|
||||||
text: textMetricsjamiBestNameText.elidedText
|
text: textMetricsjamiBestNameText.elidedText
|
||||||
|
@ -127,35 +112,50 @@ Rectangle {
|
||||||
TextMetrics {
|
TextMetrics {
|
||||||
id: textMetricsjamiBestNameText
|
id: textMetricsjamiBestNameText
|
||||||
font: jamiBestNameText.font
|
font: jamiBestNameText.font
|
||||||
text: bestName
|
text: videoCallPageRect.bestName
|
||||||
elideWidth: overlayUpperPartRect.width / 3
|
elideWidth: overlayUpperPartRect.width / 3
|
||||||
elide: Qt.ElideMiddle
|
elide: Qt.ElideRight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: callTimerText
|
id: callTimerText
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||||
Layout.preferredWidth: overlayUpperPartRect.width / 3
|
Layout.preferredWidth: overlayUpperPartRect.width / 3
|
||||||
Layout.preferredHeight: 50
|
Layout.preferredHeight: 48
|
||||||
|
|
||||||
font.pointSize: JamiTheme.textFontSize
|
font.pointSize: JamiTheme.textFontSize
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
|
||||||
text: textMetricscallTimerText.elidedText
|
text: textMetricscallTimerText.elidedText
|
||||||
color: "white"
|
color: "white"
|
||||||
|
|
||||||
TextMetrics {
|
TextMetrics {
|
||||||
id: textMetricscallTimerText
|
id: textMetricscallTimerText
|
||||||
font: callTimerText.font
|
font: callTimerText.font
|
||||||
text: timeText
|
text: timeText
|
||||||
elideWidth: overlayUpperPartRect.width / 3
|
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"
|
color: "transparent"
|
||||||
|
@ -215,8 +215,8 @@ Rectangle {
|
||||||
anchors.bottomMargin: 10
|
anchors.bottomMargin: 10
|
||||||
anchors.horizontalCenter: callOverlayRect.horizontalCenter
|
anchors.horizontalCenter: callOverlayRect.horizontalCenter
|
||||||
|
|
||||||
width: callOverlayRect.width / 3 * 2
|
height: 56
|
||||||
height: 60
|
width: callOverlayRect.width
|
||||||
opacity: 0
|
opacity: 0
|
||||||
|
|
||||||
onChatButtonClicked: {
|
onChatButtonClicked: {
|
||||||
|
@ -224,8 +224,6 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
onAddToConferenceButtonClicked: {
|
onAddToConferenceButtonClicked: {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create contact picker - conference.
|
* Create contact picker - conference.
|
||||||
*/
|
*/
|
||||||
|
@ -237,24 +235,6 @@ Rectangle {
|
||||||
ContactPickerCreation.openContactPicker()
|
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: [
|
states: [
|
||||||
State {
|
State {
|
||||||
name: "entered"
|
name: "entered"
|
||||||
|
@ -365,10 +345,6 @@ Rectangle {
|
||||||
|
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
onBestNameChanged: {
|
|
||||||
ContactAdapter.setCalleeDisplayName(bestName)
|
|
||||||
}
|
|
||||||
|
|
||||||
onWidthChanged: {
|
onWidthChanged: {
|
||||||
ContactPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2,
|
ContactPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2,
|
||||||
callOverlayRect.height / 2)
|
callOverlayRect.height / 2)
|
||||||
|
@ -378,4 +354,20 @@ Rectangle {
|
||||||
ContactPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2,
|
ContactPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2,
|
||||||
callOverlayRect.height / 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 by Savoir-faire Linux
|
* Copyright (C) 2020 by Savoir-faire Linux
|
||||||
|
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -26,286 +27,193 @@ import net.jami.Models 1.0
|
||||||
import "../../commoncomponents"
|
import "../../commoncomponents"
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: callOverlayButtonGroupRect
|
id: root
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ButtonCounts here is to make sure that flow layout margin is calculated correctly,
|
* ButtonCounts here is to make sure that flow layout margin is calculated correctly,
|
||||||
* since no other methods can make buttons at the layout center.
|
* since no other methods can make buttons at the layout center.
|
||||||
*/
|
*/
|
||||||
property int buttonCounts: 9
|
property int buttonPreferredSize: 24
|
||||||
property int buttonPreferredSize: 30
|
|
||||||
|
|
||||||
signal buttonEntered
|
|
||||||
signal chatButtonClicked
|
signal chatButtonClicked
|
||||||
signal addToConferenceButtonClicked
|
signal addToConferenceButtonClicked
|
||||||
signal transferCallButtonClicked
|
|
||||||
|
|
||||||
function setButtonStatus(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall) {
|
function setButtonStatus(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall) {
|
||||||
noVideoButton.visible = !isAudioOnly
|
noVideoButton.visible = !isAudioOnly
|
||||||
addToConferenceButton.visible = !isSIP
|
addToConferenceButton.visible = !isSIP
|
||||||
transferCallButton.visible = isSIP
|
|
||||||
sipInputPanelButton.visible = isSIP
|
|
||||||
|
|
||||||
noMicButton.setChecked(isAudioMuted)
|
noMicButton.checked = isAudioMuted
|
||||||
noVideoButton.setChecked(isVideoMuted)
|
noVideoButton.checked = isVideoMuted
|
||||||
recButton.setChecked(isRecording)
|
|
||||||
holdButton.setChecked(isPaused)
|
|
||||||
|
|
||||||
holdButton.visible = !isConferenceCall
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateFlowMargin() {
|
color: "transparent"
|
||||||
return (callOverlayButtonGroupRect.width - buttonCounts * buttonPreferredSize
|
z: 2
|
||||||
- callOverlayButtonGroupRectFlow.spacing * (buttonCounts - 1)) / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
Flow {
|
RowLayout {
|
||||||
id: callOverlayButtonGroupRectFlow
|
id: callOverlayButtonGroup
|
||||||
|
|
||||||
|
spacing: 8
|
||||||
|
height: 56
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Item {
|
||||||
/*
|
Layout.preferredWidth: {
|
||||||
* Minus 1 is to make sure that button will not flick when doing flow layout.
|
// 6 is the number of button
|
||||||
*/
|
// If ~ 500px, go into wide mode
|
||||||
anchors.leftMargin: calculateFlowMargin(
|
(callOverlayButtonGroup.width < buttonPreferredSize * 12 - callOverlayButtonGroup.spacing * 6 + 300)?
|
||||||
) < 0 ? 0 : calculateFlowMargin() - 1
|
0 : callOverlayButtonGroup.width / 2 - buttonPreferredSize * 3 - callOverlayButtonGroup.spacing
|
||||||
anchors.rightMargin: calculateFlowMargin(
|
|
||||||
) < 0 ? 0 : calculateFlowMargin() - 1
|
|
||||||
|
|
||||||
spacing: 10
|
|
||||||
|
|
||||||
TintedButton {
|
|
||||||
id: hangUpButton
|
|
||||||
|
|
||||||
width: buttonPreferredSize
|
|
||||||
height: buttonPreferredSize
|
|
||||||
|
|
||||||
tintColor: JamiTheme.hangUpButtonTintedRed
|
|
||||||
normalPixmapSource: "qrc:/images/icons/ic_close_white_24dp.png"
|
|
||||||
selectedPixmapSource: "qrc:/images/icons/ic_close_white_24dp.png"
|
|
||||||
|
|
||||||
onButtonEntered: {
|
|
||||||
callOverlayButtonGroupRect.buttonEntered()
|
|
||||||
}
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
CallAdapter.hangUpThisCall()
|
|
||||||
}
|
|
||||||
|
|
||||||
onVisibleChanged: {
|
|
||||||
if (this.visible)
|
|
||||||
buttonCounts++
|
|
||||||
else
|
|
||||||
buttonCounts--
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TintedButton {
|
HoverableButton {
|
||||||
id: holdButton
|
|
||||||
|
|
||||||
width: buttonPreferredSize
|
|
||||||
height: buttonPreferredSize
|
|
||||||
|
|
||||||
tintColor: JamiTheme.buttonTintedBlue
|
|
||||||
normalPixmapSource: "qrc:/images/icons/ic_pause_white_24dp.png"
|
|
||||||
selectedPixmapSource: "qrc:/images/icons/ic_play_white_24dp.png"
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
CallAdapter.holdThisCallToggle()
|
|
||||||
}
|
|
||||||
|
|
||||||
onButtonEntered: {
|
|
||||||
callOverlayButtonGroupRect.buttonEntered()
|
|
||||||
}
|
|
||||||
|
|
||||||
onVisibleChanged: {
|
|
||||||
if (this.visible)
|
|
||||||
buttonCounts++
|
|
||||||
else
|
|
||||||
buttonCounts--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TintedButton {
|
|
||||||
id: addToConferenceButton
|
|
||||||
|
|
||||||
width: buttonPreferredSize
|
|
||||||
height: buttonPreferredSize
|
|
||||||
|
|
||||||
tintColor: JamiTheme.buttonTintedBlue
|
|
||||||
normalPixmapSource: "qrc:/images/icons/ic_group_add_white_24dp.png"
|
|
||||||
selectedPixmapSource: "qrc:/images/icons/ic_group_add_white_24dp.png"
|
|
||||||
|
|
||||||
onButtonEntered: {
|
|
||||||
callOverlayButtonGroupRect.buttonEntered()
|
|
||||||
}
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
callOverlayButtonGroupRect.addToConferenceButtonClicked()
|
|
||||||
}
|
|
||||||
|
|
||||||
onVisibleChanged: {
|
|
||||||
if (this.visible)
|
|
||||||
buttonCounts++
|
|
||||||
else
|
|
||||||
buttonCounts--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TintedButton {
|
|
||||||
id: transferCallButton
|
|
||||||
|
|
||||||
width: buttonPreferredSize
|
|
||||||
height: buttonPreferredSize
|
|
||||||
|
|
||||||
tintColor: JamiTheme.buttonTintedBlue
|
|
||||||
normalPixmapSource: "qrc:/images/icons/ic_call_transfer_white_24px.png"
|
|
||||||
selectedPixmapSource: "qrc:/images/icons/ic_call_transfer_white_24px.png"
|
|
||||||
|
|
||||||
onButtonEntered: {
|
|
||||||
callOverlayButtonGroupRect.buttonEntered()
|
|
||||||
}
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
callOverlayButtonGroupRect.transferCallButtonClicked()
|
|
||||||
}
|
|
||||||
|
|
||||||
onVisibleChanged: {
|
|
||||||
if (this.visible)
|
|
||||||
buttonCounts++
|
|
||||||
else
|
|
||||||
buttonCounts--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TintedButton {
|
|
||||||
id: noMicButton
|
id: noMicButton
|
||||||
|
|
||||||
width: buttonPreferredSize
|
Layout.preferredWidth: buttonPreferredSize * 2
|
||||||
height: buttonPreferredSize
|
Layout.preferredHeight: buttonPreferredSize * 2
|
||||||
|
|
||||||
tintColor: JamiTheme.buttonTintedBlue
|
backgroundColor: Qt.rgba(0, 0, 0, 0.75)
|
||||||
normalPixmapSource: "qrc:/images/icons/ic_mic_white_24dp.png"
|
onEnterColor: Qt.rgba(0, 0, 0, 0.6)
|
||||||
selectedPixmapSource: "qrc:/images/icons/ic_mic_off_white_24dp.png"
|
onPressColor: Qt.rgba(0, 0, 0, 0.5)
|
||||||
|
onReleaseColor: Qt.rgba(0, 0, 0, 0.6)
|
||||||
|
onExitColor: Qt.rgba(0, 0, 0, 0.75)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
CallAdapter.muteThisCallToggle()
|
CallAdapter.muteThisCallToggle()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onButtonEntered: {
|
HoverableButton {
|
||||||
callOverlayButtonGroupRect.buttonEntered()
|
id: hangUpButton
|
||||||
}
|
|
||||||
|
|
||||||
onVisibleChanged: {
|
Layout.preferredWidth: buttonPreferredSize * 2
|
||||||
if (this.visible)
|
Layout.preferredHeight: buttonPreferredSize * 2
|
||||||
buttonCounts++
|
|
||||||
else
|
backgroundColor: JamiTheme.declineButtonRed
|
||||||
buttonCounts--
|
onEnterColor: JamiTheme.declineButtonHoverRed
|
||||||
|
onPressColor: JamiTheme.declineButtonPressedRed
|
||||||
|
onReleaseColor: JamiTheme.declineButtonHoverRed
|
||||||
|
onExitColor: JamiTheme.declineButtonRed
|
||||||
|
|
||||||
|
buttonImageHeight: buttonPreferredSize
|
||||||
|
buttonImageWidth: buttonPreferredSize
|
||||||
|
source: "qrc:/images/icons/ic_call_end_white_24px.svg"
|
||||||
|
color: "white"
|
||||||
|
radius: 30
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
CallAdapter.hangUpThisCall()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TintedButton {
|
HoverableButton {
|
||||||
id: noVideoButton
|
id: noVideoButton
|
||||||
|
|
||||||
width: buttonPreferredSize
|
Layout.preferredWidth: buttonPreferredSize * 2
|
||||||
height: buttonPreferredSize
|
Layout.preferredHeight: buttonPreferredSize * 2
|
||||||
|
|
||||||
tintColor: JamiTheme.buttonTintedBlue
|
backgroundColor: Qt.rgba(0, 0, 0, 0.75)
|
||||||
normalPixmapSource: "qrc:/images/icons/ic_videocam_white.png"
|
onEnterColor: Qt.rgba(0, 0, 0, 0.6)
|
||||||
selectedPixmapSource: "qrc:/images/icons/ic_videocam_off_white_24dp.png"
|
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: {
|
buttonImageHeight: buttonPreferredSize
|
||||||
callOverlayButtonGroupRect.buttonEntered()
|
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: {
|
onClicked: {
|
||||||
CallAdapter.videoPauseThisCallToggle()
|
CallAdapter.videoPauseThisCallToggle()
|
||||||
}
|
}
|
||||||
|
|
||||||
onVisibleChanged: {
|
|
||||||
if (this.visible)
|
|
||||||
buttonCounts++
|
|
||||||
else
|
|
||||||
buttonCounts--
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TintedButton {
|
Item {
|
||||||
id: recButton
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
width: buttonPreferredSize
|
HoverableButton {
|
||||||
height: buttonPreferredSize
|
id: addToConferenceButton
|
||||||
|
|
||||||
tintColor: JamiTheme.buttonTintedBlue
|
Layout.preferredWidth: buttonPreferredSize * 2
|
||||||
normalPixmapSource: "qrc:/images/icons/ic_voicemail_white_24dp_2x.png"
|
Layout.preferredHeight: buttonPreferredSize * 2
|
||||||
selectedPixmapSource: "qrc:/images/icons/ic_voicemail_white_24dp_2x.png"
|
|
||||||
|
|
||||||
onButtonEntered: {
|
backgroundColor: Qt.rgba(0, 0, 0, 0.75)
|
||||||
callOverlayButtonGroupRect.buttonEntered()
|
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)
|
||||||
|
|
||||||
|
buttonImageHeight: buttonPreferredSize
|
||||||
|
buttonImageWidth: buttonPreferredSize
|
||||||
|
color: "white"
|
||||||
|
source: "qrc:/images/icons/ic_group_add_white_24dp.png"
|
||||||
|
radius: 30
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
CallAdapter.recordThisCallToggle()
|
root.addToConferenceButtonClicked()
|
||||||
}
|
|
||||||
|
|
||||||
onVisibleChanged: {
|
|
||||||
if (this.visible)
|
|
||||||
buttonCounts++
|
|
||||||
else
|
|
||||||
buttonCounts--
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TintedButton {
|
HoverableButton {
|
||||||
id: sipInputPanelButton
|
id: chatButton
|
||||||
|
|
||||||
width: buttonPreferredSize
|
Layout.preferredWidth: buttonPreferredSize * 2
|
||||||
height: buttonPreferredSize
|
Layout.preferredHeight: buttonPreferredSize * 2
|
||||||
|
|
||||||
tintColor: JamiTheme.buttonTintedBlue
|
backgroundColor: Qt.rgba(0, 0, 0, 0.75)
|
||||||
normalPixmapSource: "qrc:/images/icons/icon-keypad-24-2x.png"
|
onEnterColor: Qt.rgba(0, 0, 0, 0.6)
|
||||||
selectedPixmapSource: "qrc:/images/icons/icon-keypad-24-2x.png"
|
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: {
|
buttonImageHeight: buttonPreferredSize
|
||||||
callOverlayButtonGroupRect.buttonEntered()
|
buttonImageWidth: buttonPreferredSize
|
||||||
}
|
color: "white"
|
||||||
|
source: "qrc:/images/icons/ic_chat_white_24dp.png"
|
||||||
|
radius: 30
|
||||||
|
|
||||||
onVisibleChanged: {
|
onClicked: {
|
||||||
if (this.visible)
|
root.chatButtonClicked()
|
||||||
buttonCounts++
|
|
||||||
else
|
|
||||||
buttonCounts--
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HoverableButton {
|
||||||
|
id: optionsButton
|
||||||
|
|
||||||
|
Layout.preferredWidth: buttonPreferredSize * 2
|
||||||
|
Layout.preferredHeight: buttonPreferredSize * 2
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
buttonImageHeight: buttonPreferredSize
|
||||||
|
buttonImageWidth: buttonPreferredSize
|
||||||
|
source: "qrc:/images/icons/more_vert-24px.svg"
|
||||||
|
radius: 30
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item { Layout.preferredWidth: 8 }
|
||||||
}
|
}
|
||||||
|
|
||||||
color: "transparent"
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,9 +44,6 @@ Rectangle {
|
||||||
property string responsibleConvUid: ""
|
property string responsibleConvUid: ""
|
||||||
property string responsibleAccountId: ""
|
property string responsibleAccountId: ""
|
||||||
|
|
||||||
signal outgoingCallPageBackButtonIsClicked
|
|
||||||
signal callPageBackButtonIsClicked
|
|
||||||
|
|
||||||
function needToCloseInCallConversationAndPotentialWindow() {
|
function needToCloseInCallConversationAndPotentialWindow() {
|
||||||
audioCallPage.closeInCallConversation()
|
audioCallPage.closeInCallConversation()
|
||||||
videoCallPage.closeInCallConversation()
|
videoCallPage.closeInCallConversation()
|
||||||
|
@ -58,13 +55,12 @@ Rectangle {
|
||||||
audioCallPage.closeContextMenuAndRelatedWindows()
|
audioCallPage.closeContextMenuAndRelatedWindows()
|
||||||
|
|
||||||
VideoCallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer()
|
VideoCallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer()
|
||||||
videoCallPage.setCallOverlayBackButtonVisible(true)
|
|
||||||
videoCallPage.closeContextMenuAndRelatedWindows()
|
videoCallPage.closeContextMenuAndRelatedWindows()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCorrspondingMessageWebView(webViewId) {
|
function setLinkedWebview(webViewId) {
|
||||||
audioCallPage.setAudioCallPageCorrspondingMessageWebView(webViewId)
|
audioCallPage.setLinkedWebview(webViewId)
|
||||||
videoCallPage.setVideoCallPageCorrspondingMessageWebView(webViewId)
|
videoCallPage.setLinkedWebview(webViewId)
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCorrspondingUI() {
|
function updateCorrspondingUI() {
|
||||||
|
@ -172,10 +168,6 @@ Rectangle {
|
||||||
id: audioCallPage
|
id: audioCallPage
|
||||||
|
|
||||||
property int stackNumber: 0
|
property int stackNumber: 0
|
||||||
|
|
||||||
onAudioCallPageBackButtonIsClicked: {
|
|
||||||
callStackViewWindow.callPageBackButtonIsClicked()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OutgoingCallPage {
|
OutgoingCallPage {
|
||||||
|
@ -186,32 +178,24 @@ Rectangle {
|
||||||
onCallCancelButtonIsClicked: {
|
onCallCancelButtonIsClicked: {
|
||||||
CallAdapter.hangUpACall(responsibleAccountId, responsibleConvUid)
|
CallAdapter.hangUpACall(responsibleAccountId, responsibleConvUid)
|
||||||
}
|
}
|
||||||
|
|
||||||
onBackButtonIsClicked: {
|
|
||||||
callStackViewWindow.outgoingCallPageBackButtonIsClicked()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoCallPage {
|
VideoCallPage {
|
||||||
id: videoCallPage
|
id: videoCallPage
|
||||||
|
|
||||||
property int stackNumber: 2
|
property int stackNumber: 2
|
||||||
|
property bool isFullscreen: false
|
||||||
onVideoCallPageBackButtonIsClicked: {
|
|
||||||
callStackViewWindow.callPageBackButtonIsClicked()
|
|
||||||
}
|
|
||||||
|
|
||||||
onNeedToShowInFullScreen: {
|
onNeedToShowInFullScreen: {
|
||||||
|
isFullscreen = !isFullscreen
|
||||||
VideoCallFullScreenWindowContainerCreation.createvideoCallFullScreenWindowContainerObject()
|
VideoCallFullScreenWindowContainerCreation.createvideoCallFullScreenWindowContainerObject()
|
||||||
|
|
||||||
if (!VideoCallFullScreenWindowContainerCreation.checkIfVisible()) {
|
if (!VideoCallFullScreenWindowContainerCreation.checkIfVisible()) {
|
||||||
VideoCallFullScreenWindowContainerCreation.setAsContainerChild(
|
VideoCallFullScreenWindowContainerCreation.setAsContainerChild(
|
||||||
videoCallPage)
|
videoCallPage)
|
||||||
videoCallPage.setCallOverlayBackButtonVisible(false)
|
|
||||||
VideoCallFullScreenWindowContainerCreation.showVideoCallFullScreenWindowContainer()
|
VideoCallFullScreenWindowContainerCreation.showVideoCallFullScreenWindowContainer()
|
||||||
} else {
|
} else {
|
||||||
videoCallPage.parent = callStackMainView
|
videoCallPage.parent = callStackMainView
|
||||||
videoCallPage.setCallOverlayBackButtonVisible(true)
|
|
||||||
VideoCallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer()
|
VideoCallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 by Savoir-faire Linux
|
* Copyright (C) 2020 by Savoir-faire Linux
|
||||||
* Author: Mingrui Zhang <mingrui.zhang@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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,44 +18,45 @@
|
||||||
*/
|
*/
|
||||||
import QtQuick 2.14
|
import QtQuick 2.14
|
||||||
import QtQuick.Controls 2.14
|
import QtQuick.Controls 2.14
|
||||||
|
import QtGraphicalEffects 1.12
|
||||||
import net.jami.Models 1.0
|
import net.jami.Models 1.0
|
||||||
|
|
||||||
import "../../commoncomponents"
|
import "../../commoncomponents"
|
||||||
|
|
||||||
import "../js/videodevicecontextmenuitemcreation.js" as VideoDeviceContextMenuItemCreation
|
import "../js/videodevicecontextmenuitemcreation.js" as VideoDeviceContextMenuItemCreation
|
||||||
import "../js/selectscreenwindowcreation.js" as SelectScreenWindowCreation
|
import "../js/selectscreenwindowcreation.js" as SelectScreenWindowCreation
|
||||||
import "../js/screenrubberbandcreation.js" as ScreenRubberBandCreation
|
|
||||||
|
|
||||||
Menu {
|
Menu {
|
||||||
id: contextMenu
|
id: root
|
||||||
|
|
||||||
property string responsibleAccountId: ""
|
|
||||||
property string responsibleConvUid: ""
|
|
||||||
|
|
||||||
property int generalMenuSeparatorCount: 0
|
property int generalMenuSeparatorCount: 0
|
||||||
property int commonBorderWidth: 2
|
property int commonBorderWidth: 1
|
||||||
|
font.pointSize: JamiTheme.textFontSize+3
|
||||||
|
|
||||||
signal fullScreenNeeded
|
property bool isSIP: false
|
||||||
|
property bool isPaused: false
|
||||||
|
property bool isAudioOnly: false
|
||||||
|
property bool isRecording: false
|
||||||
|
|
||||||
|
signal transferCallButtonClicked
|
||||||
|
|
||||||
function activate() {
|
function activate() {
|
||||||
var deviceContextMenuInfoMap = AvAdapter.populateVideoDeviceContextMenuItem()
|
var deviceContextMenuInfoMap = AvAdapter.populateVideoDeviceContextMenuItem()
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Somehow, the map size is undefined, so use this instead.
|
* Somehow, the map size is undefined, so use this instead.
|
||||||
*/
|
*/
|
||||||
var mapSize = deviceContextMenuInfoMap["size"]
|
var mapSize = deviceContextMenuInfoMap["size"]
|
||||||
|
|
||||||
var count = 1
|
var count = 2
|
||||||
for (var deviceName in deviceContextMenuInfoMap) {
|
for (var deviceName in deviceContextMenuInfoMap) {
|
||||||
if (deviceName === "size")
|
if (deviceName === "size" || root.isAudioOnly)
|
||||||
continue
|
continue
|
||||||
if (videoDeviceItem.itemName === "No video device") {
|
if (videoDeviceItem.itemName === "No video device") {
|
||||||
videoDeviceItem.checkable = true
|
videoDeviceItem.checkable = true
|
||||||
videoDeviceItem.itemName = deviceName
|
videoDeviceItem.itemName = deviceName
|
||||||
videoDeviceItem.checked = deviceContextMenuInfoMap[deviceName]
|
videoDeviceItem.checked = deviceContextMenuInfoMap[deviceName]
|
||||||
if (count === mapSize)
|
if (count === mapSize)
|
||||||
contextMenu.open()
|
root.open()
|
||||||
} else {
|
} else {
|
||||||
VideoDeviceContextMenuItemCreation.createVideoDeviceContextMenuItemObjects(
|
VideoDeviceContextMenuItemCreation.createVideoDeviceContextMenuItemObjects(
|
||||||
deviceName, deviceContextMenuInfoMap[deviceName],
|
deviceName, deviceContextMenuInfoMap[deviceName],
|
||||||
|
@ -63,14 +64,18 @@ Menu {
|
||||||
}
|
}
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
|
root.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
function closePotentialWindows() {
|
Component.onCompleted: {
|
||||||
SelectScreenWindowCreation.destorySelectScreenWindow()
|
VideoDeviceContextMenuItemCreation.setVideoContextMenuObject(root)
|
||||||
ScreenRubberBandCreation.destoryScreenRubberBandWindow()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
implicitWidth: 200
|
|
||||||
|
onClosed: {
|
||||||
|
videoDeviceItem.itemName = "No video device"
|
||||||
|
VideoDeviceContextMenuItemCreation.removeCreatedItems()
|
||||||
|
}
|
||||||
|
|
||||||
JamiFileDialog {
|
JamiFileDialog {
|
||||||
id: jamiFileDialog
|
id: jamiFileDialog
|
||||||
|
@ -78,32 +83,112 @@ Menu {
|
||||||
mode: JamiFileDialog.Mode.OpenFile
|
mode: JamiFileDialog.Mode.OpenFile
|
||||||
|
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
var filePath = jamiFileDialog.file
|
// No need to trim file:///.
|
||||||
|
AvAdapter.shareFile(jamiFileDialog.file)
|
||||||
|
|
||||||
/*
|
|
||||||
* No need to trim file:///.
|
|
||||||
*/
|
|
||||||
AvAdapter.shareFile(filePath)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All GeneralMenuItems should remain the same width / height.
|
* All GeneralMenuItems should remain the same width / height.
|
||||||
* The first videoDeviceItem is to make sure the border is correct.
|
|
||||||
*/
|
*/
|
||||||
VideoCallPageContextMenuDeviceItem {
|
GeneralMenuItem {
|
||||||
id: videoDeviceItem
|
id: holdCallButton
|
||||||
|
|
||||||
topBorderWidth: commonBorderWidth
|
visible: isSIP
|
||||||
contextMenuPreferredWidth: contextMenu.implicitWidth
|
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 {
|
GeneralMenuSeparator {
|
||||||
preferredWidth: videoDeviceItem.preferredWidth
|
preferredWidth: startRecordingItem.preferredWidth
|
||||||
preferredHeight: commonBorderWidth
|
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
|
||||||
|
|
||||||
|
contextMenuPreferredWidth: root.implicitWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
GeneralMenuSeparator {
|
||||||
|
preferredWidth: startRecordingItem.preferredWidth
|
||||||
|
preferredHeight: commonBorderWidth
|
||||||
|
visible: !isAudioOnly
|
||||||
|
height: !isAudioOnly? undefined : 0
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
generalMenuSeparatorCount++
|
generalMenuSeparatorCount++
|
||||||
}
|
}
|
||||||
|
@ -113,11 +198,14 @@ Menu {
|
||||||
id: shareEntireScreenItem
|
id: shareEntireScreenItem
|
||||||
|
|
||||||
itemName: qsTr("Share entire screen")
|
itemName: qsTr("Share entire screen")
|
||||||
|
iconSource: "qrc:/images/icons/screen_share-24px.svg"
|
||||||
leftBorderWidth: commonBorderWidth
|
leftBorderWidth: commonBorderWidth
|
||||||
rightBorderWidth: commonBorderWidth
|
rightBorderWidth: commonBorderWidth
|
||||||
|
visible: !isAudioOnly
|
||||||
|
height: !isAudioOnly? undefined : 0
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
contextMenu.close()
|
root.close()
|
||||||
if (Qt.application.screens.length === 1) {
|
if (Qt.application.screens.length === 1) {
|
||||||
AvAdapter.shareEntireScreen(0)
|
AvAdapter.shareEntireScreen(0)
|
||||||
} else {
|
} else {
|
||||||
|
@ -131,11 +219,14 @@ Menu {
|
||||||
id: shareScreenAreaItem
|
id: shareScreenAreaItem
|
||||||
|
|
||||||
itemName: qsTr("Share screen area")
|
itemName: qsTr("Share screen area")
|
||||||
|
iconSource: "qrc:/images/icons/screen_share-24px.svg"
|
||||||
leftBorderWidth: commonBorderWidth
|
leftBorderWidth: commonBorderWidth
|
||||||
rightBorderWidth: commonBorderWidth
|
rightBorderWidth: commonBorderWidth
|
||||||
|
visible: !isAudioOnly
|
||||||
|
height: !isAudioOnly? undefined : 0
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
contextMenu.close()
|
root.close()
|
||||||
if (Qt.application.screens.length === 1) {
|
if (Qt.application.screens.length === 1) {
|
||||||
ScreenRubberBandCreation.createScreenRubberBandWindowObject(
|
ScreenRubberBandCreation.createScreenRubberBandWindowObject(
|
||||||
null, 0)
|
null, 0)
|
||||||
|
@ -151,59 +242,56 @@ Menu {
|
||||||
id: shareFileItem
|
id: shareFileItem
|
||||||
|
|
||||||
itemName: qsTr("Share file")
|
itemName: qsTr("Share file")
|
||||||
|
iconSource: "qrc:/images/icons/insert_photo-24px.svg"
|
||||||
leftBorderWidth: commonBorderWidth
|
leftBorderWidth: commonBorderWidth
|
||||||
rightBorderWidth: commonBorderWidth
|
rightBorderWidth: commonBorderWidth
|
||||||
|
visible: !isAudioOnly
|
||||||
|
height: !isAudioOnly? undefined : 0
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
contextMenu.close()
|
root.close()
|
||||||
jamiFileDialog.open()
|
jamiFileDialog.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GeneralMenuSeparator {
|
/* TODO: In the future we want to implement this
|
||||||
preferredWidth: videoDeviceItem.preferredWidth
|
|
||||||
preferredHeight: commonBorderWidth
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
GeneralMenuItem {
|
||||||
generalMenuSeparatorCount++
|
id: advancedInfosItem
|
||||||
|
|
||||||
|
itemName: qsTr("Advanced informations")
|
||||||
|
iconSource: "qrc:/images/icons/info-24px.svg"
|
||||||
|
leftBorderWidth: commonBorderWidth
|
||||||
|
rightBorderWidth: commonBorderWidth
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
root.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GeneralMenuItem {
|
GeneralMenuItem {
|
||||||
id: fullScreenItem
|
id: pluginItem
|
||||||
|
|
||||||
property bool isFullScreen: false
|
itemName: qsTr("Toggle plugin")
|
||||||
|
iconSource: "qrc:/images/icons/extension_24dp.svg"
|
||||||
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"
|
|
||||||
leftBorderWidth: commonBorderWidth
|
leftBorderWidth: commonBorderWidth
|
||||||
rightBorderWidth: commonBorderWidth
|
rightBorderWidth: commonBorderWidth
|
||||||
bottomBorderWidth: commonBorderWidth
|
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
contextMenu.close()
|
root.close()
|
||||||
contextMenu.fullScreenNeeded()
|
|
||||||
isFullScreen = !isFullScreen
|
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
onClosed: {
|
|
||||||
videoDeviceItem.itemName = "No video device"
|
|
||||||
VideoDeviceContextMenuItemCreation.removeCreatedItems()
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
VideoDeviceContextMenuItemCreation.setVideoContextMenuObject(
|
|
||||||
contextMenu)
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
implicitWidth: contextMenu.implicitWidth
|
implicitWidth: startRecordingItem.preferredWidth
|
||||||
implicitHeight: videoDeviceItem.preferredHeight
|
implicitHeight: startRecordingItem.preferredHeight
|
||||||
* (contextMenu.count - generalMenuSeparatorCount)
|
* (root.count
|
||||||
|
- (isSIP? 0 : 2)
|
||||||
|
- (isAudioOnly? 6 : 0)
|
||||||
|
- generalMenuSeparatorCount)
|
||||||
|
|
||||||
border.width: commonBorderWidth
|
border.width: commonBorderWidth
|
||||||
border.color: JamiTheme.tabbarBorderColor
|
border.color: JamiTheme.tabbarBorderColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@ Rectangle {
|
||||||
property string bestId: "Best Id"
|
property string bestId: "Best Id"
|
||||||
|
|
||||||
signal callCancelButtonIsClicked
|
signal callCancelButtonIsClicked
|
||||||
signal backButtonIsClicked
|
|
||||||
|
|
||||||
function updateUI(accountId, convUid) {
|
function updateUI(accountId, convUid) {
|
||||||
contactImgSource = "data:image/png;base64," + ClientWrapper.utilsAdaptor.getContactImageString(
|
contactImgSource = "data:image/png;base64," + ClientWrapper.utilsAdaptor.getContactImageString(
|
||||||
|
@ -58,26 +57,6 @@ Rectangle {
|
||||||
acceptedButtons: Qt.RightButton
|
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 {
|
ColumnLayout {
|
||||||
id: outgoingCallPageRectColumnLayout
|
id: outgoingCallPageRectColumnLayout
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 by Savoir-faire Linux
|
* Copyright (C) 2020 by Savoir-faire Linux
|
||||||
* Author: Mingrui Zhang <mingrui.zhang@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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -32,12 +33,12 @@ Rectangle {
|
||||||
property string bestId: "Best Id"
|
property string bestId: "Best Id"
|
||||||
property variant clickPos: "1,1"
|
property variant clickPos: "1,1"
|
||||||
property int previewMargin: 15
|
property int previewMargin: 15
|
||||||
|
property int previewMarginY: previewMargin + 56
|
||||||
property int previewToX: 0
|
property int previewToX: 0
|
||||||
property int previewToY: 0
|
property int previewToY: 0
|
||||||
|
|
||||||
property var corrspondingMessageWebView: null
|
property var linkedWebview: null
|
||||||
|
|
||||||
signal videoCallPageBackButtonIsClicked
|
|
||||||
signal needToShowInFullScreen
|
signal needToShowInFullScreen
|
||||||
|
|
||||||
function updateUI(accountId, convUid) {
|
function updateUI(accountId, convUid) {
|
||||||
|
@ -51,27 +52,25 @@ Rectangle {
|
||||||
distantRenderer.setRendererId(id)
|
distantRenderer.setRendererId(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setVideoCallPageCorrspondingMessageWebView(webViewId) {
|
function setLinkedWebview(webViewId) {
|
||||||
corrspondingMessageWebView = webViewId
|
linkedWebview = webViewId
|
||||||
corrspondingMessageWebView.needToHideConversationInCall.disconnect(
|
linkedWebview.needToHideConversationInCall.disconnect(
|
||||||
closeInCallConversation)
|
closeInCallConversation)
|
||||||
corrspondingMessageWebView.needToHideConversationInCall.connect(
|
linkedWebview.needToHideConversationInCall.connect(
|
||||||
closeInCallConversation)
|
closeInCallConversation)
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeInCallConversation() {
|
function closeInCallConversation() {
|
||||||
if (inVideoCallMessageWebViewStack.visible) {
|
if (inVideoCallMessageWebViewStack.visible) {
|
||||||
corrspondingMessageWebView.resetMessagingHeaderBackButtonSource(
|
linkedWebview.resetMessagingHeaderBackButtonSource(
|
||||||
true)
|
true)
|
||||||
corrspondingMessageWebView.setMessagingHeaderButtonsVisible(true)
|
linkedWebview.setMessagingHeaderButtonsVisible(true)
|
||||||
inVideoCallMessageWebViewStack.visible = false
|
inVideoCallMessageWebViewStack.visible = false
|
||||||
inVideoCallMessageWebViewStack.clear()
|
inVideoCallMessageWebViewStack.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeContextMenuAndRelatedWindows() {
|
function closeContextMenuAndRelatedWindows() {
|
||||||
videoCallPageContextMenu.closePotentialWindows()
|
|
||||||
videoCallPageContextMenu.close()
|
|
||||||
videoCallOverlay.closePotentialContactPicker()
|
videoCallOverlay.closePotentialContactPicker()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +98,7 @@ Rectangle {
|
||||||
return videoCallPageMainRect.width - previewRenderer.width - previewMargin
|
return videoCallPageMainRect.width - previewRenderer.width - previewMargin
|
||||||
})
|
})
|
||||||
previewToY = Qt.binding(function () {
|
previewToY = Qt.binding(function () {
|
||||||
return videoCallPageMainRect.height - previewRenderer.height - previewMargin
|
return videoCallPageMainRect.height - previewRenderer.height - previewMarginY
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -110,7 +109,7 @@ Rectangle {
|
||||||
previewToX = Qt.binding(function () {
|
previewToX = Qt.binding(function () {
|
||||||
return videoCallPageMainRect.width - previewRenderer.width - previewMargin
|
return videoCallPageMainRect.width - previewRenderer.width - previewMargin
|
||||||
})
|
})
|
||||||
previewToY = previewMargin
|
previewToY = previewMarginY
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (previewRendererCenter.y >= distantRendererCenter.y) {
|
if (previewRendererCenter.y >= distantRendererCenter.y) {
|
||||||
|
@ -121,7 +120,7 @@ Rectangle {
|
||||||
*/
|
*/
|
||||||
previewToX = previewMargin
|
previewToX = previewMargin
|
||||||
previewToY = Qt.binding(function () {
|
previewToY = Qt.binding(function () {
|
||||||
return videoCallPageMainRect.height - previewRenderer.height - previewMargin
|
return videoCallPageMainRect.height - previewRenderer.height - previewMarginY
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -130,16 +129,12 @@ Rectangle {
|
||||||
* Top left.
|
* Top left.
|
||||||
*/
|
*/
|
||||||
previewToX = previewMargin
|
previewToX = previewMargin
|
||||||
previewToY = previewMargin
|
previewToY = previewMarginY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
previewRenderer.state = "geoChanging"
|
previewRenderer.state = "geoChanging"
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCallOverlayBackButtonVisible(visible) {
|
|
||||||
videoCallOverlay.setBackTintedButtonVisible(visible)
|
|
||||||
}
|
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
SplitView {
|
SplitView {
|
||||||
|
@ -155,182 +150,182 @@ Rectangle {
|
||||||
color: SplitHandle.pressed ? JamiTheme.pressColor : (SplitHandle.hovered ? JamiTheme.hoverColor : JamiTheme.tabbarBorderColor)
|
color: SplitHandle.pressed ? JamiTheme.pressColor : (SplitHandle.hovered ? JamiTheme.hoverColor : JamiTheme.tabbarBorderColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: videoCallPageMainRect
|
id: videoCallPageMainRect
|
||||||
|
|
||||||
SplitView.preferredHeight: (videoCallPageRect.height / 3) * 2
|
SplitView.preferredHeight: (videoCallPageRect.height / 3) * 2
|
||||||
SplitView.minimumHeight: videoCallPageRect.height / 2 + 20
|
SplitView.minimumHeight: videoCallPageRect.height / 2 + 20
|
||||||
SplitView.fillWidth: true
|
SplitView.fillWidth: true
|
||||||
|
|
||||||
CallOverlay {
|
MouseArea {
|
||||||
id: videoCallOverlay
|
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
propagateComposedEvents: true
|
||||||
|
|
||||||
Connections {
|
acceptedButtons: Qt.LeftButton
|
||||||
target: CallAdapter
|
|
||||||
|
|
||||||
function onUpdateTimeText(time) {
|
onDoubleClicked: {
|
||||||
videoCallOverlay.timeText = time
|
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
|
|
||||||
}
|
|
||||||
|
|
||||||
function onShowOnHoldLabel(isPaused) {
|
|
||||||
videoCallOverlay.showOnHoldImage(isPaused)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onBackButtonIsClicked: {
|
CallOverlay {
|
||||||
if (inVideoCallMessageWebViewStack.visible) {
|
id: videoCallOverlay
|
||||||
corrspondingMessageWebView.resetMessagingHeaderBackButtonSource(
|
|
||||||
true)
|
|
||||||
corrspondingMessageWebView.setMessagingHeaderButtonsVisible(
|
|
||||||
true)
|
|
||||||
inVideoCallMessageWebViewStack.visible = false
|
|
||||||
inVideoCallMessageWebViewStack.clear()
|
|
||||||
}
|
|
||||||
videoCallPageRect.videoCallPageBackButtonIsClicked()
|
|
||||||
}
|
|
||||||
|
|
||||||
onOverlayChatButtonClicked: {
|
anchors.fill: parent
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DistantRenderer {
|
Connections {
|
||||||
id: distantRenderer
|
target: CallAdapter
|
||||||
|
|
||||||
anchors.centerIn: videoCallPageMainRect
|
function onUpdateTimeText(time) {
|
||||||
z: -1
|
videoCallOverlay.timeText = time
|
||||||
|
videoCallOverlay.setRecording(CallAdapter.isRecordingThisCall())
|
||||||
|
}
|
||||||
|
|
||||||
width: videoCallPageMainRect.width
|
function onUpdateOverlay(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall, bestName) {
|
||||||
height: videoCallPageMainRect.height
|
videoCallOverlay.showOnHoldImage(isPaused)
|
||||||
}
|
videoCallOverlay.updateButtonStatus(isPaused,
|
||||||
|
isAudioOnly,
|
||||||
|
isAudioMuted,
|
||||||
|
isVideoMuted,
|
||||||
|
isRecording, isSIP,
|
||||||
|
isConferenceCall)
|
||||||
|
videoCallPageRect.bestName = bestName
|
||||||
|
}
|
||||||
|
|
||||||
VideoCallPreviewRenderer {
|
function onShowOnHoldLabel(isPaused) {
|
||||||
id: previewRenderer
|
videoCallOverlay.showOnHoldImage(isPaused)
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
|
|
||||||
function onPreviewVisibilityNeedToChange(visible) {
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
|
||||||
|
|
||||||
transitions: Transition {
|
onOverlayChatButtonClicked: {
|
||||||
PropertyAnimation {
|
if (inVideoCallMessageWebViewStack.visible) {
|
||||||
properties: "x,y"
|
linkedWebview.resetMessagingHeaderBackButtonSource(
|
||||||
easing.type: Easing.OutExpo
|
true)
|
||||||
duration: 250
|
linkedWebview.setMessagingHeaderButtonsVisible(
|
||||||
|
true)
|
||||||
|
inVideoCallMessageWebViewStack.visible = false
|
||||||
|
inVideoCallMessageWebViewStack.clear()
|
||||||
|
} else {
|
||||||
|
linkedWebview.resetMessagingHeaderBackButtonSource(
|
||||||
|
false)
|
||||||
|
linkedWebview.setMessagingHeaderButtonsVisible(
|
||||||
|
false)
|
||||||
|
inVideoCallMessageWebViewStack.visible = true
|
||||||
|
inVideoCallMessageWebViewStack.push(
|
||||||
|
linkedWebview)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onStopped: {
|
DistantRenderer {
|
||||||
|
id: distantRenderer
|
||||||
|
|
||||||
|
anchors.centerIn: videoCallPageMainRect
|
||||||
|
z: -1
|
||||||
|
|
||||||
|
width: videoCallPageMainRect.width
|
||||||
|
height: videoCallPageMainRect.height
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: CallAdapter
|
||||||
|
|
||||||
|
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 - 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
|
||||||
|
|
||||||
|
onStopped: {
|
||||||
|
previewRenderer.state = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: dragMouseArea
|
||||||
|
|
||||||
|
anchors.fill: previewRenderer
|
||||||
|
|
||||||
|
onPressed: {
|
||||||
|
clickPos = Qt.point(mouse.x, mouse.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
onReleased: {
|
||||||
previewRenderer.state = ""
|
previewRenderer.state = ""
|
||||||
|
previewMagneticSnap()
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
onPreviewImageAvailable: {
|
||||||
id: dragMouseArea
|
previewImageScalingFactorUpdated++
|
||||||
|
previewImageScalingFactorUpdated--
|
||||||
anchors.fill: previewRenderer
|
|
||||||
|
|
||||||
onPressed: {
|
|
||||||
clickPos = Qt.point(mouse.x, mouse.y)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onReleased: {
|
|
||||||
previewRenderer.state = ""
|
|
||||||
previewMagneticSnap()
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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--
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StackView {
|
StackView {
|
||||||
id: inVideoCallMessageWebViewStack
|
id: inVideoCallMessageWebViewStack
|
||||||
|
|
||||||
|
@ -343,32 +338,8 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoCallPageContextMenu {
|
onBestNameChanged: {
|
||||||
id: videoCallPageContextMenu
|
ContactAdapter.setCalleeDisplayName(bestName)
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
color: "black"
|
color: "black"
|
||||||
|
|
|
@ -31,60 +31,26 @@ GeneralMenuItem {
|
||||||
|
|
||||||
property int contextMenuPreferredWidth: 250
|
property int contextMenuPreferredWidth: 250
|
||||||
|
|
||||||
itemName: qsTr("No video device")
|
|
||||||
leftBorderWidth: commonBorderWidth
|
leftBorderWidth: commonBorderWidth
|
||||||
rightBorderWidth: commonBorderWidth
|
rightBorderWidth: commonBorderWidth
|
||||||
|
|
||||||
TextMetrics {
|
TextMetrics {
|
||||||
id: textMetrics
|
id: textMetrics
|
||||||
font: deviceNameText.font
|
|
||||||
elide: Text.ElideMiddle
|
elide: Text.ElideMiddle
|
||||||
elideWidth: contextMenuPreferredWidth
|
elideWidth: contextMenuPreferredWidth
|
||||||
- videoCallPageContextMenuDeviceItem.implicitIndicatorWidth
|
- videoCallPageContextMenuDeviceItem.implicitIndicatorWidth
|
||||||
text: videoCallPageContextMenuDeviceItem.itemName
|
text: videoCallPageContextMenuDeviceItem.itemName
|
||||||
}
|
}
|
||||||
|
|
||||||
contentItem: Text {
|
itemName: textMetrics.elidedText.length !== 0 ?
|
||||||
id: deviceNameText
|
textMetrics.elidedText :
|
||||||
|
qsTr("No video device")
|
||||||
|
|
||||||
leftPadding: 30
|
indicator: null
|
||||||
rightPadding: videoCallPageContextMenuDeviceItem.arrow.width
|
|
||||||
|
|
||||||
horizontalAlignment: Text.AlignLeft
|
iconSource: videoCallPageContextMenuDeviceItem.checked ?
|
||||||
verticalAlignment: Text.AlignVCenter
|
"qrc:/images/icons/check_box-24px.svg" :
|
||||||
|
"qrc:/images/icons/check_box_outline_blank-24px.svg"
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var deviceName = videoCallPageContextMenuDeviceItem.itemName
|
var deviceName = videoCallPageContextMenuDeviceItem.itemName
|
||||||
|
|
|
@ -54,11 +54,7 @@ function createVideoDeviceContextMenuItemObjects(deviceName, setChecked, last) {
|
||||||
function finishCreation(deviceName, setChecked, last) {
|
function finishCreation(deviceName, setChecked, last) {
|
||||||
videoDeviceContextMenuItemObject = videoDeviceContextMenuItemComponent.createObject()
|
videoDeviceContextMenuItemObject = videoDeviceContextMenuItemComponent.createObject()
|
||||||
if (videoDeviceContextMenuItemObject === null) {
|
if (videoDeviceContextMenuItemObject === null) {
|
||||||
|
// Error Handling.
|
||||||
|
|
||||||
/*
|
|
||||||
* Error Handling.
|
|
||||||
*/
|
|
||||||
console.log("Error creating video context menu object")
|
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.
|
* Push into the storage array, and insert it into context menu.
|
||||||
*/
|
*/
|
||||||
itemArray.push(videoDeviceContextMenuItemObject)
|
itemArray.push(videoDeviceContextMenuItemObject)
|
||||||
videoContextMenuObject.insertItem(1, videoDeviceContextMenuItemObject)
|
videoContextMenuObject.insertItem(3 /* The button is at pos 3 in the menu */, videoDeviceContextMenuItemObject)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|