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