blob: 2045edf8b23f2cdb186ad68cb95b8aa03c7ca97c [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>
5 *
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 */
19import QtQuick 2.14
20import QtQuick.Controls 2.14
21import QtQuick.Layouts 1.14
22import QtWebEngine 1.10
23import QtWebChannel 1.14
24import net.jami.Models 1.0
25
26import "../../commoncomponents"
27
28
29Rectangle {
30 id: messageWebViewRect
31
32 property int messageWebViewHeaderPreferredHeight: 60
33 property string headerUserAliasLabelText: ""
34 property string headerUserUserNameLabelText: ""
35
36 signal needToGoBackToWelcomeView
37 signal needToHideConversationInCall
38 signal needToSendContactRequest
39
40 signal sendMessageContentSaved(string arg)
41 signal messagesCleared
42 signal messagesLoaded
43
44
45 function webViewRunJavaScript(arg) {
46 messageWebView.runJavaScript(arg)
47 }
48
49 function setSendContactRequestButtonVisible(visible) {
50 messageWebViewHeader.sendContactRequestButtonVisible = visible
51 }
52
53 function setMessagingHeaderButtonsVisible(visible) {
54 messageWebViewHeader.toggleMessagingHeaderButtonsVisible(visible)
55 }
56
57 function resetMessagingHeaderBackButtonSource(reset) {
58 messageWebViewHeader.resetBackToWelcomeViewButtonSource(reset)
59 }
60
61 anchors.fill: parent
62
63 JamiFileDialog {
64 id: jamiFileDialog
65
66 mode: JamiFileDialog.Mode.OpenFiles
67
68 onAccepted: {
69 var filePaths = jamiFileDialog.files
70 for (var index = 0; index < filePaths.length; ++index) {
71 var path = ClientWrapper.utilsAdaptor.getAbsPath(filePaths[index])
72 MessagesAdapter.setNewMessagesContent(path)
73 }
74 }
75 }
76
77 MessageWebViewHeader {
78
79 DropArea{
80 anchors.fill: parent
81 onDropped: {
82 var path = ClientWrapper.utilsAdaptor.getAbsPath(drop.text.toString())
83 MessagesAdapter.setNewMessagesContent(path)
84 }
85 }
86
87 id: messageWebViewHeader
88
89 anchors.top: messageWebViewRect.top
90 anchors.left: messageWebViewRect.left
91
92 width: messageWebViewRect.width
93 height: messageWebViewHeaderPreferredHeight
94
95 userAliasLabelText: headerUserAliasLabelText
96 userUserNameLabelText: headerUserUserNameLabelText
97
98 onBackToWelcomeViewButtonClicked: {
99 MessagesAdapter.updateDraft()
100 messageWebViewRect.needToGoBackToWelcomeView()
101 }
102
103 onNeedToHideConversationInCall: {
104 messageWebViewRect.needToHideConversationInCall()
105 }
106
107 onSendContactRequestButtonClicked: {
108 MessagesAdapter.sendContactRequest()
109 }
110 }
111
112 QtObject {
113 id: jsBridgeObject
114
115
116 /*
117 * ID, under which this object will be known at chatview.js side.
118 */
119 WebChannel.id: "jsbridge"
120
121
122 /*
123 * Functions that are exposed, return code can be derived from js side
124 * by setting callback function.
125 */
126 function deleteInteraction(arg) {
127 MessagesAdapter.deleteInteraction(arg)
128 }
129
130 function retryInteraction(arg) {
131 MessagesAdapter.retryInteraction(arg)
132 }
133
134 function openFile(arg) {
135 MessagesAdapter.openFile(arg)
136 }
137
138 function acceptFile(arg) {
139 MessagesAdapter.acceptFile(arg)
140 }
141
142 function refuseFile(arg) {
143 MessagesAdapter.refuseFile(arg)
144 }
145
146 function sendMessage(arg) {
147 MessagesAdapter.sendMessage(arg)
148 }
149
150 function sendImage(arg) {
151 MessagesAdapter.sendImage(arg)
152 }
153
154 function sendFile(arg) {
155 MessagesAdapter.sendFile(arg)
156 }
157
158 function selectFile() {
159 jamiFileDialog.open()
160 }
161
162 function acceptInvitation() {
163 MessagesAdapter.acceptInvitation()
164 }
165
166 function refuseInvitation() {
167 MessagesAdapter.refuseInvitation()
168 }
169
170 function blockConversation() {
171 MessagesAdapter.blockConversation()
172 }
173
174 function emitMessagesCleared() {
175 messageWebViewRect.messagesCleared()
176 }
177
178 function emitMessagesLoaded() {
179 messageWebViewRect.messagesLoaded()
180 }
181
182 function emitPasteKeyDetected() {
183 MessagesAdapter.pasteKeyDetected()
184 }
185
186 function openAudioRecorder(spikePosX, spikePosY) {
187 recordBox.openRecorder(spikePosX, spikePosY, false)
188 }
189
190 function openVideoRecorder(spikePosX, spikePosY) {
191 recordBox.openRecorder(spikePosX, spikePosY, true)
192 }
193
194 function saveSendMessageContent(arg) {
195 messageWebViewRect.sendMessageContentSaved(arg)
196 }
197
198 function onComposing(isComposing) {
199 MessagesAdapter.onComposing(isComposing)
200 }
201 }
202
203 WebEngineView {
204
205 id: messageWebView
206
207 anchors.top: messageWebViewHeader.bottom
208 anchors.topMargin: 1
209 anchors.left: messageWebViewRect.left
210
211 width: messageWebViewRect.width
212 height: messageWebViewRect.height - messageWebViewHeaderPreferredHeight
213
214 settings.javascriptEnabled: true
215 settings.javascriptCanOpenWindows: true
216 settings.fullScreenSupportEnabled: true
217 settings.allowRunningInsecureContent: true
218 settings.localContentCanAccessRemoteUrls: true
219 settings.localContentCanAccessFileUrls: true
220 settings.errorPageEnabled: false
221 settings.pluginsEnabled: false
222 settings.screenCaptureEnabled: false
223 settings.linksIncludedInFocusChain: false
224 settings.localStorageEnabled: false
225
226 webChannel: messageWebViewChannel
227 profile: messageWebViewProfile
228
229 DropArea{
230 anchors.fill: parent
231 onDropped: {
232 var path = ClientWrapper.utilsAdaptor.getAbsPath(drop.text.toString())
233 MessagesAdapter.setNewMessagesContent(path)
234 }
235 }
236
237 onLoadingChanged: {
238 if (loadRequest.status == WebEngineView.LoadSucceededStatus) {
239 messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.getStyleSheet(
240 "chatcss",
241 ClientWrapper.utilsAdaptor.qStringFromFile(
242 ":/chatview.css")))
243 messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.getStyleSheet(
244 "chatwin",
245 ClientWrapper.utilsAdaptor.qStringFromFile(
246 ":/chatview-windows.css")))
247
248 messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile(
249 ":/jed.js"))
250 messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile(
251 ":/linkify.js"))
252 messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile(
253 ":/linkify-html.js"))
254 messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile(
255 ":/linkify-string.js"))
256 messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile(
257 ":/qwebchannel.js"))
258 messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile(
259 ":/chatview.js"))
260 messageWebView.runJavaScript("init_i18n();")
261 messageWebView.runJavaScript("displayNavbar(false);")
262 }
263 }
264 Component.onCompleted: {
265 messageWebView.loadHtml(ClientWrapper.utilsAdaptor.qStringFromFile(
266 ":/chatview.html"), ":/chatview.html")
267 messageWebView.url = "qrc:/chatview.html"
268 }
269 }
270
271
272 /*
273 * Provide WebEngineProfile.
274 */
275 WebEngineProfile {
276 id: messageWebViewProfile
277
278 cachePath: ClientWrapper.utilsAdaptor.getCachePath()
279 persistentStoragePath: ClientWrapper.utilsAdaptor.getCachePath()
280 persistentCookiesPolicy: WebEngineProfile.NoPersistentCookies
281 httpCacheType: WebEngineProfile.NoCache
282 httpUserAgent: "jami-windows"
283 }
284
285
286 /*
287 * Provide WebChannel by registering jsBridgeObject.
288 */
289 WebChannel {
290 id: messageWebViewChannel
291 registeredObjects: [jsBridgeObject]
292 }
293}