blob: 7d57e82fd6f899b2b92c75a1dfbf13ca55a4d5e5 [file] [log] [blame]
Sébastien Blin1f915762020-08-03 13:27:42 -04001/*
2 * Copyright (C) 2020 by Savoir-faire Linux
3 * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
Sébastien Blin8940f3c2020-07-23 17:03:11 -04004 * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
Sébastien Blin1f915762020-08-03 13:27:42 -04005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
Andreas Traczyk88816942020-09-04 14:51:39 -040019
Sébastien Blin1f915762020-08-03 13:27:42 -040020import 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
Andreas Traczyk88816942020-09-04 14:51:39 -040026import net.jami.Adapters 1.0
Sébastien Blin1f915762020-08-03 13:27:42 -040027
28import "../../commoncomponents"
29
30Rectangle {
31 id: videoCallPageRect
32
33 property string bestName: "Best Name"
34 property string bestId: "Best Id"
35 property variant clickPos: "1,1"
36 property int previewMargin: 15
Sébastien Blin8940f3c2020-07-23 17:03:11 -040037 property int previewMarginY: previewMargin + 56
Sébastien Blin1f915762020-08-03 13:27:42 -040038 property int previewToX: 0
39 property int previewToY: 0
40
Sébastien Blin8940f3c2020-07-23 17:03:11 -040041 property var linkedWebview: null
Sébastien Blin1f915762020-08-03 13:27:42 -040042
Sébastien Blin1f915762020-08-03 13:27:42 -040043 signal needToShowInFullScreen
44
45 function updateUI(accountId, convUid) {
Sébastien Blin6607e0e2020-07-24 15:15:47 -040046 videoCallOverlay.handleParticipantsInfo(CallAdapter.getConferencesInfos())
47
Andreas Traczyk88816942020-09-04 14:51:39 -040048 bestName = UtilsAdapter.getBestName(accountId, convUid)
Sébastien Blin1f915762020-08-03 13:27:42 -040049
Andreas Traczyk88816942020-09-04 14:51:39 -040050 var id = UtilsAdapter.getBestId(accountId, convUid)
Sébastien Blin1f915762020-08-03 13:27:42 -040051 bestId = (bestName !== id) ? id : ""
52 }
53
54 function setDistantRendererId(id) {
55 distantRenderer.setRendererId(id)
56 }
57
Sébastien Blin8940f3c2020-07-23 17:03:11 -040058 function setLinkedWebview(webViewId) {
59 linkedWebview = webViewId
60 linkedWebview.needToHideConversationInCall.disconnect(
Sébastien Blin1f915762020-08-03 13:27:42 -040061 closeInCallConversation)
Sébastien Blin8940f3c2020-07-23 17:03:11 -040062 linkedWebview.needToHideConversationInCall.connect(
Sébastien Blin1f915762020-08-03 13:27:42 -040063 closeInCallConversation)
64 }
65
66 function closeInCallConversation() {
67 if (inVideoCallMessageWebViewStack.visible) {
Sébastien Blin8940f3c2020-07-23 17:03:11 -040068 linkedWebview.resetMessagingHeaderBackButtonSource(
Sébastien Blin1f915762020-08-03 13:27:42 -040069 true)
Sébastien Blin8940f3c2020-07-23 17:03:11 -040070 linkedWebview.setMessagingHeaderButtonsVisible(true)
Sébastien Blin1f915762020-08-03 13:27:42 -040071 inVideoCallMessageWebViewStack.visible = false
72 inVideoCallMessageWebViewStack.clear()
73 }
74 }
75
76 function closeContextMenuAndRelatedWindows() {
Sébastien Blin1f915762020-08-03 13:27:42 -040077 videoCallOverlay.closePotentialContactPicker()
78 }
79
Sébastien Blin6607e0e2020-07-24 15:15:47 -040080 function handleParticipantsInfo(infos) {
81 if (infos.length === 0) {
Andreas Traczyk88816942020-09-04 14:51:39 -040082 bestName = UtilsAdapter.getBestName(accountId, convUid)
Sébastien Blin6607e0e2020-07-24 15:15:47 -040083 } else {
84 bestName = ""
85 }
86 videoCallOverlay.handleParticipantsInfo(infos)
87 }
88
Sébastien Blin1f915762020-08-03 13:27:42 -040089 function previewMagneticSnap() {
90
91
agsantosc5687502020-09-03 21:19:10 -040092 // Calculate the position where the previewRenderer should attach to.
Sébastien Blin1f915762020-08-03 13:27:42 -040093 var previewRendererCenter = Qt.point(
94 previewRenderer.x + previewRenderer.width / 2,
95 previewRenderer.y + previewRenderer.height / 2)
96 var distantRendererCenter = Qt.point(
97 distantRenderer.x + distantRenderer.width / 2,
98 distantRenderer.y + distantRenderer.height / 2)
99
100 if (previewRendererCenter.x >= distantRendererCenter.x) {
101 if (previewRendererCenter.y >= distantRendererCenter.y) {
102
103
agsantosc5687502020-09-03 21:19:10 -0400104 // Bottom right.
Sébastien Blin1f915762020-08-03 13:27:42 -0400105 previewToX = Qt.binding(function () {
106 return videoCallPageMainRect.width - previewRenderer.width - previewMargin
107 })
108 previewToY = Qt.binding(function () {
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400109 return videoCallPageMainRect.height - previewRenderer.height - previewMarginY
Sébastien Blin1f915762020-08-03 13:27:42 -0400110 })
111 } else {
112
113
agsantosc5687502020-09-03 21:19:10 -0400114 // Top right.
Sébastien Blin1f915762020-08-03 13:27:42 -0400115 previewToX = Qt.binding(function () {
116 return videoCallPageMainRect.width - previewRenderer.width - previewMargin
117 })
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400118 previewToY = previewMarginY
Sébastien Blin1f915762020-08-03 13:27:42 -0400119 }
120 } else {
121 if (previewRendererCenter.y >= distantRendererCenter.y) {
122
123
agsantosc5687502020-09-03 21:19:10 -0400124 // Bottom left.
Sébastien Blin1f915762020-08-03 13:27:42 -0400125 previewToX = previewMargin
126 previewToY = Qt.binding(function () {
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400127 return videoCallPageMainRect.height - previewRenderer.height - previewMarginY
Sébastien Blin1f915762020-08-03 13:27:42 -0400128 })
129 } else {
130
131
agsantosc5687502020-09-03 21:19:10 -0400132 // Top left.
Sébastien Blin1f915762020-08-03 13:27:42 -0400133 previewToX = previewMargin
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400134 previewToY = previewMarginY
Sébastien Blin1f915762020-08-03 13:27:42 -0400135 }
136 }
137 previewRenderer.state = "geoChanging"
138 }
139
Sébastien Blin1f915762020-08-03 13:27:42 -0400140 anchors.fill: parent
141
142 SplitView {
143 id: mainColumnLayout
144
145 anchors.fill: parent
146
147 orientation: Qt.Vertical
148
149 handle: Rectangle {
150 implicitWidth: videoCallPageRect.width
ababia284cae2020-08-10 12:33:34 +0200151 implicitHeight: JamiTheme.splitViewHandlePreferredWidth
Sébastien Blin1f915762020-08-03 13:27:42 -0400152 color: SplitHandle.pressed ? JamiTheme.pressColor : (SplitHandle.hovered ? JamiTheme.hoverColor : JamiTheme.tabbarBorderColor)
153 }
154
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400155
Sébastien Blin1f915762020-08-03 13:27:42 -0400156 Rectangle {
157 id: videoCallPageMainRect
Sébastien Blin1f915762020-08-03 13:27:42 -0400158 SplitView.preferredHeight: (videoCallPageRect.height / 3) * 2
159 SplitView.minimumHeight: videoCallPageRect.height / 2 + 20
160 SplitView.fillWidth: true
161
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400162 MouseArea {
Sébastien Blin1f915762020-08-03 13:27:42 -0400163 anchors.fill: parent
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400164 hoverEnabled: true
165 propagateComposedEvents: true
Sébastien Blin1f915762020-08-03 13:27:42 -0400166
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400167 acceptedButtons: Qt.LeftButton
Sébastien Blin1f915762020-08-03 13:27:42 -0400168
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400169 onDoubleClicked: {
170 needToShowInFullScreen()
Sébastien Blin1f915762020-08-03 13:27:42 -0400171 }
172
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400173 CallOverlay {
174 id: videoCallOverlay
Sébastien Blin1f915762020-08-03 13:27:42 -0400175
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400176 anchors.fill: parent
Sébastien Blin1f915762020-08-03 13:27:42 -0400177
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400178 Connections {
179 target: CallAdapter
Sébastien Blin1f915762020-08-03 13:27:42 -0400180
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400181 function onUpdateTimeText(time) {
182 videoCallOverlay.timeText = time
183 videoCallOverlay.setRecording(CallAdapter.isRecordingThisCall())
184 }
Sébastien Blin1f915762020-08-03 13:27:42 -0400185
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400186 function onUpdateOverlay(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall, bestName) {
187 videoCallOverlay.showOnHoldImage(isPaused)
188 videoCallOverlay.updateButtonStatus(isPaused,
189 isAudioOnly,
190 isAudioMuted,
191 isVideoMuted,
192 isRecording, isSIP,
193 isConferenceCall)
194 videoCallPageRect.bestName = bestName
195 }
Sébastien Blin1f915762020-08-03 13:27:42 -0400196
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400197 function onShowOnHoldLabel(isPaused) {
198 videoCallOverlay.showOnHoldImage(isPaused)
Sébastien Blin1f915762020-08-03 13:27:42 -0400199 }
200 }
Sébastien Blin1f915762020-08-03 13:27:42 -0400201
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400202 onOverlayChatButtonClicked: {
203 if (inVideoCallMessageWebViewStack.visible) {
204 linkedWebview.resetMessagingHeaderBackButtonSource(
205 true)
206 linkedWebview.setMessagingHeaderButtonsVisible(
207 true)
208 inVideoCallMessageWebViewStack.visible = false
209 inVideoCallMessageWebViewStack.clear()
210 } else {
211 linkedWebview.resetMessagingHeaderBackButtonSource(
212 false)
213 linkedWebview.setMessagingHeaderButtonsVisible(
214 false)
215 inVideoCallMessageWebViewStack.visible = true
216 inVideoCallMessageWebViewStack.push(
217 linkedWebview)
218 }
219 }
220 }
Sébastien Blin1f915762020-08-03 13:27:42 -0400221
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400222 DistantRenderer {
223 id: distantRenderer
224
225 anchors.centerIn: videoCallPageMainRect
226 z: -1
227
228 width: videoCallPageMainRect.width
229 height: videoCallPageMainRect.height
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400230
231 onOffsetChanged: {
232 videoCallOverlay.handleParticipantsInfo(CallAdapter.getConferencesInfos())
233 }
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400234 }
235
236 VideoCallPreviewRenderer {
237 id: previewRenderer
238
239
agsantosc5687502020-09-03 21:19:10 -0400240 // Property is used in the {} expression for height (extra dependency),
241 // it will not affect the true height expression, since expression
242 // at last will be taken only, but it will force the height to update
243 // and reevaluate getPreviewImageScalingFactor().
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400244 property int previewImageScalingFactorUpdated: 0
245
246 Connections {
247 target: CallAdapter
248
249 onPreviewVisibilityNeedToChange: previewRenderer.visible = visible
250 }
251
252 width: videoCallPageMainRect.width / 4
253 height: {
254 previewImageScalingFactorUpdated
255 return previewRenderer.width * previewRenderer.getPreviewImageScalingFactor()
256 }
257 x: videoCallPageMainRect.width - previewRenderer.width - previewMargin
agsantosc5687502020-09-03 21:19:10 -0400258 y: videoCallPageMainRect.height - previewRenderer.height - previewMargin - 56 // Avoid overlay
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400259 z: -1
260
261 states: [
262 State {
263 name: "geoChanging"
264 PropertyChanges {
265 target: previewRenderer
266 x: previewToX
267 y: previewToY
268 }
269 }
270 ]
271
272 transitions: Transition {
273 PropertyAnimation {
274 properties: "x,y"
275 easing.type: Easing.OutExpo
276 duration: 250
277
278 onStopped: {
279 previewRenderer.state = ""
280 }
281 }
282 }
283
284 MouseArea {
285 id: dragMouseArea
286
287 anchors.fill: previewRenderer
288
289 onPressed: {
290 clickPos = Qt.point(mouse.x, mouse.y)
291 }
292
293 onReleased: {
Sébastien Blin1f915762020-08-03 13:27:42 -0400294 previewRenderer.state = ""
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400295 previewMagneticSnap()
296 }
297
298 onPositionChanged: {
299
300
agsantosc5687502020-09-03 21:19:10 -0400301 // Calculate mouse position relative change.
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400302 var delta = Qt.point(mouse.x - clickPos.x,
303 mouse.y - clickPos.y)
304 var deltaW = previewRenderer.x + delta.x + previewRenderer.width
305 var deltaH = previewRenderer.y + delta.y + previewRenderer.height
306
307
agsantosc5687502020-09-03 21:19:10 -0400308 // Check if the previewRenderer exceeds the border of videoCallPageMainRect.
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400309 if (deltaW < videoCallPageMainRect.width
310 && previewRenderer.x + delta.x > 1)
311 previewRenderer.x += delta.x
312 if (deltaH < videoCallPageMainRect.height
313 && previewRenderer.y + delta.y > 1)
314 previewRenderer.y += delta.y
Sébastien Blin1f915762020-08-03 13:27:42 -0400315 }
316 }
Sébastien Blin1f915762020-08-03 13:27:42 -0400317
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400318 onPreviewImageAvailable: {
319 previewImageScalingFactorUpdated++
320 previewImageScalingFactorUpdated--
Sébastien Blin1f915762020-08-03 13:27:42 -0400321 }
Sébastien Blin1f915762020-08-03 13:27:42 -0400322 }
323 }
324
325 color: "transparent"
326 }
327
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400328
Sébastien Blin1f915762020-08-03 13:27:42 -0400329 StackView {
330 id: inVideoCallMessageWebViewStack
331
332 SplitView.preferredHeight: videoCallPageRect.height / 3
333 SplitView.fillWidth: true
334
335 visible: false
336
337 clip: true
338 }
339 }
340
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400341 onBestNameChanged: {
342 ContactAdapter.setCalleeDisplayName(bestName)
Sébastien Blin1f915762020-08-03 13:27:42 -0400343 }
344
345 color: "black"
346}