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]
+    }
+}