diff --git a/whatsweb/CMakeLists.txt b/whatsweb/CMakeLists.txt index a4e2e50..3e3f618 100644 --- a/whatsweb/CMakeLists.txt +++ b/whatsweb/CMakeLists.txt @@ -23,4 +23,5 @@ install(FILES whatsweb-push-helper.json DESTINATION ${CMAKE_INSTALL_PREFIX}) install(FILES whatsweb-push.apparmor DESTINATION ${CMAKE_INSTALL_PREFIX}) install(FILES push-apparmor.json DESTINATION ${CMAKE_INSTALL_PREFIX}) install(FILES content-hub.json DESTINATION ${CMAKE_INSTALL_PREFIX}) +install(PROGRAMS launcher.sh DESTINATION ${CMAKE_INSTALL_PREFIX}) diff --git a/whatsweb/app/Backgrounds/screensaver-black.png b/whatsweb/app/Backgrounds/screensaver-black.png index bb7e790..57b3b37 100644 Binary files a/whatsweb/app/Backgrounds/screensaver-black.png and b/whatsweb/app/Backgrounds/screensaver-black.png differ diff --git a/whatsweb/app/Backgrounds/screensaver.png b/whatsweb/app/Backgrounds/screensaver.png index ac8854a..dd48cfc 100644 Binary files a/whatsweb/app/Backgrounds/screensaver.png and b/whatsweb/app/Backgrounds/screensaver.png differ diff --git a/whatsweb/app/Icons/gear.png b/whatsweb/app/Icons/gear.png new file mode 100644 index 0000000..2c81617 Binary files /dev/null and b/whatsweb/app/Icons/gear.png differ diff --git a/whatsweb/app/Icons/warning.png b/whatsweb/app/Icons/warning.png new file mode 100644 index 0000000..dc268ff Binary files /dev/null and b/whatsweb/app/Icons/warning.png differ diff --git a/whatsweb/app/ImportPage.qml b/whatsweb/app/ImportPage.qml index 7d0d6cb..fef3aac 100644 --- a/whatsweb/app/ImportPage.qml +++ b/whatsweb/app/ImportPage.qml @@ -57,19 +57,26 @@ Page { handler: picker.handler //ContentHandler.Source onPeerSelected: { - peer.selectionType = ContentTransfer.Single + peer.selectionType = ContentTransfer.Multiple picker.activeTransfer = peer.request() picker.activeTransfer.stateChanged.connect(function() { - if (picker.activeTransfer.state === ContentTransfer.InProgress) { - console.log("In progress"); - picker.activeTransfer.items = picker.activeTransfer.items[0].url = url; - picker.activeTransfer.state = ContentTransfer.Charged; - } + // if (picker.activeTransfer.state === ContentTransfer.InProgress) { + // console.log("In progress"); + // picker.activeTransfer.items = picker.activeTransfer.items[0].url = url; + // picker.activeTransfer.state = ContentTransfer.Charged; + // } if (picker.activeTransfer.state === ContentTransfer.Charged) { - console.log("Charged"); - picker.imported(picker.activeTransfer.items[0].url) - console.log(picker.activeTransfer.items[0].url) - picker.activeTransfer = null + console.log("Charged"); + var res=""; + for (var i = 0; i < picker.activeTransfer.items.length; i++) { + if (res == "") + res=picker.activeTransfer.items[i].url + else + res=res+"\n"+picker.activeTransfer.items[i].url + + } + picker.imported(res) + picker.activeTransfer = null } }) } diff --git a/whatsweb/app/Main.qml b/whatsweb/app/Main.qml index ce03658..941a6f6 100644 --- a/whatsweb/app/Main.qml +++ b/whatsweb/app/Main.qml @@ -8,7 +8,7 @@ import Qt.labs.settings 1.0 import QtSystemInfo 5.5 import Ubuntu.Components.ListItems 1.3 as ListItemm import Ubuntu.Content 1.3 -import Pparent.DownloadHelper 1.0 +import Pparent.DownloadHelper 1.0 MainView { @@ -16,13 +16,34 @@ MainView { property var appID: "alefnode.whatsweb"; property var hook: "whatsweb"; - property var localStorage: "/home/phablet/.cache/alefnode.whatsweb/alefnode.whatsweb/QtWebEngine"; + property var localStorage: "/home/phablet/.cache/alefnode.whatsweb/alefnode.whatsweb/QtWebEngine"; property int lastUnreadCount: -1; property var lastNotifyTimestamp: 0; + Settings { + id: config + category: "AppSettings" + + property int webviewWidthPortait: 410 + property int webviewWidthLandscape: 900 + property int textFontSize: 110 + property int spanFontSize: 104 + + property bool enableDesktopNotifications: true + property bool enableTitleChangeNotifications: true + property bool enableSoundNotifications: true + property bool enableNotificationCounter: true + + property bool enableScreensaver: true + property bool disableBackgroundAudio: true + + property bool enableQuickCopy: true + property bool enableGpu: true + } + DownloadHelper { id: downloadHelper blob_path: localStorage+"/IndexedDB/https_web.whatsapp.com_0.indexeddb.blob/" @@ -36,21 +57,23 @@ MainView { objectName: "mainView" - //theme.name: "Ubuntu.Components.Themes.SuruDark" applicationName: appID backgroundColor : "transparent" - - - property list importItems - + ScreenSaver { id: screenSaver - screenSaverEnabled: !(Qt.application.active) + screenSaverEnabled: !(Qt.application.active) } + + ScreenSaverView { + id: screenSaverView + visible: (! Qt.application.active) && config.enableScreensaver + } PageStack { id: mainPageStack + visible: Qt.application.active || (! config.enableScreensaver) anchors.fill: parent Component.onCompleted: mainPageStack.push(pageMain) @@ -58,26 +81,22 @@ MainView { Page { id: pageMain anchors.fill: parent - - - ScreenSaverView { - id: screenSaverView - } + visible: Qt.application.active || (! config.enableScreensaver) //Webview----------------------------------------------------------------------------------------------------- WebEngineView { id: webview - audioMuted: !Qt.application.active - visible: Qt.application.active + audioMuted: config.disableBackgroundAudio && (!Qt.application.active) + visible: Qt.application.active || (! config.enableScreensaver) property int keyboardSize: UbuntuApplication.inputMethod.visible ? 10+UbuntuApplication.inputMethod.keyboardRectangle.height/(units.gridUnit / 8) : 0 anchors{ fill: parent } focus: true property var currentWebview: webview settings.pluginsEnabled: true - zoomFactor: mainView.width { + if ( config.enableDesktopNotifications ) notifier.notifyMain(notification.title, notification.message); } onDownloadRequested: { //Not working for now in Qt5 + //Using Download Helper instead } }//End WebEngineProfile @@ -109,6 +130,16 @@ MainView { } url: "https://web.whatsapp.com" userScripts: [ + WebEngineScript { + name: "AppConfig" + injectionPoint: WebEngineScript.DocumentCreation + worldId: WebEngineScript.MainWorld + sourceCode: "window.appConfig = " + JSON.stringify({ + textFontSize: config.textFontSize, + spanFontSize: config.spanFontSize, + enableQuickCopy: config.enableQuickCopy + }) + ";" + }, WebEngineScript { injectionPoint: WebEngineScript.DocumentCreation worldId: WebEngineScript.MainWorld @@ -119,9 +150,13 @@ MainView { onFileDialogRequested: function(request) { request.accepted = true; var importPage = mainPageStack.push(Qt.resolvedUrl("ImportPage.qml"),{"contentType": ContentType.All, "handler": ContentHandler.Source}) - importPage.imported.connect(function(fileUrl) { - console.log(String(fileUrl).replace("file://", "")) - request.dialogAccept(String(fileUrl).replace("file://", "")); + importPage.imported.connect(function(fileUrls) { + var files = [] + var urls = fileUrls.split("\n") + for (var i = 0; i < urls.length; i++) { + files.push(urls[i].trim().replace("file://", "")); + } + request.dialogAccept(files); mainPageStack.pop(importPage) }) importPage.cancel.connect(function() { @@ -151,10 +186,12 @@ MainView { } if ( unread>lastUnreadCount && unread>0 ) { - notifier.triggerDelayedNotification2(unread+" whatsapp message unread"); + if ( config.enableTitleChangeNotifications ) + notifier.triggerDelayedNotification2(unread+" whatsapp message unread"); } lastUnreadCount=unread - if (unread > 0) + + if ( unread > 0 && config.enableNotificationCounter ) notifier.updateCount(unread) else notifier.updateCount(0) @@ -167,16 +204,18 @@ MainView { // Notification based on audio sound file played (Low priority) //--------------------------------------------------------------------------- if (message.startsWith("[DbgAud] https://static.whatsapp.net/")) { - //Send notification in 50ms through timer1 - notifier.triggerDelayedNotification1("New Whatsapp audio notification"); + //Send notification + if ( config.enableSoundNotifications ) + notifier.triggerDelayedNotification1("New Whatsapp audio notification"); } if (message.startsWith("[ClipBoardCopy]")) { - //Send notification in 50ms through timer1 + if (config.enableQuickCopy) + { textEdit.text = message.replace(/^\[ClipBoardCopy\]\s*/, "") - //textEdit.text = message textEdit.selectAll() textEdit.copy() toast.show("Message copied!") + } } if (message.startsWith("[ShowDebug]")) { toast.show(message.replace(/^\[ShowDebug\]\s*/, "")) @@ -187,17 +226,19 @@ MainView { let output = downloadHelper.getLastDownloaded() var exportPage = mainPageStack.push(Qt.resolvedUrl("ExportPage.qml"),{"url": Qt.resolvedUrl("file://"+output),"contentType": ContentType.All}) } - + if (message.startsWith("[HideAppControls]")) + { + notificationsHowto.visible= false; + settingsButton.visible= false; + } if (message.startsWith("[ThemeBackgroundColorDebug]")) { - if ( message.replace(/^\[ThemeBackgroundColorDebug\]\s*/, "") == "#FFFFFF" ) { screenSaverView.backgroundSource="Backgrounds/screensaver.png"; } else screenSaverView.backgroundSource="Backgrounds/screensaver-black.png" ; - notificationsHowto.visible= false; } } @@ -220,7 +261,12 @@ MainView { id: notificationsHowto pageStack: mainPageStack } - + + + SettingsButton{ + id: settingsButton + pageStack: mainPageStack + } } diff --git a/whatsweb/app/NotificationsHowto.qml b/whatsweb/app/NotificationsHowto.qml index b85d615..494b454 100644 --- a/whatsweb/app/NotificationsHowto.qml +++ b/whatsweb/app/NotificationsHowto.qml @@ -44,7 +44,7 @@ Item { // Texte en gras Text { - text: "This application supports notifications." + text: i18n.tr("This application supports notifications.") font.pixelSize: 14 font.bold: false color: "#666666" // gris intermédiaire visible sur clair et sombre @@ -54,7 +54,7 @@ Item { } Label { - text: "Show me how!" + text: i18n.tr("Show me how!") font.pixelSize: 14 color: "#37a5e8" // Couleur bleu typique des liens anchors.horizontalCenter: parent.horizontalCenter @@ -83,7 +83,7 @@ Item { leadingActionBar.actions: [ Action { iconName: "back" - text: "Retour" + text: i18n.tr("Back") onTriggered: { parent.pageStack.pop() } diff --git a/whatsweb/app/SettingsButton.qml b/whatsweb/app/SettingsButton.qml new file mode 100644 index 0000000..7716e1d --- /dev/null +++ b/whatsweb/app/SettingsButton.qml @@ -0,0 +1,48 @@ +import QtQuick 2.9 +import Ubuntu.Components 1.3 +import QtQuick.Window 2.2 +import Ubuntu.Components.ListItems 1.3 as ListItemm +import Ubuntu.Content 1.3 + + +Item { + id: notificationsHowto + width: parent.width + height: parent.height + property PageStack pageStack + + opacity: 0 // initialement invisible + + // Timer pour déclencher l'apparition + Timer { + interval: 2000 // 2 secondes + running: true + repeat: false + onTriggered: notificationsHowto.opacity = 1 + } + + // Animation du fondu + Behavior on opacity { + NumberAnimation { duration: 500 } // 0.5 secondes + } + Image { + source: "Icons/gear.png" + id:settingsButton + width: 25 + height: 25 + anchors { + top: parent.top + right: parent.right + topMargin: units.gu(1) + rightMargin: units.gu(1) + } + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + mainPageStack.push(Qt.resolvedUrl("SettingsPage.qml"),{"config":mainView.config}) + } + } + } + +} diff --git a/whatsweb/app/SettingsPage.qml b/whatsweb/app/SettingsPage.qml new file mode 100644 index 0000000..0d405ab --- /dev/null +++ b/whatsweb/app/SettingsPage.qml @@ -0,0 +1,186 @@ +import QtQuick 2.9 +import Ubuntu.Components 1.3 +import Qt.labs.settings 1.1 +import "UCSComponents" + +Page { + id: settingsPage + title: i18n.tr("Configuration") + + header: PageHeader { + id:header + title: i18n.tr("Settings") + leadingActionBar.actions: + [ + Action { + iconName: "back" + text: i18n.tr("Back") + onTriggered: { + parent.pageStack.pop() + } + } + ] + } + + + // --- Image de fond --- + Image { + id: imageBackground + source: Qt.resolvedUrl("Backgrounds/screensaver-black.png") // ton image de fond + anchors.centerIn: parent + width: parent.width + height: parent.height + fillMode: Image.PreserveAspectCrop + } + + Settings { + id: config + category: "AppSettings" + + property int webviewWidthPortait: 410 + property int webviewWidthLandscape: 900 + property int textFontSize: 110 + property int spanFontSize: 104 + + property bool enableDesktopNotifications: true + property bool enableTitleChangeNotifications: true + property bool enableSoundNotifications: true + property bool enableNotificationCounter: true + + property bool enableScreensaver: true + property bool disableBackgroundAudio: true + + property bool enableQuickCopy: true + property bool enableGpu: true + } + + + + Flickable { + id: flick + anchors { fill: parent; topMargin: header.height } + clip: true + + // Dimensions du contenu à défiler + contentWidth: width + contentHeight: column.implicitHeight + Column { + id:column + width: parent.width + spacing: units.gu(2) + padding: units.gu(1) + //anchors { fill: parent} + + // --- Warning Sections -- + + // Warning 1 + Row { + width: parent ? parent.width : units.gu(40) + anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined + leftPadding: units.gu(2) + height: Math.max(imgWarning1.height, labelWarning1.implicitHeight) + units.gu(1) + spacing: units.gu(1) + Image { + source: "Icons/warning.png" + width: units.gu(3) + height: units.gu(3) + fillMode: Image.PreserveAspectFit + id:imgWarning1 + } + Label { + text: i18n.tr("Warning: changing the following parameters may prevent the app from working correctly. Only modify if you understand what you're doing. You can always go back to default parameters.") + wrapMode: Text.Wrap + font.bold: true + color: "orange" + width: parent.width - units.gu(7) + id:labelWarning1 + } + } + + // Warning 2 + Row { + height: Math.max(imgWarning2.height, labelWarning2.implicitHeight) + units.gu(1) + width: parent ? parent.width : units.gu(40) + anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined + leftPadding: units.gu(2) + spacing: units.gu(1) + Image { + source: "Icons/warning.png" + width: units.gu(3) + height: units.gu(3) + fillMode: Image.PreserveAspectFit + id:imgWarning2 + } + Label { + text: i18n.tr("Warning: parameters will only be applied after restarting the app") + wrapMode: Text.Wrap + font.bold: true + color: "orange" + width: parent.width - units.gu(7) + id:labelWarning2 + } + } + + + + Row{ + Button { + text: i18n.tr("Reset to default values") + onClicked: { + config.webviewWidthPortait = 410 + webviewWidthPortait.value = 410 + config.webviewWidthLandscape = 900 + webviewWidthLandscape.value = 900 + config.textFontSize = 110 + textFontSize.value = 110 + config.spanFontSize = 104 + spanFontSize.value = 104 + + config.enableDesktopNotifications = true + enableDesktopNotifications.checked = true + config.enableTitleChangeNotifications = true + enableTitleChangeNotifications.checked = true + config.enableSoundNotifications = true + enableSoundNotifications.checked = true + config.enableNotificationCounter = true + enableNotificationCounter.checked = true + + config.enableScreensaver = true + enableScreensaver.checked = true + config.disableBackgroundAudio = true + disableBackgroundAudio.checked = true + + config.enableQuickCopy = true + enableQuickCopy.checked = true + config.enableGpu = true + enableGpu.checked = true + } + } + + } + // --- Scaling --- + Label { text: i18n.tr("Scaling"); font.bold: true; fontSize: "large"; color: UbuntuColors.orange } + NumberEditRow { id:webviewWidthPortait; text: i18n.tr("Webview width (portrait)"); value: config.webviewWidthPortait; onValueChanged: config.webviewWidthPortait = value } + NumberEditRow { id:webviewWidthLandscape; text: i18n.tr("Webview width (landsca.)"); value: config.webviewWidthLandscape; onValueChanged: config.webviewWidthLandscape = value } + NumberEditRow { id:textFontSize; text: i18n.tr("Text fontsize (%)"); value: config.textFontSize; onValueChanged: config.textFontSize = value } + NumberEditRow { id:spanFontSize; text: i18n.tr("Span fontsize (%)"); value: config.spanFontSize; onValueChanged: config.spanFontSize = value } + + // --- Notifications --- + Label { text: i18n.tr("Notifications"); font.bold: true; fontSize: "large"; color: UbuntuColors.orange } + SwitchRow { id:enableDesktopNotifications; text: i18n.tr("Enable notifications from desktop not."); checked: config.enableDesktopNotifications; onCheckedChanged: config.enableDesktopNotifications = checked } + SwitchRow { id:enableTitleChangeNotifications; text: i18n.tr("Enable notifications from title change"); checked: config.enableTitleChangeNotifications; onCheckedChanged: config.enableTitleChangeNotifications = checked } + SwitchRow { id:enableSoundNotifications; text: i18n.tr("Enable notifications from sound event"); checked: config.enableSoundNotifications; onCheckedChanged: config.enableSoundNotifications = checked } + SwitchRow { id:enableNotificationCounter; text: i18n.tr("Enable notification counter"); checked: config.enableNotificationCounter; onCheckedChanged: config.enableNotificationCounter = checked } + + // --- Background behaviour --- + Label { text: i18n.tr("Background behaviour"); font.bold: true; fontSize: "large"; color: UbuntuColors.orange } + SwitchRow { id:enableScreensaver; text: i18n.tr("Enable screensaver"); checked: config.enableScreensaver; onCheckedChanged: config.enableScreensaver = checked } + SwitchRow {id:disableBackgroundAudio; text: i18n.tr("Disable background audio"); checked: config.disableBackgroundAudio; onCheckedChanged: config.disableBackgroundAudio = checked } + + // --- Tweaking --- + Label { text: i18n.tr("Tweaking"); font.bold: true; fontSize: "large"; color: UbuntuColors.orange } + SwitchRow { id:enableQuickCopy; text: i18n.tr("Enable quick copy to clipboard"); checked: config.enableQuickCopy; onCheckedChanged: config.enableQuickCopy = checked } + SwitchRow {id:enableGpu; text: i18n.tr("Enable GPU"); checked: config.enableGpu; onCheckedChanged: config.enableGpu = checked } + } + } +} diff --git a/whatsweb/app/UCSComponents/NumberEditRow.qml b/whatsweb/app/UCSComponents/NumberEditRow.qml new file mode 100644 index 0000000..da7e50a --- /dev/null +++ b/whatsweb/app/UCSComponents/NumberEditRow.qml @@ -0,0 +1,69 @@ +import QtQuick 2.15 +import Ubuntu.Components 1.3 + +Row { + id: root + property string text: "Option" + property int value + property int minimumValue: 50 + property int maximumValue: 5000 + property int stepSize: 1 + + width: parent ? parent.width : units.gu(40) + spacing: units.gu(1) + anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined + leftPadding: units.gu(5) + + Label { + id:label + text: root.text + width: units.gu(20) + verticalAlignment: Text.AlignVCenter + color: "#ffffff" + } + + Button { + text: "-" + width: units.gu(3) + onClicked: { + if (root.value - root.stepSize >= root.minimumValue) { + root.value -= root.stepSize + root.valueChanged(root.value) + } + } + } + + TextEdit { + id:textEdit1 + text: root.value.toString() + width: units.gu(8) + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: "#ffffff" + Keys.onReturnPressed: { + if (parseInt(text)>root.minimumValue && parseInt(text)root.minimumValue && parseInt(text) document.querySelector("#app"), + browser: () => document.getElementById('app').getElementsByClassName('browser')[0] , + //MainWrapper stuff (element class two)---------------------------------------------------- mainWrapper: () => document.querySelector('.two'), - unkownSection1: () => document.querySelector('.two').childNodes[1], - unkownSection2: () => document.querySelector('.two').childNodes[1].childNodes[0], - overlayMenus: () => document.querySelector('.two').childNodes[2], - uploadPannel: () => document.querySelector('.two').childNodes[2].childNodes[1], //(to upload photos/videos/document) - leftSettingPannel: () => document.querySelector('.two').childNodes[2].childNodes[0], // leftMenus (Settings, status, community, profile, ...) - chatList: () => document.querySelector('.two').childNodes[3], - chatWindow: () => document.querySelector('.two').childNodes[4], + unkownSection1: () => document.querySelector('.two').childNodes[2], + unkownSection2: () => document.querySelector('.two').childNodes[2].childNodes[0], + overlayMenus: () => document.querySelector('.two').childNodes[3], + uploadPannel: () => document.querySelector('.two').childNodes[3].childNodes[1], //(to upload photos/videos/document) + leftSettingPannel: () => document.querySelector('.two').childNodes[3].childNodes[0], // leftMenus (Settings, status, community, profile, ...) + chatList: () => document.querySelector('.two').childNodes[4], + chatListHeader: () => document.querySelector('.two').childNodes[4].querySelector('header').querySelector('header'), + chatWindow: () => document.querySelector('.two').childNodes[5], + chatHeader: () => document.querySelector('.two').childNodes[5].querySelector('header'), //------------------------------------------------------------------------------------------- upperWrapper: () => document.querySelector('.three'), - contactInfo: () => document.querySelector('.three').childNodes[5], + contactInfo: () => document.querySelector('.two').childNodes[6], leftMenu: () => document.querySelector('header'), @@ -35,142 +90,69 @@ const X = { landingWrapper: () => document.querySelector('.landing-wrapper'), landingHeader: () => document.querySelector('.landing-header'), mainDiv: () => document.querySelector("div#main"), - chatHeader: () => document.querySelector("div#main").querySelector("header") -}; - -//------------------------------------------------------------------------------------- -// Quick ClipBoard code -//------------------------------------------------------------------------------------- - -// Ensemble pour garder la trace des div déjà sélectionnées -var copiedMessage1; -var copiedMessage2; - -document.addEventListener("touchend", () => { - const selection = window.getSelection(); - const selectedText = selection.toString().trim(); - if (selectedText.length > 0) { - const node = selection.anchorNode; - const div = node?.nodeType === 1 ? node.closest("div") : node?.parentElement?.closest("div"); + chatHeader: () => document.querySelector("div#main").querySelector("header"), - - if (div && !div.isContentEditable && copiedMessage1!=div&& copiedMessage2!=div) { - copiedMessage1=div; - copiedMessage2=div; - const range = document.createRange(); - range.selectNodeContents(div); - selection.removeAllRanges(); - selection.addRange(range); - const originalHTML = div.innerHTML; - div.querySelectorAll('img').forEach(img => { - const altText = img.getAttribute('alt') || ''; - const textNode = document.createTextNode(altText); - img.replaceWith(textNode); - }); - console.log("[ClipBoardCopy]" + window.getSelection().toString()); - div.innerHTML=originalHTML; - selection.removeAllRanges(); - } - } - + dialog: () =>document.querySelector('[role="dialog"]'), -}); - - -// Declare variables -updatenotificacion = 0; -allownotification = 0; -var lastClickContact = 0; -var lastClickEditable = 0; -var isInArchivedMenu = 0; -var isInNewChatMenu = 0; -var isInCommunity = 0; - -//----------------------------------------------------- -//Request by default webnofications permission -//----------------------------------------------------- -Notification.requestPermission(); - - -//----------------------------------------------------- -// Usefull functions -//----------------------------------------------------- - function addCss(cssString) { - var head = document.getElementsByTagName('head')[0]; - var newCss = document.createElement('style'); - newCss.type = "text/css"; - newCss.innerHTML = cssString; - head.appendChild(newCss); - } -// Listeners to startup APP -window.addEventListener("load", function(event) { - console.log("Loaded"); - main(); -}); - -document.addEventListener('readystatechange', event => { - console.log(event.target.readyState); - if (event.target.readyState === "complete") { - console.log("Completed"); - } -}); - -//----------------------------------------------------- -// First resize after loading the web -// (temporary timeout only running at the begining) -//------------------------------------------------------ -var check = 0; -var checkExist = setInterval(function() { + linkedDevicesInstructions: () => document.querySelector('#link-device-instructions-list'), + loginView: () => document.querySelector('#link-device-instructions-list').parentElement.parentElement.parentElement.parentElement.parentElement, - if (document.getElementById('app').getElementsByClassName('browser')[0]) { - clean(); - location.reload(); - } else { - if (X.landingWrapper()) { - X.landingWrapper().style.minWidth = 'auto'; - X.landingHeader().style.display = 'none'; - } - if (X.mainWrapper().childNodes.length) { - console.log("Exists!"); - if ( check == 0 ) { - clearInterval(checkExist); - clean(); - main(); - check = 1; - } - } - } -}, 1000); + + //----------------------------------------------------------------------------------------- + isInCommunityPannel: () => (document.querySelector("[role=navigation]") != null), + isElementInChatlist: (el) => ( el.closest('[role="grid"]')!= null ), + isElementChatOpenerInCommunityPanel: (el) => X.leftSettingPannel().contains(lastClickEl) && lastClickEl.closest('[role="listitem"]') && lastClickEl.closest('[role="listitem"]').querySelector("[title]"), + isAPossibleChatOpener: (el) => (el.closest("[role=listitem]") != null) +}; -//---------------------------------------------------------------------- -// Define all the functions to work on it -// (Called one time when main app is loaded) -//---------------------------------------------------------------------- +//----------------------------------------------s-------------------------------------------------- +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// SECTION2: Main() function that is called when it is detected that the main view has loaded +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//------------------------------------------------------------------------------------------------ function main(){ console.log("Call main function") - //Adapt fontsize - addCss("span { font-size: 104% !important; }"); - addCss(".selectable-text { font-size: 110% !important; }"); - addCss(".message-out { padding-right: 20px !important; }"); - addCss(".message-in { padding-left: 20px !important; }"); + // //Adapt fontsize + try { + addCss(".customDialog { transform: scaleX(0.8) scaleY(0.8) !important; transition: transform 0.3s ease !important; }"); + addCss(".emojiDialog { transform: scaleX(0.7) scaleY(0.7) !important; transition: transform 0.3s ease !important; transformOrigin = left bottom !important; left:2% !important; }"); + addCss(".message-out { padding-right: 20px !important; }"); + addCss(".message-in { padding-left: 20px !important; }"); + addCss("span { font-size: "+window.appConfig.spanFontSize+"% !important; }"); + addCss(".selectable-text { font-size: "+window.appConfig.textFontSize+"% !important; }"); + } catch (e) { console.log("Error while applying css: "+e) } + X.overlayMenus().style.width="0"; - showchatlist(); X.chatList().style.minWidth = "100%" - X.chatWindow().style.minWidth = "100%" + X.chatWindow().style.minWidth = "100%" + X.chatWindow().style.maxWidth = "100%" + X.chatWindow().style.width = "100%" X.mainWrapper().style.minWidth = 'auto'; X.mainWrapper().style.minHeight = 'auto'; - - //Avoid opening the keyboard when entering a chat + X.unkownSection1().style.borderInlineStartWidth = "0" ; + + //-------------------------------------------------------------- + // SECTION2.1 Avoid opening the keyboard when entering a chat + // by listening to focusin + //--------------------------------------------------------------- document.body.addEventListener('focusin', (event) => { - const el = event.target; - if ( lastClickEditable == 0 && el.isContentEditable) + lastFocusEl = event.target; + if ( lastFocusEl.isContentEditable && (!lastClickEl || ! lastClickEl.isContentEditable ) ) + { + lastFocusEl.blur(); + lastFocusEl.setAttribute('contenteditable', false); + lastFocusEl.classList.add('contenteditableDisabled'); + } + + if (X.chatWindow().contains(lastFocusEl)) { - el.blur(); + calculateSecondaryChatWindowOpen(); } + }); addLeftMenuButtonToChatList(); @@ -179,60 +161,62 @@ function main(){ X.leftMenu().style.display = 'none'; } - //Fix emoticons panel + //------------------------------------- + //SECTION2.2 Fix emoticons panel + //------------------------------------- if (X.smileyWrapper()) { const observer = new MutationObserver((mutationsList) => { - X.smileyPanel().style.transformOrigin = "left bottom"; - X.smileyPanel().style.transform= 'scale(0.7)'; - X.smileyPanel().style.left= '2%'; - setTimeout(() => { - X.smileyPanel().style.transform= 'scale(0.7)'; - }, 300); - setTimeout(() => { - X.smileyPanel().style.transform= 'scale(0.7)'; - }, 1000); + X.smileyPanel().style.transformOrigin = "left bottom"; + X.smileyPanel().classList.add('emojiDialog') }); observer.observe(X.smileyWrapper(), { childList: true, subtree: true }); } + //------------------------------------------------------------ + //SECTION2.3 Open left panel when changes are detected in it + //------------------------------------------------------------ + if (X.leftSettingPannel()) { + setTimeout( () => { + const observer = new MutationObserver((mutationsList) => { + if ( X.leftMenu().style.display == 'none' && X.chatList().style.left != "-100%" + && !(lastClickEl != null && X.isAPossibleChatOpener(lastClickEl) && ! X.app().contains(lastClickEl) ) ) + { + console.log("toggle menu") + toggleLeftMenu(); + } + }); + observer.observe(X.leftSettingPannel(), { childList: true, subtree: true }); + },35) + } + + //Send theme information to mainView console.log("[ThemeBackgroundColorDebug]"+getComputedStyle(X.leftMenu()).getPropertyValue('--WDS-surface-default').trim()); - //Open menu for new chat list - X.newChatButton().addEventListener('click', () => { - isInNewChatMenu=1; isInCommunity=0; isInArchivedMenu=0; - if ( X.leftMenu().style.display == 'none' ) - toggleLeftMenu(); - }); - //Open menu for archivedMenu - if (X.archivedChatButton().tagName.toLowerCase() === 'button') { - X.archivedChatButton().addEventListener('click', () => { - isInArchivedMenu=1;isInCommunity=0; isInNewChatMenu=0; - if ( X.leftMenu().style.display == 'none' ) - toggleLeftMenu(); - }); - } - - - // Créer un observer pour le body - const observer = new MutationObserver((mutations, obs) => { + //------------------------------------------------------------ + //SECTION2.4 global mutation observer + //------------------------------------------------------------ + const observer3 = new MutationObserver((mutations, obs) => { - if (document.querySelector('.three')) { + if (X.dialog()) + { + X.dialog().style.minWidth="100%" + X.dialog().firstChild.classList.add('customDialog') + } + // Handle contactInfo Openned panel if (X.upperWrapper() !== undefined){ if (X.contactInfo() !== undefined){ inchatcontactandgroupinfo(); } } - } backupBackButton() }); - - // Observer le body entier pour toutes les modifications - observer.observe(document.body, { + // Observe the whole body + observer3.observe(document.body, { childList: true, subtree: true }); @@ -241,43 +225,144 @@ function main(){ Notification.requestPermission(); } -//--------------------------------------------------------------------- -//------------------------------------------------------------ -// Analize JS after every click on APP and execute Actions -//------------------------------------------------------------ -//--------------------------------------------------------------------- -//--------------------------------------------- -// Handle Main navigation to chatWindow -//--------------------------------------------- +//----------------------------------------------------------------------------------------- +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// SECTION3: Click handler: this allows to intercept any click made by the user and do +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//----------------------------------------------------------------------------------------- + window.addEventListener("click", function() { - lastClickEditable=0 - const grid = event.target.closest('[role="grid"]'); - if (grid) { - if (lastClickContact==0) - { - showchatWindow(); - } - lastClickContact=1 + //Register Last clicked element + lastClickEl=event.target; + + //--------------------------------------------------------------------------------- + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // Important section: Handle navigation towards chatWindow + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + //---------------------------------------------------------------------------------- + if (X.isElementInChatlist(lastClickEl)) + showchatWindow(); + + setTimeout( () => { + + calculateSecondaryChatWindowOpen(); + + //(Re)-enable content Editable ( If it was disabled when "OnFocus" was called without click) + if ( lastClickEl.closest('.contenteditableDisabled') ) + { + lastClickEl.closest('.contenteditableDisabled').setAttribute('contenteditable', true); + lastClickEl.closest('.contenteditableDisabled').classList.remove('contenteditableDisabled') + } + needToShowChatWindow=0; + },5); +}); + + +function calculateSecondaryChatWindowOpen() +{ + if ( X.isInCommunityPannel() ) + { + //Special detect for in-community Panel + if (X.isElementChatOpenerInCommunityPanel(lastClickEl)) + showchatWindow(); } else { - lastClickContact=0 - const el=event.target; - if ( el && el.isContentEditable) - { - lastClickEditable=1; - } + //If the focus was requested to ChatWindow + if (X.chatWindow().contains(lastFocusEl) ) + { + //Click form Settings Panel (except community panel) -> proceed and open the chatWindow + if( X.leftSettingPannel().contains(lastClickEl) ) + { + //We have clicked on an element of left window + showchatWindow(); + } + //If we have a click on an orpheline listitem proceed as well + else if ( ! X.app().contains(lastClickEl) && X.isAPossibleChatOpener(lastClickEl) ) + { + showchatWindow(); + } + } } - -}); +} -//---------------------------------------------------- -// Security to add back buttons it not present -//--------------------------------------------------- window.addEventListener("click", function() { -backupBackButton(); -}); + setTimeout( () => { + backupBackButton(); + },400); + //Backup Back button + setTimeout( () => { + backupBackButton(); + },4000); +}) + +//--------------------------------------------------------------------- +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//SECTION4: Navigation functions showchatWindow() and showchatList() +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//--------------------------------------------------------------------- +function showchatlist(){ + + if ( X.leftMenu().style.display != 'none') + toggleLeftMenu() + + //Slide back Chatlist panel to main view + X.chatList().style.transition= "left 0.25s ease-in-out"; + X.chatList().style.position= 'absolute'; + X.chatList().style.left= '0'; + + + document.querySelectorAll(".contenteditableDisabled").forEach(el2 => { + el2.classList.remove('contenteditableDisabled') + el2.setAttribute("contenteditable", "true"); + }); +} + +function showchatWindow(){ + //Make sure to unfocus any focused élément of previous view + document.activeElement.blur(); + + X.chatWindow().style.position="" + X.chatWindow().style.left="" + X.chatWindow().style.minWidth = "100%" + X.chatWindow().style.maxWidth = "100%" + X.chatWindow().style.width = "100%" + + //Slide Chatlist panel to the left + X.chatList().style.transition= "left 0.25s ease-in-out"; + X.chatList().style.position= 'absolute'; + X.chatList().style.left= "-100%"; + + //Hide left menu (in case it was oppened) + X.leftMenu().style.display = 'none'; + X.unkownSection2().style.minWidth = "100%" + X.overlayMenus().style.minWidth = "100%" + X.overlayMenus().style.width="100%"; + + //Activate Upload Panel, in case the user will upload some files + X.uploadPannel().style.width="100%"; + X.uploadPannel().style.minWidth="100%"; + X.leftSettingPannel().style.display="none"; + addBackButtonToChatViewWithTimeout(); +} + +function addBackButtonToChatViewWithTimeout() +{ + //Add back Button + setTimeout(() => { + addBackButtonToChatView(); + }, 20); + + setTimeout(() => { + addBackButtonToChatView(); + }, 300); + + setTimeout(() => { + addBackButtonToChatView(); + }, 1500); + +} function backupBackButton() { @@ -295,103 +380,62 @@ function backupBackButton() } } } - -//--------------------------------------------- -// Handle navigation form leftmenu to chatWindow -//--------------------------------------------- -window.addEventListener("click", function() { - - //Cette fonction gère seulement si le menu de gauche est affiché - if ( X.leftMenu().style.display == 'none' ) - return; - - //Click on a chat in menu -> Show chat menu - if (isInNewChatMenu ==1 - && event.target.closest('[role="listitem"]') - && event.target.closest('[role="listitem"]').firstElementChild.getAttribute('role') === 'button'){ - showchatWindow(); - } - - if ( event.target.getAttribute('data-icon') === 'community-filled-refreshed-32' || event.target.getAttribute('data-icon') === 'community-refreshed-32') - { - isInCommunity=1; - isInArchivedMenu=0; - isInNewChatMenu=0; - addBackButtonToChatViewWithTimeout(); - } - - //Changing view in menus - if (event.target.getAttribute('data-icon') === 'status-refreshed' - || event.target.getAttribute('data-icon') === 'newsletter-outline' - || event.target.getAttribute('data-icon') === 'settings-refreshed' - || event.target.getAttribute('data-icon') === 'status-filled-refreshed' - || event.target.getAttribute('data-icon') === 'newsletter-outline' - || event.target.getAttribute('data-icon') === 'settings-filled-refreshed') - { - console.log("view changed") - isInArchivedMenu=0; - isInNewChatMenu=0; - isInCommunity=0; - } - - - //Click on a chat in menu -> Show chat menu - if (isInArchivedMenu ==1 - && X.leftSettingPannel().contains(event.target) - && event.target.closest('[role="listitem"]') - && event.target.closest('[role="listitem"]').firstElementChild.hasAttribute('aria-selected')){ - showchatWindow(); - } - - //Click on a chat in menu -> Show chat menu - if (isInNewChatMenu ==1 - && X.leftSettingPannel().contains(event.target) - && event.target.closest('[role="listitem"]') - && event.target.closest('[role="listitem"]').firstElementChild.getAttribute('role') === 'button'){ - showchatWindow(); - } - - //Click on a chat in menu -> Show chat menu - if (isInCommunity ==1 - && X.leftSettingPannel().contains(event.target) - && event.target.closest('[role="listitem"]')){ - if (event.target.closest('[role="listitem"]').querySelector("[title]")) - showchatWindow(); - else - addBackButtonToChatViewWithTimeout(); - } + +//--------------------------------------------------------------- +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// SECTION5: Functions to add navigation buttons to headers +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//--------------------------------------------------------------- + +//------------------------------------------------------------------------------------ +// Function do add a button to access left menu +// inside main chat list header +//------------------------------------------------------------------------------------ +function addLeftMenuButtonToChatList(){ - if (event.target.getAttribute('data-icon') === 'chat-filled-refreshed' || event.target.getAttribute('data-icon') === 'chat-refreshed') - { - isInArchivedMenu=0; - isInNewChatMenu=0; - isInCommunity=0; - addBackButtonToChatViewWithTimeout(); - } + if ( X.chatListHeader() && X.chatListHeader().firstChild && ! X.chatListHeader().querySelector('#added_menu_button') ) + { + addCss(".added_menu_button span { display:block; height: 100%; width: 100%;}.added_menu_button { z-index:500; width:50px; height:45px; } html[dir] .added_menu_button { border-radius:50%; } html[dir=ltr] .added_menu_button { right:11px } html[dir=rtl] .added_menu_button { left:11px } .added_menu_button path { fill:var(--panel-header-icon); fill-opacity:1 } .svg_back { transform: rotate(90deg); height: 100%;}"); + + var newHTML = document.createElement('div'); + newHTML.className += "added_menu_button"; + newHTML.style = ""; + newHTML.addEventListener("click", toggleLeftMenu); + newHTML.innerHTML = '
'; -}); - -//--------------------------------------------- -// Handle quick copy to ClipBoard -//--------------------------------------------- -window.addEventListener("click", function() { - //For Quick Copy to ClipBoard system - if ( lastClickContact != 1 ) - { - const selection = window.getSelection(); - const selectedText = selection.toString().trim(); - if (selectedText.length == 0) { - if (copiedMessage1) copiedMessage1 = null; - else copiedMessage2 = null; + //Insert it, TODO improve the way it is inserted + X.chatListHeader().firstChild.style.width="calc(100% - 40px)"; + X.chatListHeader().prepend(newHTML); } - } - -}); + +} + + + +//----------------------------------------------------------------------------- +// Function to add a back button in chat view header +// To go back to main chat list view +//---------------------------------------------------------------------------- +function addBackButtonToChatView(){ + + addCss(".back_button span { display:block; height: 100%; width: 100%;}.back_button { z-index:200; width:37px; height:45px; } html[dir] .back_button { border-radius:50%; } html[dir=ltr] .back_button { right:11px } html[dir=rtl] .back_button { left:11px } .back_button path { fill:var(--panel-header-icon); fill-opacity:1 } .svg_back { transform: rotate(90deg); height: 100%;}"); + + var newHTML = document.createElement('div'); + newHTML.className += "back_button"; + newHTML.style = ""; + newHTML.addEventListener("click", showchatlist); + newHTML.innerHTML = ""; + + if (! X.chatHeader().querySelector('#back_button') ) + X.chatHeader().prepend(newHTML); +} //------------------------------------------------------------------------------------ -// Function To display or hide left menu +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// SECTION6: Function To display or hide left menu +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //------------------------------------------------------------------------------------ function toggleLeftMenu(){ if (X.leftMenu()) { @@ -410,11 +454,16 @@ function toggleLeftMenu(){ X.uploadPannel().style.minWidth=""; X.leftSettingPannel().style.display=""; X.leftSettingPannel().style.maxWidth="85%"; - X.leftSettingPannel().style.minWidth="85%"; + X.leftSettingPannel().style.minWidth="85%"; + X.chatWindow().style.position="absolute" + X.chatWindow().style.left="0" + X.leftMenu().style.marginRight="-1px" } else { + X.chatWindow().style.position="" + X.chatWindow().style.left="" X.chatList().style.position= 'absolute'; X.chatList().style.left= '0'; X.overlayMenus().style.minWidth = "0%" @@ -429,115 +478,107 @@ function toggleLeftMenu(){ } } -//------------------------------------------------------------------------------------ -// Function do add a button to access left menu -// inside main chat list header -//------------------------------------------------------------------------------------ -function addLeftMenuButtonToChatList(){ - addCss(".added_menu_button span { display:block; height: 100%; width: 100%;}.added_menu_button { z-index:500; width:50px; height:45px; } html[dir] .added_menu_button { border-radius:50%; } html[dir=ltr] .added_menu_button { right:11px } html[dir=rtl] .added_menu_button { left:11px } .added_menu_button path { fill:var(--panel-header-icon); fill-opacity:1 } .svg_back { transform: rotate(90deg); height: 100%;}"); - - var newHTML = document.createElement('div'); - newHTML.className += "added_menu_button"; - newHTML.style = ""; - newHTML.addEventListener("click", toggleLeftMenu); - newHTML.innerHTML = '
'; - - //Insert it, TODO improve the way it is inserted - document.querySelectorAll('header').forEach(header => { - if ( header.querySelector('[data-icon="new-chat-outline"]') && ! header.querySelector('#added_menu_button') ) - { - if ( header.firstChild.firstChild ) - header.firstChild.firstChild .style.width="calc(100% - 40px)"; - header.prepend(newHTML); - } - }); -} - - - -//----------------------------------------------------------------------------- -// Function to add a back button in chat view header -// To go back to main chat list view -//---------------------------------------------------------------------------- -function addBackButtonToChatView(){ - - addCss(".back_button span { display:block; height: 100%; width: 100%;}.back_button { z-index:200; width:37px; height:45px; } html[dir] .back_button { border-radius:50%; } html[dir=ltr] .back_button { right:11px } html[dir=rtl] .back_button { left:11px } .back_button path { fill:var(--panel-header-icon); fill-opacity:1 } .svg_back { transform: rotate(90deg); height: 100%;}"); - - var newHTML = document.createElement('div'); - newHTML.className += "back_button"; - newHTML.style = ""; - newHTML.addEventListener("click", showchatlist); - newHTML.innerHTML = ""; - - if (! X.chatHeader().querySelector('#back_button') ) - X.chatHeader().prepend(newHTML); -} +//------------------------------------------------------------------------------------- +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// SECTION7: Code for Quick ClipBoard +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//------------------------------------------------------------------------------------- +// Ensemble pour garder la trace des div déjà sélectionnées +var copiedMessage1; +var copiedMessage2; -//----------------------------------------------------------------------------- -// Function to show main chat list view -//---------------------------------------------------------------------------- -function showchatlist(){ - //Make sure to unfocus any focused élément of previous view - document.activeElement.blur(); - - //Slide back Chatlist panel to main view - X.chatList().style.transition= "left 0.30s ease-in-out"; - X.chatList().style.position= 'absolute'; - X.chatList().style.left= '0'; - - //Comming back to community pannel, and left pannel was open close it - if (isInCommunity ==1 && X.leftMenu().style.display != 'none' ) +document.addEventListener("touchend", () => { + if (window.appConfig.enableQuickCopy) { - toggleLeftMenu(); + const selection = window.getSelection(); + const selectedText = selection.toString().trim(); + if (selectedText.length > 0) { + const node = selection.anchorNode; + const div = node?.nodeType === 1 ? node.closest("div") : node?.parentElement?.closest("div"); + + + if (div && !div.isContentEditable && copiedMessage1!=div&& copiedMessage2!=div) { + copiedMessage1=div; + copiedMessage2=div; + const range = document.createRange(); + range.selectNodeContents(div); + selection.removeAllRanges(); + selection.addRange(range); + const originalHTML = div.innerHTML; + div.querySelectorAll('img').forEach(img => { + const altText = img.getAttribute('alt') || ''; + const textNode = document.createTextNode(altText); + img.replaceWith(textNode); + }); + console.log("[ClipBoardCopy]" + window.getSelection().toString()); + div.innerHTML=originalHTML; + selection.removeAllRanges(); + } } - -} - -function showchatWindow(){ - //Make sure to unfocus any focused élément of previous view - document.activeElement.blur(); - - //Slide Chatlist panel to the left - X.chatList().style.transition= "left 0.30s ease-in-out"; - X.chatList().style.position= 'absolute'; - X.chatList().style.left= "-100%"; - - //Hide left menu (in case it was oppened) - X.leftMenu().style.display = 'none'; - X.unkownSection2().style.minWidth = "100%" - X.overlayMenus().style.minWidth = "100%" - X.overlayMenus().style.width="100%"; + } +}); - //Activate Upload Panel, in case the user will upload some files - X.uploadPannel().style.width="100%"; - X.uploadPannel().style.minWidth="100%"; - X.leftSettingPannel().style.display="none"; - addBackButtonToChatViewWithTimeout(); -} +window.addEventListener("click", function() { + if (window.appConfig.enableQuickCopy) + { + setTimeout(function() { + // Handle events for Quick Copy to Clipboard + const selection = window.getSelection(); + const selectedText = selection.toString().trim(); -function addBackButtonToChatViewWithTimeout() -{ - //Add back Button - setTimeout(() => { - addBackButtonToChatView(); - }, 20); + if (selectedText.length === 0) { + if (copiedMessage1) copiedMessage1 = null; + else copiedMessage2 = null; + } + }, 800); // délai en millisecondes + } +}); + +//------------------------------------------------------------------------------- +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//SECTION8: Pre-Loader: this code executes before the mainview is started. +// First resize after loading the web +// (temporary timeout only running at the begining) +////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//------------------------------------------------------------------------------- +var check = 0; +var checkExist = setInterval(function() { + if (X.landingWrapper()) { + X.landingWrapper().style.minWidth = 'auto'; + X.landingHeader().style.display = 'none'; + } + if (X.linkedDevicesInstructions()) + { + //Make the login page responsive + X.loginView().style.width="100%" + X.loginView().style.height="100%" + X.loginView().style.position="fixed" + X.loginView().style.left="0" + X.loginView().style.top="0" + X.loginView().style.borderRadius= "0"; + X.loginView().style.paddingLeft= "5%"; + X.linkedDevicesInstructions().parentElement.parentElement.style.transformOrigin="left"; + X.linkedDevicesInstructions().parentElement.parentElement.style.transform="scaleX(0.8) scaleY(0.8)"; + console.log("[HideAppControls]") + } + if (X.mainWrapper().childNodes.length) { + if ( check == 0 ) { + clearInterval(checkExist); + console.log("[HideAppControls]") + main(); + check = 1; + } + } +}, 1000); - setTimeout(() => { - addBackButtonToChatView(); - }, 300); - - setTimeout(() => { - addBackButtonToChatView(); - }, 1500); - -} -//----------------------------------------------------------------------------- -// Functions to handle contactInfo pannel +//---------------------------------------------------------------------------- +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// SECTION9: function to handle contactInfo pannel +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //---------------------------------------------------------------------------- function inchatcontactandgroupinfo(){ - // console.log("inchatcontactandgroupinfo") if (X.contactInfo()){ //We need for this section to use absolute postion X.contactInfo().style.position= "absolute"; @@ -547,29 +588,60 @@ function inchatcontactandgroupinfo(){ } } +//---------------------------------------------------------------------------- +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// SECTION10: Declare global variables and useful functions +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//---------------------------------------------------------------------------- +// Declare variables +updatenotificacion = 0; +allownotification = 0; +var lastClickEl=null; +var lastFocusEl=null; +var needToShowChatWindow=0; +var firstChatLoad=1; -//----------------------------------------------------------------------------- -// Clean -//---------------------------------------------------------------------------- + function addCss(cssString) { + var head = document.getElementsByTagName('head')[0]; + var newCss = document.createElement('style'); + newCss.type = "text/css"; + newCss.innerHTML = cssString; + head.appendChild(newCss); + } + + +// Listeners to startup APP +window.addEventListener("load", function(event) { + console.log("Loaded"); + main(); +}); -function clean() { - navigator.serviceWorker.getRegistrations().then(function(registrations) { - for(let registration of registrations) { - registration.unregister() - }}).catch(function(err) { - console.log('Service Worker registration failed: ', err); - }); -} +document.addEventListener('readystatechange', event => { + console.log(event.target.readyState); + if (event.target.readyState === "complete") { + console.log("Completed"); + } +}); +//---------------------------------------------------------------------------- +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// SECTION11: Request Desktop Notification permission, on load +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//---------------------------------------------------------------------------- +Notification.requestPermission(); + //----------------------------------------------------------------------- // End of main thing //----------------------------------------------------------------------- -//----------------------------------------------------------------------- -// Detect Audio évents to trigger Notifications -//----------------------------------------------------------------------- +//---------------------------------------------------------------------------- +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// SECTION12: Detect Audio évents to trigger Notifications +// to detect audio notifications +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//---------------------------------------------------------------------------- (function() { if (window.__my_audio_hook_installed) return; window.__my_audio_hook_installed = true; @@ -617,9 +689,14 @@ function clean() { -//---------------------------------------------------------------------------------------- -// Handle download Blobs to local storage -//----------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// SECTION13: Handle blob downloads Workaround. +// This work with qml-download-helper-module to allow downloads +// Despite that Qt5 does not support download from blobs. +// TO BE REMOVED WHEN UPGRADING TO QT6 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//---------------------------------------------------------------------------- const blobMap = new Map(); var downloadedBlob; @@ -679,8 +756,6 @@ var downloadedBlob; try { const href = target.href; if (href.startsWith('blob:')) { - //console.log('[DownloadBlob]', href); - // si tu veux aussi accéder au Blob objet : const entry = blobMap.get(href); downloadedBlob=entry; saveBlob(downloadedBlob.blob,"testpierre") diff --git a/whatsweb/launcher.sh b/whatsweb/launcher.sh new file mode 100644 index 0000000..52ac431 --- /dev/null +++ b/whatsweb/launcher.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +enableGPU=true; + +while read p; do + if [ "$p" = "enableGpu=false" ]; then + enableGPU="false"; + fi +done < /home/phablet/.config/alefnode.whatsweb/alefnode.whatsweb.conf + +if [ "$enableGPU" = "true" ]; then + export QTWEBENGINE_CHROMIUM_FLAGS="" + exec qmlscene %u -I qml-plugins/ app/Main.qml --scaling --gles +else + export QTWEBENGINE_CHROMIUM_FLAGS="--disable-gpu" + exec qmlscene %u -I qml-plugins/ app/Main.qml --scaling --disable-gpu --software +fi diff --git a/whatsweb/manifest.json b/whatsweb/manifest.json index 524f212..df05832 100644 --- a/whatsweb/manifest.json +++ b/whatsweb/manifest.json @@ -14,7 +14,7 @@ "push-helper": "whatsweb-push-helper.json" } }, - "version": "0.3.2", + "version": "0.3.3", "maintainer": "Adrian Campos ", "framework": "ubuntu-sdk-20.04" } diff --git a/whatsweb/whatsweb.desktop b/whatsweb/whatsweb.desktop index ca31754..c59f1c8 100644 --- a/whatsweb/whatsweb.desktop +++ b/whatsweb/whatsweb.desktop @@ -1,7 +1,7 @@ [Desktop Entry] Name=WhatsWeb Comment=Whatsapp with Responsive -Exec=qmlscene %u -I qml-plugins/ app/Main.qml --scaling --multisample --gles +Exec=./launcher.sh Terminal=false Type=Application Icon=icon.png