// SPDX-License-Identifier: GPL-3.0-or-later /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 2013 - 2024, nymea GmbH * Copyright (C) 2024 - 2025, chargebyte austria GmbH * * This file is part of nymea-app. * * nymea-app 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. * * nymea-app 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 nymea-app. If not, see . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ import QtQuick import QtQuick.Controls import QtQuick.Controls.Material import QtQuick.Layouts import QtCharts import Qt5Compat.GraphicalEffects import Nymea import "../../components" import "../../delegates" //import QtWebView DashboardDelegateBase { id: root property DashboardWebViewItem item: null configurable: true function configure() { root.openDialog(configDialogComponent) } contentItem: MouseArea { id: delegateRoot width: root.width height: root.height Component.onCompleted: { // This might fail if qml-module-qtwebview isn't around try { var webView = Qt.createQmlObject(webViewString, webViewContainer); print("created webView", webView) } catch(e) { console.warn("Error creating webview") errorLabel.visible = true } } // Some platforms cannot embed webviews inside an app. In those cases, a platform native // Browser will be overlaid on top of the app. As we can't draw on top of that, we'll need to be // clever in resizing and hding... property bool needsHack: ["android", "ios", "osx"].indexOf(Qt.platform.os) >= 0 property bool webViewVisible: !needsHack || (!app.mainMenu.visible && !root.editMode && root.topClip < root.height && root.bottomClip < height && !pageStack.busy && root.dashboardVisible) property int topClip: needsHack ? root.topClip : 0 property int bottomClip: needsHack ? root.bottomClip : 0 property string webViewString: ' import QtQuick; import QtWebView; import Nymea; WebView { id: webView anchors.fill: parent anchors.bottomMargin: delegateRoot.bottomClip + Style.smallMargins anchors.topMargin: delegateRoot.topClip + Style.smallMargins url: root.item.url enabled: root.item.interactive visible: delegateRoot.webViewVisible } ' Item { id: webViewContainer anchors.fill: parent anchors.margins: Style.smallMargins Label { id: errorLabel visible: false anchors.centerIn: parent width: parent.width - Style.margins * 2 horizontalAlignment: Text.AlignHCenter text: qsTr("Web view is not supported on this platform.") wrapMode: Text.WordWrap } } Rectangle { id: mask anchors.fill: parent anchors.margins: Style.smallMargins radius: Style.cornerRadius color: Style.tileBackgroundColor } OpacityMask { anchors.fill: parent anchors.margins: Style.smallMargins source: ShaderEffectSource { sourceItem: webViewContainer recursive: true hideSource: true } maskSource: mask } ColumnLayout { anchors.centerIn: parent width: delegateRoot.width - Style.margins * 2 spacing: Style.margins visible: !parent.webViewVisible ColorIcon { Layout.alignment: Qt.AlignHCenter size: Style.largeIconSize name: "stock_website" color: Style.accentColor } Label { Layout.fillWidth: true text: root.item.url wrapMode: Text.WrapAtWordBoundaryOrAnywhere font.pixelSize: app.smallFont horizontalAlignment: Text.AlignHCenter maximumLineCount: 5 elide: Text.ElideRight } } } Component { id: configDialogComponent NymeaDialog { id: configDialog onAccepted: { root.item.url = urlTextField.text root.item.columnSpan = columnsTabs.currentValue root.item.rowSpan = rowsTabs.currentValue root.item.interactive = interactiveSwitch.checked } SettingsPageSectionHeader { Layout.fillWidth: true text: qsTr("Location") } TextField { id: urlTextField Layout.fillWidth: true Layout.leftMargin: Style.margins Layout.rightMargin: Style.margins placeholderText: qsTr("Enter a URL") text: root.item.url } SettingsPageSectionHeader { Layout.fillWidth: true text: qsTr("Size") } GridLayout { columns: width > 300 ? 2 : 1 Layout.fillWidth: true Layout.leftMargin: Style.margins Layout.rightMargin: Style.margins columnSpacing: Style.smallMargins rowSpacing: Style.smallMargins Label { text: qsTr("Columns") } SelectionTabs { id: columnsTabs Layout.fillWidth: true model: [1, 2, 3, 4, 5, 6] currentIndex: root.item.columnSpan - 1 } Label { text: qsTr("Rows") } SelectionTabs { id: rowsTabs Layout.fillWidth: true model: [1, 2, 3, 4, 5, 6] currentIndex: root.item.rowSpan - 1 } } SettingsPageSectionHeader { Layout.fillWidth: true text: qsTr("Behavior") visible: ["android", "ios"].indexOf(Qt.platform.os) < 0 } SwitchDelegate { id: interactiveSwitch Layout.fillWidth: true checked: root.item.interactive text: qsTr("Interactive") visible: ["android", "ios"].indexOf(Qt.platform.os) < 0 } } } }