diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 5f78d7b..bc1599a 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -8,4 +8,4 @@ SPDX-License-Identifier: GFDL-1.3-or-later ## Programming - author: Mirian Margiani -- many improvements: roundedrectangle \ No newline at end of file +- link title copying, link sharing, webview preview: roundedrectangle \ No newline at end of file diff --git a/Opal/LinkHandler/LinkHandler.js b/Opal/LinkHandler/LinkHandler.js index 93319ae..5976aaa 100644 --- a/Opal/LinkHandler/LinkHandler.js +++ b/Opal/LinkHandler/LinkHandler.js @@ -28,16 +28,32 @@ */ /*! - \qmlmethod bool LinkHandler::openOrCopyUrl(externalUrl, title) + \qmlmethod bool LinkHandler::openOrCopyUrl(externalUrl, title, previewType) This function shows a page that lets the user preview an external link (\a externalUrl) before either copying it to the clipboard, copying its title (if available), sharing it or opening it externally. The \a title argument is optional. + This module includes an algorithm for checking if the WebView module is installed, + Internet connection is established, Sailjail permissions include Internet usage + and the scheme provided is an Internet scheme. + You can override this algorithm with \a previewType property which can be one of the following: + + \list + \li \c LinkPreviewType.auto - default + \li \c LinkPreviewType.internetOnly - skips WebView and scheme check, recommended for internet links where scheme should not be checked + \li \c LinkPreviewType.schemeOnly - skips WebView and internet check + \li \c LinkPreviewType.internetAndScheme - skips WebView check, recommended for links where you can't fully know if scheme is http or https + \li \c LinkPreviewType.disable - skips all checks and disables preview, recommended for apps without Internet and WebVoew permissions + \li \c LinkPreviewType.enable - skips all checks and enables preview + + \endlist + + It is recommended to set a value different from auto to skip unnecessary checks for performance. \sa Qt::openUrlExternally */ -function openOrCopyUrl(externalUrl, title) { +function openOrCopyUrl(externalUrl, title, previewType) { pageStack.push(Qt.resolvedUrl("private/ExternalUrlPage.qml"), - {'externalUrl': externalUrl, 'title': !!title ? title : ''}) -} + {'externalUrl': externalUrl, 'title': !!title ? title : '', 'previewType': typeof previewType !== 'undefined' ? previewType : 0}) +} \ No newline at end of file diff --git a/Opal/LinkHandler/PreviewType.qml b/Opal/LinkHandler/PreviewType.qml new file mode 100644 index 0000000..8a6fe06 --- /dev/null +++ b/Opal/LinkHandler/PreviewType.qml @@ -0,0 +1,11 @@ +pragma Singleton +import QtQuick 2.0 + +QtObject { + property int auto: 0 + property int internetOnly: 1 + property int schemeOnly: 2 + property int internetAndScheme: 3 + property int enable: 4 + property int disable: 5 +} \ No newline at end of file diff --git a/Opal/LinkHandler/private/ExternalUrlPage.qml b/Opal/LinkHandler/private/ExternalUrlPage.qml index 04158e8..bec8dcc 100644 --- a/Opal/LinkHandler/private/ExternalUrlPage.qml +++ b/Opal/LinkHandler/private/ExternalUrlPage.qml @@ -7,14 +7,103 @@ import QtQuick 2.2 import Sailfish.Silica 1.0 import Nemo.Notifications 1.0 import Sailfish.Share 1.0 +import Nemo.DBus 2.0 +import '..' Page { id: root property url externalUrl property string title: '' // optional + property int previewType: LinkPreviewType.auto allowedOrientations: Orientation.All + Component { + id: webViewComponent + Page { + id: webViewPage + allowedOrientations: Orientation.All + property bool __linkhandler_webview: true + property var __webview + + onStatusChanged: if (status == PageStatus.Active) + __webview = Qt.createQmlObject("import Sailfish.WebView 1.0 +WebView { + anchors.fill: parent + url: externalUrl +}", webViewPage); else if (__webview) __webview.destroy() + Component.onCompleted: statusChanged() + } + } + + Timer { + id: pushWebviewTimer + interval: 0 + onTriggered: if (previewType === LinkPreviewType.enable) pageStack.pushAttached(webViewComponent) + else if (previewType === LinkPreviewType.schemeOnly) connman.checkState('online') + } + + DBusInterface { + // Sailjail info: if we don't specify Internet permission, we won't have access to this service, and as a result no webview will pop up + // And WebView permission doesn't seem to change anything + id: connman + bus: DBus.SystemBus + service: 'net.connman' + iface: 'net.connman.Manager' + path: '/' + + signalsEnabled: previewType === LinkPreviewType.auto || previewType === LinkPreviewType.internetOnly || previewType === LinkPreviewType.internetAndScheme + + function checkState(state) { + if (state === "online") { + if (previewType === LinkPreviewType.auto) { + try { + const tester = Qt.createQmlObject("import QtQuick 2.0 +import Sailfish.Silica 1.0 +import Sailfish.WebView 1.0 +Item{}", root, 'WebviewTester [inline]') + } catch(err) { console.log(err); return } + if (typeof tester === 'undefined') return + tester.destroy() + } + + if (previewType !== LinkPreviewType.internetOnly) { + switch (externalUrl.toString().slice(0, externalUrl.toString().indexOf(':'))) { + case 'http': + case 'https': + //case 'file': + break + default: return + } + } + + if (!pageStack.nextPage()) + pageStack.pushAttached(webViewComponent) + } else if (pageStack.nextPage() && pageStack.nextPage().__linkhandler_webview) + pageStack.popAttached() + } + + function propertyChanged(name, value) { + if (name === 'State') checkState(value) + } + + Component.onCompleted:{ + switch (previewType) { + case LinkPreviewType.disable: + break + case LinkPreviewType.enable: + case LinkPreviewType.schemeOnly: + // pageStack.completeAnimation doesn't work + pushWebviewTimer.start() + break + default: + call('GetProperties', [], function(properties) { + checkState(properties.State) + }) + } + } + } + ShareAction { id: shareHandler mimeType: 'text/x-url' @@ -70,6 +159,8 @@ Page { } width: parent.width spacing: Theme.paddingLarge + height: implicitHeight + Behavior on height { NumberAnimation { duration: 200 } } ButtonLayout { id: firstRow @@ -123,5 +214,16 @@ Page { } } } + + Label { + text: qsTr("Swipe left to preview") + visible: pageStack.nextPage() && pageStack.nextPage().__linkhandler_webview + width: parent.width - 2*Theme.horizontalPageMargin + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + color: Theme.secondaryHighlightColor + font.pixelSize: Theme.fontSizeSmall + wrapMode: Text.Wrap + } } } diff --git a/Opal/LinkHandler/qmldir b/Opal/LinkHandler/qmldir index e1b28af..5c844f9 100644 --- a/Opal/LinkHandler/qmldir +++ b/Opal/LinkHandler/qmldir @@ -3,3 +3,4 @@ module Opal.LinkHandler # SPDX-FileCopyrightText: 2023 Mirian Margiani # SPDX-License-Identifier: GPL-3.0-or-later LinkHandler 1.0 LinkHandler.js +singleton LinkPreviewType 1.0 PreviewType.qml \ No newline at end of file diff --git a/README.md b/README.md index 133563f..3d8fb79 100644 --- a/README.md +++ b/README.md @@ -5,15 +5,15 @@ SPDX-License-Identifier: GFDL-1.3-or-later # Link handler for Sailfish apps -This module provides a link handler to open, copy or share external links. +This module provides a link handler to open, copy, share or preview external links. Text items and Silica's `Label` support external links using the `title` notation. They can then be opened externally when clicked by a user. -To avoid surprises, it is often desirable to give users the option to copy an -external link instead of immediately opening it in the default web browser. -This module provides a way to do that. +To avoid surprises, it is often desirable to give users the option to copy, +share or preview an external link instead of immediately opening it +in the default web browser. This module provides a way to do that. ## Usage @@ -34,6 +34,19 @@ Label { } ``` +## Permissions + +Some permissions are required for WebView-based preview support in this module to work in Sailjail. Make sure that if you aren't using Internet URLs you don't need Internet permission, and if you are not using preview at all you don't need any of these permissions. + +Add this to your `harbour-my-app.desktop` file: + +```{ini} +[X-Sailjail] +Permissions=Internet;WebView +``` + +See [here](https://github.com/sailfishos/sailjail-permissions#permissions) for a list of all Sailjail permissions. + ## Screenshots | 1. | 2. |