fix(dapps) Wallet Connect internet connection reestablishing issue
Add a new NetworkChecker QObject to StatusQ to be used in checking internet connection status. This is used by the WebEngineLoader to only allow loading of web pages when there is an active internet to cover for a corner case on MacOS where the internet connection is not reestablished if the WebEngineView was loaded without an active internet connection. Closes: #15598, #15806
This commit is contained in:
parent
910af539d6
commit
98c18901e0
|
@ -57,8 +57,7 @@ proc getActiveSessions*(validAtTimestamp: int): JsonNode =
|
|||
return nil
|
||||
|
||||
let jsonResultStr = rpcRes.result.getStr()
|
||||
if jsonResultStr == "null":
|
||||
# nil means error
|
||||
if jsonResultStr == "null" or jsonResultStr == "":
|
||||
return newJArray()
|
||||
|
||||
if rpcRes.result.kind != JArray:
|
||||
|
|
|
@ -83,6 +83,15 @@ Item {
|
|||
font.bold: true
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
StatusBaseText { text: "SDK status:" }
|
||||
Rectangle {
|
||||
Layout.preferredWidth: 20
|
||||
Layout.preferredHeight: Layout.preferredWidth
|
||||
radius: Layout.preferredWidth / 2
|
||||
color: walletConnectService.wcSDK.sdkReady ? "green" : "red"
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
text: "Testnet Mode"
|
||||
|
@ -289,7 +298,7 @@ Item {
|
|||
id: walletConnectService
|
||||
|
||||
wcSDK: WalletConnectSDK {
|
||||
active: settings.enableSDK
|
||||
enableSdk: settings.enableSDK
|
||||
|
||||
projectId: projectIdText.projectId
|
||||
}
|
||||
|
|
|
@ -108,6 +108,7 @@ add_library(StatusQ SHARED
|
|||
include/StatusQ/modelsyncedcontainer.h
|
||||
include/StatusQ/modelutilsinternal.h
|
||||
include/StatusQ/movablemodel.h
|
||||
include/StatusQ/networkchecker.h
|
||||
include/StatusQ/objectproxymodel.h
|
||||
include/StatusQ/permissionutilsinternal.h
|
||||
include/StatusQ/rolesrenamingmodel.h
|
||||
|
@ -137,6 +138,7 @@ add_library(StatusQ SHARED
|
|||
src/modelentry.cpp
|
||||
src/modelutilsinternal.cpp
|
||||
src/movablemodel.cpp
|
||||
src/networkchecker.cpp
|
||||
src/objectproxymodel.cpp
|
||||
src/permissionutilsinternal.cpp
|
||||
src/plugin.cpp
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
/// Checks if the internet connection is available, when active.
|
||||
/// It checks the connection every 30 seconds as long as the \c active property is \c true.
|
||||
class NetworkChecker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool isOnline READ isOnline NOTIFY isOnlineChanged)
|
||||
Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
|
||||
|
||||
public:
|
||||
explicit NetworkChecker(QObject* parent = nullptr);
|
||||
bool isOnline() const;
|
||||
|
||||
bool isActive() const;
|
||||
void setActive(bool active);
|
||||
|
||||
signals:
|
||||
void isOnlineChanged(bool online);
|
||||
void activeChanged(bool active);
|
||||
|
||||
private:
|
||||
QNetworkAccessManager manager;
|
||||
QTimer timer;
|
||||
bool online = false;
|
||||
bool active = true;
|
||||
constexpr static std::chrono::milliseconds checkInterval = 30s;
|
||||
|
||||
void checkNetwork();
|
||||
void onFinished(QNetworkReply* reply);
|
||||
void updateRegularCheck(bool active);
|
||||
};
|
|
@ -3,6 +3,8 @@ import QtQuick 2.15
|
|||
import QtWebEngine 1.10
|
||||
import QtWebChannel 1.15
|
||||
|
||||
import StatusQ 0.1
|
||||
|
||||
// Helper to load and setup an instance of \c WebEngineView
|
||||
//
|
||||
// The \c webChannelObjects property is used to register specific objects
|
||||
|
@ -11,34 +13,33 @@ import QtWebChannel 1.15
|
|||
// qrc:/StatusQ/Components/private/qwebchannel/helpers.js will provide
|
||||
// access to window.statusq APIs used to exchange data between the internal
|
||||
// web engine and the QML application
|
||||
//
|
||||
// It doesn't load the web engine until NetworkChecker detects and active internet
|
||||
// connection to avoid the corner case of initializing the web engine without
|
||||
// network connectivity. If the web engine is initialized without network connectivity
|
||||
// it won't restore the connectivity when it's available on Mac OS
|
||||
Item {
|
||||
id: root
|
||||
|
||||
required property url url
|
||||
required property var webChannelObjects
|
||||
|
||||
property alias active: loader.active
|
||||
// Used to control the loading of the web engine
|
||||
property bool active: false
|
||||
// Useful to monitor the loading state of the web engine (depends on active and internet connectivity)
|
||||
readonly property bool isActive: loader.active
|
||||
property alias instance: loader.item
|
||||
property bool waitForInternet: true
|
||||
|
||||
signal engineLoaded(WebEngineView instance)
|
||||
signal engineUnloaded()
|
||||
signal pageLoaded()
|
||||
signal pageLoadingError(string errorString)
|
||||
|
||||
Loader {
|
||||
id: loader
|
||||
Component {
|
||||
id: webEngineViewComponent
|
||||
|
||||
active: false
|
||||
|
||||
onStatusChanged: function() {
|
||||
if (status === Loader.Ready) {
|
||||
root.engineLoaded(loader.item)
|
||||
} else if (status === Loader.Null) {
|
||||
root.engineUnloaded()
|
||||
}
|
||||
}
|
||||
|
||||
sourceComponent: WebEngineView {
|
||||
WebEngineView {
|
||||
id: webEngineView
|
||||
|
||||
anchors.fill: parent
|
||||
|
@ -65,4 +66,35 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: loader
|
||||
|
||||
active: root.active && (!root.waitForInternet || (d.passedFirstTimeInitialization || networkChecker.isOnline))
|
||||
|
||||
onStatusChanged: function() {
|
||||
if (status === Loader.Ready) {
|
||||
root.engineLoaded(loader.item)
|
||||
d.passedFirstTimeInitialization = true
|
||||
} else if (status === Loader.Null) {
|
||||
root.engineUnloaded()
|
||||
}
|
||||
}
|
||||
|
||||
sourceComponent: webEngineViewComponent
|
||||
}
|
||||
|
||||
NetworkChecker {
|
||||
id: networkChecker
|
||||
|
||||
// Deactivate searching for network connectivity after the web engine is loaded
|
||||
active: !d.passedFirstTimeInitialization
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
// Used to hold the loading of the web engine until internet connectivity is available
|
||||
property bool passedFirstTimeInitialization: false
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
#include "StatusQ/networkchecker.h"
|
||||
|
||||
NetworkChecker::NetworkChecker(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
connect(&manager, &QNetworkAccessManager::finished, this, &NetworkChecker::onFinished);
|
||||
connect(&timer, &QTimer::timeout, this, &NetworkChecker::checkNetwork);
|
||||
|
||||
updateRegularCheck(active);
|
||||
}
|
||||
|
||||
bool NetworkChecker::isOnline() const
|
||||
{
|
||||
return online;
|
||||
}
|
||||
|
||||
void NetworkChecker::checkNetwork()
|
||||
{
|
||||
QNetworkRequest request(QUrl("https://fedoraproject.org/static/hotspot.txt"));
|
||||
manager.get(request);
|
||||
}
|
||||
|
||||
void NetworkChecker::onFinished(QNetworkReply* reply)
|
||||
{
|
||||
bool wasOnline = online;
|
||||
online = (reply->error() == QNetworkReply::NoError);
|
||||
reply->deleteLater();
|
||||
|
||||
if(wasOnline != online)
|
||||
{
|
||||
emit isOnlineChanged(online);
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkChecker::isActive() const
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
void NetworkChecker::setActive(bool active)
|
||||
{
|
||||
if(active == this->active) return;
|
||||
|
||||
this->active = active;
|
||||
emit activeChanged(active);
|
||||
|
||||
updateRegularCheck(active);
|
||||
}
|
||||
|
||||
void NetworkChecker::updateRegularCheck(bool active)
|
||||
{
|
||||
if(active)
|
||||
{
|
||||
checkNetwork();
|
||||
timer.start(checkInterval);
|
||||
}
|
||||
else
|
||||
{
|
||||
timer.stop();
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
#include "StatusQ/modelentry.h"
|
||||
#include "StatusQ/modelutilsinternal.h"
|
||||
#include "StatusQ/movablemodel.h"
|
||||
#include "StatusQ/networkchecker.h"
|
||||
#include "StatusQ/objectproxymodel.h"
|
||||
#include "StatusQ/permissionutilsinternal.h"
|
||||
#include "StatusQ/rolesrenamingmodel.h"
|
||||
|
@ -58,6 +59,7 @@ public:
|
|||
qmlRegisterType<SourceModel>("StatusQ", 0, 1, "SourceModel");
|
||||
qmlRegisterType<ConcatModel>("StatusQ", 0, 1, "ConcatModel");
|
||||
qmlRegisterType<MovableModel>("StatusQ", 0, 1, "MovableModel");
|
||||
qmlRegisterType<NetworkChecker>("StatusQ", 0, 1, "NetworkChecker");
|
||||
|
||||
qmlRegisterType<FastExpressionFilter>("StatusQ", 0, 1, "FastExpressionFilter");
|
||||
qmlRegisterType<FastExpressionRole>("StatusQ", 0, 1, "FastExpressionRole");
|
||||
|
|
|
@ -38,6 +38,8 @@ TestCase {
|
|||
sourceComponent: WebEngineLoader {
|
||||
url: "./WebEngineLoader/test.html"
|
||||
webChannelObjects: [testObject]
|
||||
|
||||
waitForInternet: false
|
||||
}
|
||||
}
|
||||
SignalSpy { id: loadedSpy; target: loader; signalName: "loaded" }
|
||||
|
@ -67,13 +69,13 @@ TestCase {
|
|||
compare(webEngine.instance, null, "By default the engine is not loaded")
|
||||
webEngine.active = true
|
||||
|
||||
webEngineLoadedSpy.wait(1000);
|
||||
webEngineLoadedSpy.wait(1000)
|
||||
verify(webEngine.instance !== null , "The WebEngineView should be available")
|
||||
|
||||
if (Qt.platform.os === "linux") {
|
||||
skip("fails to load page on linux")
|
||||
}
|
||||
pageLoadedSpy.wait(1000);
|
||||
pageLoadedSpy.wait(1000)
|
||||
webEngine.active = false
|
||||
engineUnloadedSpy.wait(1000);
|
||||
|
||||
|
|
|
@ -14,10 +14,10 @@ WalletConnectSDKBase {
|
|||
id: root
|
||||
|
||||
readonly property alias sdkReady: d.sdkReady
|
||||
readonly property alias webEngineLoader: loader
|
||||
|
||||
property alias active: loader.active
|
||||
property alias url: loader.url
|
||||
// Enable the WalletConnect SDK
|
||||
property alias enableSdk: loader.active
|
||||
readonly property alias url: loader.url
|
||||
|
||||
implicitWidth: 1
|
||||
implicitHeight: 1
|
||||
|
@ -81,15 +81,15 @@ WalletConnectSDKBase {
|
|||
function init() {
|
||||
console.debug(`WC WalletConnectSDK.wcCall.init; root.projectId: ${root.projectId}`)
|
||||
|
||||
d.engine.runJavaScript(`wc.init("${root.projectId}").catch((error) => {wc.statusObject.sdkInitialized("SDK init error: "+error);})`, function(result) {
|
||||
|
||||
console.debug(`WC WalletConnectSDK.wcCall.init; response: ${JSON.stringify(result)}`)
|
||||
|
||||
if (result && !!result.error)
|
||||
{
|
||||
console.error("init: ", result.error)
|
||||
}
|
||||
})
|
||||
d.engine.runJavaScript(`
|
||||
wc.init("${root.projectId}")
|
||||
.then(()=> {
|
||||
wc.statusObject.sdkInitialized("");
|
||||
})
|
||||
.catch((error) => {
|
||||
wc.statusObject.sdkInitialized("SDK init error: "+error)
|
||||
})
|
||||
`)
|
||||
}
|
||||
|
||||
function getPairings(callback) {
|
||||
|
@ -259,7 +259,7 @@ WalletConnectSDKBase {
|
|||
|
||||
WebChannel.id: "statusObject"
|
||||
|
||||
function bubbleConsoleMessage(type, message) {
|
||||
function echo(type, message) {
|
||||
if (type === "warn") {
|
||||
console.warn(message)
|
||||
} else if (type === "debug") {
|
||||
|
@ -272,7 +272,7 @@ WalletConnectSDKBase {
|
|||
}
|
||||
|
||||
function sdkInitialized(error) {
|
||||
console.debug(`WC WalletConnectSDK.sdkInitialized; error: ${error}`)
|
||||
console.debug(`WC WalletConnectSDK.sdkInitialized: ${!!error ? "error: " + error : "success"}`)
|
||||
d.sdkReady = !error
|
||||
root.sdkInit(d.sdkReady, error)
|
||||
}
|
||||
|
|
|
@ -54,8 +54,8 @@ function buildSupportedNamespacesFromModels(chainsModel, accountsModel, methods)
|
|||
}
|
||||
|
||||
function buildSupportedNamespaces(chainIds, addresses, methods) {
|
||||
var eipChainIds = []
|
||||
var eipAddresses = []
|
||||
let eipChainIds = []
|
||||
let eipAddresses = []
|
||||
for (let i = 0; i < chainIds.length; i++) {
|
||||
let chainId = chainIds[i]
|
||||
eipChainIds.push(`"eip155:${chainId}"`)
|
||||
|
@ -65,7 +65,13 @@ function buildSupportedNamespaces(chainIds, addresses, methods) {
|
|||
}
|
||||
let methodsStr = methods.map(method => `"${method}"`).join(',')
|
||||
return `{
|
||||
"eip155":{"chains": [${eipChainIds.join(',')}],"methods": [${methodsStr}],"events": ["accountsChanged", "chainChanged"],"accounts": [${eipAddresses.join(',')}]}}`
|
||||
"eip155":{
|
||||
"chains": [${eipChainIds.join(',')}],
|
||||
"methods": [${methodsStr}],
|
||||
"events": ["accountsChanged", "chainChanged"],
|
||||
"accounts": [${eipAddresses.join(',')}]
|
||||
}
|
||||
}`
|
||||
}
|
||||
|
||||
function validURI(uri) {
|
||||
|
|
|
@ -2191,7 +2191,7 @@ Item {
|
|||
id: walletConnectService
|
||||
|
||||
wcSDK: WalletConnectSDK {
|
||||
active: WalletStore.RootStore.walletSectionInst.walletReady
|
||||
enableSdk: WalletStore.RootStore.walletSectionInst.walletReady
|
||||
|
||||
projectId: WalletStore.RootStore.appSettings.walletConnectProjectID
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue