blob: 105f7c8d482e25753bb1655ed8d1b9853a72d3a5 [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 QtGraphicalEffects 1.14
25import net.jami.Models 1.0
26
27import "../../commoncomponents"
28
29Rectangle {
30 id: videoCallPageRect
31
32 property string bestName: "Best Name"
33 property string bestId: "Best Id"
34 property variant clickPos: "1,1"
35 property int previewMargin: 15
Sébastien Blin8940f3c2020-07-23 17:03:11 -040036 property int previewMarginY: previewMargin + 56
Sébastien Blin1f915762020-08-03 13:27:42 -040037 property int previewToX: 0
38 property int previewToY: 0
39
Sébastien Blin8940f3c2020-07-23 17:03:11 -040040 property var linkedWebview: null
Sébastien Blin1f915762020-08-03 13:27:42 -040041
Sébastien Blin1f915762020-08-03 13:27:42 -040042 signal needToShowInFullScreen
43
44 function updateUI(accountId, convUid) {
Sébastien Blin6607e0e2020-07-24 15:15:47 -040045 videoCallOverlay.handleParticipantsInfo(CallAdapter.getConferencesInfos())
46
Sébastien Blin1f915762020-08-03 13:27:42 -040047 bestName = ClientWrapper.utilsAdaptor.getBestName(accountId, convUid)
48
49 var id = ClientWrapper.utilsAdaptor.getBestId(accountId, convUid)
50 bestId = (bestName !== id) ? id : ""
51 }
52
53 function setDistantRendererId(id) {
54 distantRenderer.setRendererId(id)
55 }
56
Sébastien Blin8940f3c2020-07-23 17:03:11 -040057 function setLinkedWebview(webViewId) {
58 linkedWebview = webViewId
59 linkedWebview.needToHideConversationInCall.disconnect(
Sébastien Blin1f915762020-08-03 13:27:42 -040060 closeInCallConversation)
Sébastien Blin8940f3c2020-07-23 17:03:11 -040061 linkedWebview.needToHideConversationInCall.connect(
Sébastien Blin1f915762020-08-03 13:27:42 -040062 closeInCallConversation)
63 }
64
65 function closeInCallConversation() {
66 if (inVideoCallMessageWebViewStack.visible) {
Sébastien Blin8940f3c2020-07-23 17:03:11 -040067 linkedWebview.resetMessagingHeaderBackButtonSource(
Sébastien Blin1f915762020-08-03 13:27:42 -040068 true)
Sébastien Blin8940f3c2020-07-23 17:03:11 -040069 linkedWebview.setMessagingHeaderButtonsVisible(true)
Sébastien Blin1f915762020-08-03 13:27:42 -040070 inVideoCallMessageWebViewStack.visible = false
71 inVideoCallMessageWebViewStack.clear()
72 }
73 }
74
75 function closeContextMenuAndRelatedWindows() {
Sébastien Blin1f915762020-08-03 13:27:42 -040076 videoCallOverlay.closePotentialContactPicker()
77 }
78
Sébastien Blin6607e0e2020-07-24 15:15:47 -040079 function handleParticipantsInfo(infos) {
80 if (infos.length === 0) {
81 bestName = ClientWrapper.utilsAdaptor.getBestName(accountId, convUid)
82 } else {
83 bestName = ""
84 }
85 videoCallOverlay.handleParticipantsInfo(infos)
86 }
87
Sébastien Blin1f915762020-08-03 13:27:42 -040088 function previewMagneticSnap() {
89
90
91 /*
92 * Calculate the position where the previewRenderer should attach to.
93 */
94 var previewRendererCenter = Qt.point(
95 previewRenderer.x + previewRenderer.width / 2,
96 previewRenderer.y + previewRenderer.height / 2)
97 var distantRendererCenter = Qt.point(
98 distantRenderer.x + distantRenderer.width / 2,
99 distantRenderer.y + distantRenderer.height / 2)
100
101 if (previewRendererCenter.x >= distantRendererCenter.x) {
102 if (previewRendererCenter.y >= distantRendererCenter.y) {
103
104
105 /*
106 * Bottom right.
107 */
108 previewToX = Qt.binding(function () {
109 return videoCallPageMainRect.width - previewRenderer.width - previewMargin
110 })
111 previewToY = Qt.binding(function () {
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400112 return videoCallPageMainRect.height - previewRenderer.height - previewMarginY
Sébastien Blin1f915762020-08-03 13:27:42 -0400113 })
114 } else {
115
116
117 /*
118 * Top right.
119 */
120 previewToX = Qt.binding(function () {
121 return videoCallPageMainRect.width - previewRenderer.width - previewMargin
122 })
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400123 previewToY = previewMarginY
Sébastien Blin1f915762020-08-03 13:27:42 -0400124 }
125 } else {
126 if (previewRendererCenter.y >= distantRendererCenter.y) {
127
128
129 /*
130 * Bottom left.
131 */
132 previewToX = previewMargin
133 previewToY = Qt.binding(function () {
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400134 return videoCallPageMainRect.height - previewRenderer.height - previewMarginY
Sébastien Blin1f915762020-08-03 13:27:42 -0400135 })
136 } else {
137
138
139 /*
140 * Top left.
141 */
142 previewToX = previewMargin
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400143 previewToY = previewMarginY
Sébastien Blin1f915762020-08-03 13:27:42 -0400144 }
145 }
146 previewRenderer.state = "geoChanging"
147 }
148
Sébastien Blin1f915762020-08-03 13:27:42 -0400149 anchors.fill: parent
150
151 SplitView {
152 id: mainColumnLayout
153
154 anchors.fill: parent
155
156 orientation: Qt.Vertical
157
158 handle: Rectangle {
159 implicitWidth: videoCallPageRect.width
ababia284cae2020-08-10 12:33:34 +0200160 implicitHeight: JamiTheme.splitViewHandlePreferredWidth
Sébastien Blin1f915762020-08-03 13:27:42 -0400161 color: SplitHandle.pressed ? JamiTheme.pressColor : (SplitHandle.hovered ? JamiTheme.hoverColor : JamiTheme.tabbarBorderColor)
162 }
163
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400164
Sébastien Blin1f915762020-08-03 13:27:42 -0400165 Rectangle {
166 id: videoCallPageMainRect
Sébastien Blin1f915762020-08-03 13:27:42 -0400167 SplitView.preferredHeight: (videoCallPageRect.height / 3) * 2
168 SplitView.minimumHeight: videoCallPageRect.height / 2 + 20
169 SplitView.fillWidth: true
170
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400171 MouseArea {
Sébastien Blin1f915762020-08-03 13:27:42 -0400172 anchors.fill: parent
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400173 hoverEnabled: true
174 propagateComposedEvents: true
Sébastien Blin1f915762020-08-03 13:27:42 -0400175
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400176 acceptedButtons: Qt.LeftButton
Sébastien Blin1f915762020-08-03 13:27:42 -0400177
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400178 onDoubleClicked: {
179 needToShowInFullScreen()
Sébastien Blin1f915762020-08-03 13:27:42 -0400180 }
181
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400182 CallOverlay {
183 id: videoCallOverlay
Sébastien Blin1f915762020-08-03 13:27:42 -0400184
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400185 anchors.fill: parent
Sébastien Blin1f915762020-08-03 13:27:42 -0400186
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400187 Connections {
188 target: CallAdapter
Sébastien Blin1f915762020-08-03 13:27:42 -0400189
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400190 function onUpdateTimeText(time) {
191 videoCallOverlay.timeText = time
192 videoCallOverlay.setRecording(CallAdapter.isRecordingThisCall())
193 }
Sébastien Blin1f915762020-08-03 13:27:42 -0400194
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400195 function onUpdateOverlay(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall, bestName) {
196 videoCallOverlay.showOnHoldImage(isPaused)
197 videoCallOverlay.updateButtonStatus(isPaused,
198 isAudioOnly,
199 isAudioMuted,
200 isVideoMuted,
201 isRecording, isSIP,
202 isConferenceCall)
203 videoCallPageRect.bestName = bestName
204 }
Sébastien Blin1f915762020-08-03 13:27:42 -0400205
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400206 function onShowOnHoldLabel(isPaused) {
207 videoCallOverlay.showOnHoldImage(isPaused)
Sébastien Blin1f915762020-08-03 13:27:42 -0400208 }
209 }
Sébastien Blin1f915762020-08-03 13:27:42 -0400210
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400211 onOverlayChatButtonClicked: {
212 if (inVideoCallMessageWebViewStack.visible) {
213 linkedWebview.resetMessagingHeaderBackButtonSource(
214 true)
215 linkedWebview.setMessagingHeaderButtonsVisible(
216 true)
217 inVideoCallMessageWebViewStack.visible = false
218 inVideoCallMessageWebViewStack.clear()
219 } else {
220 linkedWebview.resetMessagingHeaderBackButtonSource(
221 false)
222 linkedWebview.setMessagingHeaderButtonsVisible(
223 false)
224 inVideoCallMessageWebViewStack.visible = true
225 inVideoCallMessageWebViewStack.push(
226 linkedWebview)
227 }
228 }
229 }
Sébastien Blin1f915762020-08-03 13:27:42 -0400230
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400231 DistantRenderer {
232 id: distantRenderer
233
234 anchors.centerIn: videoCallPageMainRect
235 z: -1
236
237 width: videoCallPageMainRect.width
238 height: videoCallPageMainRect.height
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400239
240 onOffsetChanged: {
241 videoCallOverlay.handleParticipantsInfo(CallAdapter.getConferencesInfos())
242 }
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400243 }
244
245 VideoCallPreviewRenderer {
246 id: previewRenderer
247
248
249 /*
250 * Property is used in the {} expression for height (extra dependency),
251 * it will not affect the true height expression, since expression
252 * at last will be taken only, but it will force the height to update
253 * and reevaluate getPreviewImageScalingFactor().
254 */
255 property int previewImageScalingFactorUpdated: 0
256
257 Connections {
258 target: CallAdapter
259
260 onPreviewVisibilityNeedToChange: previewRenderer.visible = visible
261 }
262
263 width: videoCallPageMainRect.width / 4
264 height: {
265 previewImageScalingFactorUpdated
266 return previewRenderer.width * previewRenderer.getPreviewImageScalingFactor()
267 }
268 x: videoCallPageMainRect.width - previewRenderer.width - previewMargin
269 y: videoCallPageMainRect.height - previewRenderer.height - previewMargin - 56 /* Avoid overlay */
270 z: -1
271
272 states: [
273 State {
274 name: "geoChanging"
275 PropertyChanges {
276 target: previewRenderer
277 x: previewToX
278 y: previewToY
279 }
280 }
281 ]
282
283 transitions: Transition {
284 PropertyAnimation {
285 properties: "x,y"
286 easing.type: Easing.OutExpo
287 duration: 250
288
289 onStopped: {
290 previewRenderer.state = ""
291 }
292 }
293 }
294
295 MouseArea {
296 id: dragMouseArea
297
298 anchors.fill: previewRenderer
299
300 onPressed: {
301 clickPos = Qt.point(mouse.x, mouse.y)
302 }
303
304 onReleased: {
Sébastien Blin1f915762020-08-03 13:27:42 -0400305 previewRenderer.state = ""
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400306 previewMagneticSnap()
307 }
308
309 onPositionChanged: {
310
311
312 /*
313 * Calculate mouse position relative change.
314 */
315 var delta = Qt.point(mouse.x - clickPos.x,
316 mouse.y - clickPos.y)
317 var deltaW = previewRenderer.x + delta.x + previewRenderer.width
318 var deltaH = previewRenderer.y + delta.y + previewRenderer.height
319
320
321 /*
322 * Check if the previewRenderer exceeds the border of videoCallPageMainRect.
323 */
324 if (deltaW < videoCallPageMainRect.width
325 && previewRenderer.x + delta.x > 1)
326 previewRenderer.x += delta.x
327 if (deltaH < videoCallPageMainRect.height
328 && previewRenderer.y + delta.y > 1)
329 previewRenderer.y += delta.y
Sébastien Blin1f915762020-08-03 13:27:42 -0400330 }
331 }
Sébastien Blin1f915762020-08-03 13:27:42 -0400332
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400333 onPreviewImageAvailable: {
334 previewImageScalingFactorUpdated++
335 previewImageScalingFactorUpdated--
Sébastien Blin1f915762020-08-03 13:27:42 -0400336 }
Sébastien Blin1f915762020-08-03 13:27:42 -0400337 }
338 }
339
340 color: "transparent"
341 }
342
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400343
Sébastien Blin1f915762020-08-03 13:27:42 -0400344 StackView {
345 id: inVideoCallMessageWebViewStack
346
347 SplitView.preferredHeight: videoCallPageRect.height / 3
348 SplitView.fillWidth: true
349
350 visible: false
351
352 clip: true
353 }
354 }
355
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400356 onBestNameChanged: {
357 ContactAdapter.setCalleeDisplayName(bestName)
Sébastien Blin1f915762020-08-03 13:27:42 -0400358 }
359
360 color: "black"
361}