blob: 7a6b3f1e1a4eb5da209807349c45f02d5f2571c7 [file] [log] [blame]
Sébastien Blin1f915762020-08-03 13:27:42 -04001
2/*
3 * Copyright (C) 2020 by Savoir-faire Linux
4 * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
Sébastien Blin8940f3c2020-07-23 17:03:11 -04005 * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
Sébastien Blin1f915762020-08-03 13:27:42 -04006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20import QtQuick 2.14
21import QtQuick.Controls 2.14
22import QtQuick.Layouts 1.14
23import QtQuick.Controls.Universal 2.12
24import QtQml 2.14
25import net.jami.Models 1.0
26
27import "../js/contactpickercreation.js" as ContactPickerCreation
28
29import "../../commoncomponents"
30
31Rectangle {
32 id: callOverlayRect
33
Sébastien Blin1f915762020-08-03 13:27:42 -040034 property string timeText: "00:00"
35
Sébastien Blin1f915762020-08-03 13:27:42 -040036 signal overlayChatButtonClicked
37
Sébastien Blin8940f3c2020-07-23 17:03:11 -040038 function setRecording(isRecording) {
39 callViewContextMenu.isRecording = isRecording
40 recordingRect.visible = isRecording
41 }
42
Sébastien Blin1f915762020-08-03 13:27:42 -040043 function updateButtonStatus(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall) {
Sébastien Blin8940f3c2020-07-23 17:03:11 -040044 callViewContextMenu.isSIP = isSIP
45 callViewContextMenu.isPaused = isPaused
46 callViewContextMenu.isAudioOnly = isAudioOnly
47 callViewContextMenu.isRecording = isRecording
48 recordingRect.visible = isRecording
Sébastien Blin1f915762020-08-03 13:27:42 -040049 callOverlayButtonGroup.setButtonStatus(isPaused, isAudioOnly,
50 isAudioMuted, isVideoMuted,
51 isRecording, isSIP,
52 isConferenceCall)
53 }
54
55 function showOnHoldImage(visible) {
56 onHoldImage.visible = visible
57 }
58
59 function closePotentialContactPicker() {
60 ContactPickerCreation.closeContactPicker()
61 }
62
Sébastien Blin1f915762020-08-03 13:27:42 -040063 anchors.fill: parent
64
65
66 /*
67 * Timer to decide when overlay fade out.
68 */
69 Timer {
70 id: callOverlayTimer
71 interval: 5000
72 onTriggered: {
73 if (overlayUpperPartRect.state !== 'freezed') {
74 overlayUpperPartRect.state = 'freezed'
75 }
76 if (callOverlayButtonGroup.state !== 'freezed') {
77 callOverlayButtonGroup.state = 'freezed'
78 }
79 }
80 }
81
82 Rectangle {
83 id: overlayUpperPartRect
84
85 anchors.top: callOverlayRect.top
86
87 width: callOverlayRect.width
88 height: 50
89 opacity: 0
90
91 RowLayout {
92 id: overlayUpperPartRectRowLayout
93
94 anchors.fill: parent
95
Sébastien Blin1f915762020-08-03 13:27:42 -040096 Text {
97 id: jamiBestNameText
98
99 Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
100 Layout.preferredWidth: overlayUpperPartRect.width / 3
101 Layout.preferredHeight: 50
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400102 leftPadding: 16
Sébastien Blin1f915762020-08-03 13:27:42 -0400103
104 font.pointSize: JamiTheme.textFontSize
105
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400106 horizontalAlignment: Text.AlignLeft
Sébastien Blin1f915762020-08-03 13:27:42 -0400107 verticalAlignment: Text.AlignVCenter
108
109 text: textMetricsjamiBestNameText.elidedText
110 color: "white"
111
112 TextMetrics {
113 id: textMetricsjamiBestNameText
114 font: jamiBestNameText.font
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400115 text: videoCallPageRect.bestName
Sébastien Blin1f915762020-08-03 13:27:42 -0400116 elideWidth: overlayUpperPartRect.width / 3
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400117 elide: Qt.ElideRight
Sébastien Blin1f915762020-08-03 13:27:42 -0400118 }
119 }
120
121 Text {
122 id: callTimerText
Sébastien Blin1f915762020-08-03 13:27:42 -0400123 Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
124 Layout.preferredWidth: overlayUpperPartRect.width / 3
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400125 Layout.preferredHeight: 48
Sébastien Blin1f915762020-08-03 13:27:42 -0400126 font.pointSize: JamiTheme.textFontSize
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400127 horizontalAlignment: Text.AlignRight
Sébastien Blin1f915762020-08-03 13:27:42 -0400128 verticalAlignment: Text.AlignVCenter
Sébastien Blin1f915762020-08-03 13:27:42 -0400129 text: textMetricscallTimerText.elidedText
130 color: "white"
Sébastien Blin1f915762020-08-03 13:27:42 -0400131 TextMetrics {
132 id: textMetricscallTimerText
133 font: callTimerText.font
134 text: timeText
135 elideWidth: overlayUpperPartRect.width / 3
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400136 elide: Qt.ElideRight
Sébastien Blin1f915762020-08-03 13:27:42 -0400137 }
138 }
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400139
140 Rectangle {
141 id: recordingRect
142 Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
143 height: 16
144 width: 16
145 radius: height / 2
146 color: "red"
147
148 SequentialAnimation on color {
149 loops: Animation.Infinite
150 running: true
151 ColorAnimation { from: "red"; to: "transparent"; duration: 500 }
152 ColorAnimation { from: "transparent"; to: "red"; duration: 500 }
153 }
154 }
155
156 Item {
157 width: 8
158 }
Sébastien Blin1f915762020-08-03 13:27:42 -0400159 }
160
161 color: "transparent"
162
163
164 /*
165 * Rect states: "entered" state should make overlay fade in,
166 * "freezed" state should make overlay fade out.
167 * Combine with PropertyAnimation of opacity.
168 */
169 states: [
170 State {
171 name: "entered"
172 PropertyChanges {
173 target: overlayUpperPartRect
174 opacity: 1
175 }
176 },
177 State {
178 name: "freezed"
179 PropertyChanges {
180 target: overlayUpperPartRect
181 opacity: 0
182 }
183 }
184 ]
185
186 transitions: Transition {
187 PropertyAnimation {
188 target: overlayUpperPartRect
189 property: "opacity"
190 duration: 1000
191 }
192 }
193 }
194
195 Image {
196 id: onHoldImage
197
198 anchors.verticalCenter: callOverlayRect.verticalCenter
199 anchors.horizontalCenter: callOverlayRect.horizontalCenter
200
201 width: 200
202 height: 200
203
204 visible: false
205
206 fillMode: Image.PreserveAspectFit
207 source: "qrc:/images/icons/ic_pause_white_100px.png"
208 asynchronous: true
209 }
210
211 CallOverlayButtonGroup {
212 id: callOverlayButtonGroup
213
214 anchors.bottom: callOverlayRect.bottom
215 anchors.bottomMargin: 10
216 anchors.horizontalCenter: callOverlayRect.horizontalCenter
217
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400218 height: 56
219 width: callOverlayRect.width
Sébastien Blin1f915762020-08-03 13:27:42 -0400220 opacity: 0
221
222 onChatButtonClicked: {
223 callOverlayRect.overlayChatButtonClicked()
224 }
225
226 onAddToConferenceButtonClicked: {
Sébastien Blin1f915762020-08-03 13:27:42 -0400227 /*
228 * Create contact picker - conference.
229 */
230 ContactPickerCreation.createContactPickerObjects(
231 ContactPicker.ContactPickerType.JAMICONFERENCE,
232 callOverlayRect)
233 ContactPickerCreation.calculateCurrentGeo(
234 callOverlayRect.width / 2, callOverlayRect.height / 2)
235 ContactPickerCreation.openContactPicker()
236 }
237
Sébastien Blin1f915762020-08-03 13:27:42 -0400238 states: [
239 State {
240 name: "entered"
241 PropertyChanges {
242 target: callOverlayButtonGroup
243 opacity: 1
244 }
245 },
246 State {
247 name: "freezed"
248 PropertyChanges {
249 target: callOverlayButtonGroup
250 opacity: 0
251 }
252 }
253 ]
254
255 transitions: Transition {
256 PropertyAnimation {
257 target: callOverlayButtonGroup
258 property: "opacity"
259 duration: 1000
260 }
261 }
262 }
263
264
265 /*
266 * MouseAreas to make sure that overlay states are correctly set.
267 */
268 MouseArea {
269 id: callOverlayButtonGroupLeftSideMouseArea
270
271 anchors.bottom: callOverlayRect.bottom
272 anchors.left: callOverlayRect.left
273
274 width: callOverlayRect.width / 6
275 height: 60
276
277 hoverEnabled: true
278 propagateComposedEvents: true
279 acceptedButtons: Qt.NoButton
280
281 onEntered: {
282 callOverlayRectMouseArea.entered()
283 }
284
285 onMouseXChanged: {
286 callOverlayRectMouseArea.entered()
287 }
288 }
289
290 MouseArea {
291 id: callOverlayButtonGroupRightSideMouseArea
292
293 anchors.bottom: callOverlayRect.bottom
294 anchors.right: callOverlayRect.right
295
296 width: callOverlayRect.width / 6
297 height: 60
298
299 hoverEnabled: true
300 propagateComposedEvents: true
301 acceptedButtons: Qt.NoButton
302
303 onEntered: {
304 callOverlayRectMouseArea.entered()
305 }
306
307 onMouseXChanged: {
308 callOverlayRectMouseArea.entered()
309 }
310 }
311
312 MouseArea {
313 id: callOverlayRectMouseArea
314
315 anchors.top: callOverlayRect.top
316 anchors.topMargin: 50
317
318 width: callOverlayRect.width
319 height: callOverlayRect.height - callOverlayButtonGroup.height - 50
320
321 hoverEnabled: true
322 propagateComposedEvents: true
323 acceptedButtons: Qt.NoButton
324
325 onEntered: {
326 if (overlayUpperPartRect.state !== 'entered') {
327 overlayUpperPartRect.state = 'entered'
328 }
329 if (callOverlayButtonGroup.state !== 'entered') {
330 callOverlayButtonGroup.state = 'entered'
331 }
332 callOverlayTimer.restart()
333 }
334
335 onMouseXChanged: {
336 if (overlayUpperPartRect.state !== 'entered') {
337 overlayUpperPartRect.state = 'entered'
338 }
339 if (callOverlayButtonGroup.state !== 'entered') {
340 callOverlayButtonGroup.state = 'entered'
341 }
342 callOverlayTimer.restart()
343 }
344 }
345
346 color: "transparent"
347
Sébastien Blin1f915762020-08-03 13:27:42 -0400348 onWidthChanged: {
349 ContactPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2,
350 callOverlayRect.height / 2)
351 }
352
353 onHeightChanged: {
354 ContactPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2,
355 callOverlayRect.height / 2)
356 }
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400357
358 CallViewContextMenu {
359 id: callViewContextMenu
360
361 onTransferCallButtonClicked: {
362 /*
363 * Create contact picker - sip transfer.
364 */
365 ContactPickerCreation.createContactPickerObjects(
366 ContactPicker.ContactPickerType.SIPTRANSFER,
367 callOverlayRect)
368 ContactPickerCreation.calculateCurrentGeo(
369 callOverlayRect.width / 2, callOverlayRect.height / 2)
370 ContactPickerCreation.openContactPicker()
371 }
372 }
Sébastien Blin1f915762020-08-03 13:27:42 -0400373}