client-qml: add initial commit
Change-Id: I32bfdd2a618aa7ac6181da2697e241667b010aab
diff --git a/src/mainview/components/MessageWebView.qml b/src/mainview/components/MessageWebView.qml
new file mode 100644
index 0000000..2045edf
--- /dev/null
+++ b/src/mainview/components/MessageWebView.qml
@@ -0,0 +1,293 @@
+
+/*
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+import QtQuick 2.14
+import QtQuick.Controls 2.14
+import QtQuick.Layouts 1.14
+import QtWebEngine 1.10
+import QtWebChannel 1.14
+import net.jami.Models 1.0
+
+import "../../commoncomponents"
+
+
+Rectangle {
+ id: messageWebViewRect
+
+ property int messageWebViewHeaderPreferredHeight: 60
+ property string headerUserAliasLabelText: ""
+ property string headerUserUserNameLabelText: ""
+
+ signal needToGoBackToWelcomeView
+ signal needToHideConversationInCall
+ signal needToSendContactRequest
+
+ signal sendMessageContentSaved(string arg)
+ signal messagesCleared
+ signal messagesLoaded
+
+
+ function webViewRunJavaScript(arg) {
+ messageWebView.runJavaScript(arg)
+ }
+
+ function setSendContactRequestButtonVisible(visible) {
+ messageWebViewHeader.sendContactRequestButtonVisible = visible
+ }
+
+ function setMessagingHeaderButtonsVisible(visible) {
+ messageWebViewHeader.toggleMessagingHeaderButtonsVisible(visible)
+ }
+
+ function resetMessagingHeaderBackButtonSource(reset) {
+ messageWebViewHeader.resetBackToWelcomeViewButtonSource(reset)
+ }
+
+ anchors.fill: parent
+
+ JamiFileDialog {
+ id: jamiFileDialog
+
+ mode: JamiFileDialog.Mode.OpenFiles
+
+ onAccepted: {
+ var filePaths = jamiFileDialog.files
+ for (var index = 0; index < filePaths.length; ++index) {
+ var path = ClientWrapper.utilsAdaptor.getAbsPath(filePaths[index])
+ MessagesAdapter.setNewMessagesContent(path)
+ }
+ }
+ }
+
+ MessageWebViewHeader {
+
+ DropArea{
+ anchors.fill: parent
+ onDropped: {
+ var path = ClientWrapper.utilsAdaptor.getAbsPath(drop.text.toString())
+ MessagesAdapter.setNewMessagesContent(path)
+ }
+ }
+
+ id: messageWebViewHeader
+
+ anchors.top: messageWebViewRect.top
+ anchors.left: messageWebViewRect.left
+
+ width: messageWebViewRect.width
+ height: messageWebViewHeaderPreferredHeight
+
+ userAliasLabelText: headerUserAliasLabelText
+ userUserNameLabelText: headerUserUserNameLabelText
+
+ onBackToWelcomeViewButtonClicked: {
+ MessagesAdapter.updateDraft()
+ messageWebViewRect.needToGoBackToWelcomeView()
+ }
+
+ onNeedToHideConversationInCall: {
+ messageWebViewRect.needToHideConversationInCall()
+ }
+
+ onSendContactRequestButtonClicked: {
+ MessagesAdapter.sendContactRequest()
+ }
+ }
+
+ QtObject {
+ id: jsBridgeObject
+
+
+ /*
+ * ID, under which this object will be known at chatview.js side.
+ */
+ WebChannel.id: "jsbridge"
+
+
+ /*
+ * Functions that are exposed, return code can be derived from js side
+ * by setting callback function.
+ */
+ function deleteInteraction(arg) {
+ MessagesAdapter.deleteInteraction(arg)
+ }
+
+ function retryInteraction(arg) {
+ MessagesAdapter.retryInteraction(arg)
+ }
+
+ function openFile(arg) {
+ MessagesAdapter.openFile(arg)
+ }
+
+ function acceptFile(arg) {
+ MessagesAdapter.acceptFile(arg)
+ }
+
+ function refuseFile(arg) {
+ MessagesAdapter.refuseFile(arg)
+ }
+
+ function sendMessage(arg) {
+ MessagesAdapter.sendMessage(arg)
+ }
+
+ function sendImage(arg) {
+ MessagesAdapter.sendImage(arg)
+ }
+
+ function sendFile(arg) {
+ MessagesAdapter.sendFile(arg)
+ }
+
+ function selectFile() {
+ jamiFileDialog.open()
+ }
+
+ function acceptInvitation() {
+ MessagesAdapter.acceptInvitation()
+ }
+
+ function refuseInvitation() {
+ MessagesAdapter.refuseInvitation()
+ }
+
+ function blockConversation() {
+ MessagesAdapter.blockConversation()
+ }
+
+ function emitMessagesCleared() {
+ messageWebViewRect.messagesCleared()
+ }
+
+ function emitMessagesLoaded() {
+ messageWebViewRect.messagesLoaded()
+ }
+
+ function emitPasteKeyDetected() {
+ MessagesAdapter.pasteKeyDetected()
+ }
+
+ function openAudioRecorder(spikePosX, spikePosY) {
+ recordBox.openRecorder(spikePosX, spikePosY, false)
+ }
+
+ function openVideoRecorder(spikePosX, spikePosY) {
+ recordBox.openRecorder(spikePosX, spikePosY, true)
+ }
+
+ function saveSendMessageContent(arg) {
+ messageWebViewRect.sendMessageContentSaved(arg)
+ }
+
+ function onComposing(isComposing) {
+ MessagesAdapter.onComposing(isComposing)
+ }
+ }
+
+ WebEngineView {
+
+ id: messageWebView
+
+ anchors.top: messageWebViewHeader.bottom
+ anchors.topMargin: 1
+ anchors.left: messageWebViewRect.left
+
+ width: messageWebViewRect.width
+ height: messageWebViewRect.height - messageWebViewHeaderPreferredHeight
+
+ settings.javascriptEnabled: true
+ settings.javascriptCanOpenWindows: true
+ settings.fullScreenSupportEnabled: true
+ settings.allowRunningInsecureContent: true
+ settings.localContentCanAccessRemoteUrls: true
+ settings.localContentCanAccessFileUrls: true
+ settings.errorPageEnabled: false
+ settings.pluginsEnabled: false
+ settings.screenCaptureEnabled: false
+ settings.linksIncludedInFocusChain: false
+ settings.localStorageEnabled: false
+
+ webChannel: messageWebViewChannel
+ profile: messageWebViewProfile
+
+ DropArea{
+ anchors.fill: parent
+ onDropped: {
+ var path = ClientWrapper.utilsAdaptor.getAbsPath(drop.text.toString())
+ MessagesAdapter.setNewMessagesContent(path)
+ }
+ }
+
+ onLoadingChanged: {
+ if (loadRequest.status == WebEngineView.LoadSucceededStatus) {
+ messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.getStyleSheet(
+ "chatcss",
+ ClientWrapper.utilsAdaptor.qStringFromFile(
+ ":/chatview.css")))
+ messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.getStyleSheet(
+ "chatwin",
+ ClientWrapper.utilsAdaptor.qStringFromFile(
+ ":/chatview-windows.css")))
+
+ messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile(
+ ":/jed.js"))
+ messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile(
+ ":/linkify.js"))
+ messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile(
+ ":/linkify-html.js"))
+ messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile(
+ ":/linkify-string.js"))
+ messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile(
+ ":/qwebchannel.js"))
+ messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile(
+ ":/chatview.js"))
+ messageWebView.runJavaScript("init_i18n();")
+ messageWebView.runJavaScript("displayNavbar(false);")
+ }
+ }
+ Component.onCompleted: {
+ messageWebView.loadHtml(ClientWrapper.utilsAdaptor.qStringFromFile(
+ ":/chatview.html"), ":/chatview.html")
+ messageWebView.url = "qrc:/chatview.html"
+ }
+ }
+
+
+ /*
+ * Provide WebEngineProfile.
+ */
+ WebEngineProfile {
+ id: messageWebViewProfile
+
+ cachePath: ClientWrapper.utilsAdaptor.getCachePath()
+ persistentStoragePath: ClientWrapper.utilsAdaptor.getCachePath()
+ persistentCookiesPolicy: WebEngineProfile.NoPersistentCookies
+ httpCacheType: WebEngineProfile.NoCache
+ httpUserAgent: "jami-windows"
+ }
+
+
+ /*
+ * Provide WebChannel by registering jsBridgeObject.
+ */
+ WebChannel {
+ id: messageWebViewChannel
+ registeredObjects: [jsBridgeObject]
+ }
+}