Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions ui/StatusQ/src/StatusQ/Core/Utils/SubscriptionBroker.qml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ QtObject {
}
}

const onDestructionHandler = () => {
if(!d.managedSubscriptions.hasOwnProperty(subscriptionId))
return

root.unsubscribed.disconnect(onUnsubscribedHandler) //object is destroyed, no need to listen to the signal anymore
unsubscribe(subscriptionId)
}

const onUnsubscribedHandler = (subscriptionId) => {
if(subscriptionId !== subscription.subscriptionId)
return
Expand All @@ -135,14 +143,6 @@ QtObject {
subscription.topicChanged.disconnect(onTopicChangeHandler)
}

const onDestructionHandler = () => {
if(!d.managedSubscriptions.hasOwnProperty(subscriptionId))
return

root.unsubscribed.disconnect(onUnsubscribedHandler) //object is destroyed, no need to listen to the signal anymore
unsubscribe(subscriptionId)
}

subscription.Component.onDestruction.connect(onDestructionHandler)
subscription.isReadyChanged.connect(onReadyChangeHandler)
subscription.topicChanged.connect(onTopicChangeHandler)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ QtObject {
}
}

const onDestructionHandler = () => {
if(!d.managedSubscriptions.hasOwnProperty(subscriptionId))
return

root.unsubscribed.disconnect(onUnsubscribedHandler) //object is destroyed, no need to listen to the signal anymore
unsubscribe(subscriptionId)
}

const onUnsubscribedHandler = (subscriptionId) => {
if(subscriptionId !== subscription.subscriptionId)
return
Expand All @@ -125,14 +133,6 @@ QtObject {
subscription.topicChanged.disconnect(onTopicChangeHandler)
}

const onDestructionHandler = () => {
if(!d.managedSubscriptions.hasOwnProperty(subscriptionId))
return

root.unsubscribed.disconnect(onUnsubscribedHandler) //object is destroyed, no need to listen to the signal anymore
unsubscribe(subscriptionId)
}

subscription.Component.onDestruction.connect(onDestructionHandler)
subscription.isReadyChanged.connect(onReadyChangeHandler)
subscription.topicChanged.connect(onTopicChangeHandler)
Expand Down
64 changes: 31 additions & 33 deletions ui/app/AppLayouts/Browser/BrowserLayout.qml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import shared.stores.send

import AppLayouts.Browser.stores as BrowserStores

import "provider/qml"
import "popups"
import "controls"
import "views"
Expand All @@ -33,14 +34,12 @@ StatusSectionLayout {
required property bool thirdpartyServicesEnabled

required property TransactionStore transactionStore
required property var assetsStore
required property var currencyStore
required property var tokensStore

required property BrowserStores.BookmarksStore bookmarksStore
required property BrowserStores.DownloadsStore downloadsStore
required property BrowserStores.BrowserRootStore browserRootStore
required property BrowserStores.BrowserWalletStore browserWalletStore
required property var connectorController

signal sendToRecipientRequested(string address)

Expand All @@ -49,6 +48,22 @@ StatusSectionLayout {
tab.url = _internal.determineRealURL(url)
}

ConnectorBridge {
id: connectorBridge

userUID: root.userUID
connectorController: root.connectorController
defaultAccountAddress: root.browserWalletStore.dappBrowserAccount.address
accountsModel: root.browserWalletStore.accounts
httpUserAgent: {
if (localAccountSensitiveSettings.compatibilityMode) {
// Google doesn't let you connect if the user agent is Chrome-ish and doesn't satisfy some sort of hidden requirement
return "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36"
}
return ""
}
}

QtObject {
id: _internal

Expand Down Expand Up @@ -91,32 +106,13 @@ StatusSectionLayout {
standardButtons: Dialog.Ok
}

property QtObject defaultProfile: WebEngineProfile {
storageName: "Profile_%1".arg(root.userUID)
offTheRecord: false
httpUserAgent: {
if (localAccountSensitiveSettings.compatibilityMode) {
// Google doesn't let you connect if the user agent is Chrome-ish and doesn't satisfy some sort of hidden requirement
return "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36"
}
return ""
}
}

property QtObject otrProfile: WebEngineProfile {
storageName: "IncognitoProfile_%1".arg(root.userUID)
offTheRecord: true
persistentCookiesPolicy: WebEngineProfile.NoPersistentCookies
httpUserAgent: _internal.defaultProfile.httpUserAgent
}

function addNewDownloadTab() {
tabs.createDownloadTab(tabs.count !== 0 ? currentWebView.profile : defaultProfile);
tabs.createDownloadTab(tabs.count !== 0 ? currentWebView.profile : connectorBridge.defaultProfile);
tabs.currentIndex = tabs.count - 1;
}

function addNewTab() {
var tab = tabs.createEmptyTab(tabs.count !== 0 ? currentWebView.profile : defaultProfile);
var tab = tabs.createEmptyTab(tabs.count !== 0 ? currentWebView.profile : connectorBridge.defaultProfile);
browserHeader.addressBar.forceActiveFocus();
browserHeader.addressBar.selectAll();

Expand Down Expand Up @@ -218,9 +214,9 @@ StatusSectionLayout {
}
onOpenNewTabTriggered: _internal.addNewTab()
Component.onCompleted: {
_internal.defaultProfile.downloadRequested.connect(_internal.onDownloadRequested);
_internal.otrProfile.downloadRequested.connect(_internal.onDownloadRequested);
var tab = createEmptyTab(_internal.defaultProfile, true);
connectorBridge.defaultProfile.downloadRequested.connect(_internal.onDownloadRequested);
connectorBridge.otrProfile.downloadRequested.connect(_internal.onDownloadRequested);
var tab = createEmptyTab(connectorBridge.defaultProfile, true);
// For Devs: Uncomment the next line if you want to use the simpledapp on first load
// tab.url = root.browserRootStore.determineRealURL("https://simpledapp.eth");
}
Expand Down Expand Up @@ -312,11 +308,11 @@ StatusSectionLayout {
id: settingsMenu
x: parent.width - width
y: browserHeader.y + browserHeader.height
isIncognito: _internal.currentWebView && _internal.currentWebView.profile === _internal.otrProfile
isIncognito: _internal.currentWebView && _internal.currentWebView.profile === connectorBridge.otrProfile
onAddNewTab: _internal.addNewTab()
onGoIncognito: function (checked) {
if (_internal.currentWebView) {
_internal.currentWebView.profile = checked ? _internal.otrProfile : _internal.defaultProfile;
_internal.currentWebView.profile = checked ? connectorBridge.otrProfile : connectorBridge.defaultProfile;
}
}
onZoomIn: {
Expand Down Expand Up @@ -352,9 +348,6 @@ StatusSectionLayout {
Component {
id: browserWalletMenu
BrowserWalletMenu {
assetsStore: root.assetsStore
currencyStore: root.currencyStore
tokensStore: root.tokensStore
currentTabConnected: root.browserRootStore.currentTabConnected
browserWalletStore: root.browserWalletStore
property point headerPoint: Qt.point(browserHeader.x, browserHeader.y)
Expand Down Expand Up @@ -455,7 +448,7 @@ StatusSectionLayout {
bookmarksStore: root.bookmarksStore
downloadsStore: root.downloadsStore
currentWebView: _internal.currentWebView
webChannel: channel
webChannel: connectorBridge.webChannel
findBarComp: findBar
favMenu: favoriteMenu
addFavModal: addFavoriteModal
Expand Down Expand Up @@ -542,6 +535,11 @@ StatusSectionLayout {
function onUrlChanged() {
browserHeader.addressBar.text = root.browserRootStore.obtainAddress(_internal.currentWebView.url)
root.browserRootStore.currentTabConnected = false // TODO: Will be handled by connector

// Update ConnectorBridge with current dApp metadata
if (_internal.currentWebView && _internal.currentWebView.url) {
connectorBridge.updateDAppUrl(_internal.currentWebView.url, _internal.currentWebView.title)
}
}
}

Expand Down
45 changes: 5 additions & 40 deletions ui/app/AppLayouts/Browser/popups/BrowserWalletMenu.qml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ import AppLayouts.Browser.stores as BrowserStores
Dialog {
id: root

required property var assetsStore
required property var currencyStore
required property var tokensStore

required property bool currentTabConnected
required property BrowserStores.BrowserWalletStore browserWalletStore

Expand Down Expand Up @@ -193,42 +189,11 @@ Dialog {
anchors.topMargin: Theme.bigPadding
anchors.bottom: parent.bottom

StatusTabBar {
id: walletTabBar
width: parent.width
anchors.top: parent.top

StatusTabButton {
id: assetBtn
width: implicitWidth
text: qsTr("Assets")
}
StatusTabButton {
id: historyBtn
width: implicitWidth
text: qsTr("History")
}
}

StackLayout {
id: stackLayout
width: parent.width
anchors.top: walletTabBar.bottom
anchors.topMargin: Theme.bigPadding
anchors.bottom: parent.bottom
currentIndex: walletTabBar.currentIndex

// FIXME integrate
// AssetsView {
// id: assetsTab
// controller: root.assetsStore.assetsController
// currencyStore: root.currencyStore
// tokensStore: root.tokensStore
// }
HistoryView {
id: historyTab
overview: root.browserWalletStore.dappBrowserAccount
}
// TODO: Add Assets and History tabs when ready
StatusBaseText {
anchors.centerIn: parent
text: qsTr("Wallet info will appear here")
color: Theme.palette.baseColor1
}
}
onClosed: {
Expand Down
25 changes: 11 additions & 14 deletions ui/app/AppLayouts/Browser/provider/qml/ConnectorBridge.qml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ import QtWebChannel

import StatusQ.Core.Theme
import utils

import "Utils.js" as Utils

/**
* ConnectorBridge
*
*
* Simplified connector infrastructure for BrowserLayout.
* Provides WebEngine profiles with script injection, WebChannel,
* Provides WebEngine profiles with script injection, WebChannel,
* ConnectorManager, and direct connection to Nim backend.
*
*
* This component bridges the Browser UI with the Connector backend system.
*/
Item {
Expand All @@ -29,15 +28,15 @@ Item {
readonly property alias webChannel: channel
readonly property alias defaultProfile: defaultProfile
readonly property alias otrProfile: otrProfile

readonly property alias manager: connectorManager

property alias dappUrl: connectorManager.dappUrl
property alias dappOrigin: connectorManager.dappOrigin
property alias dappName: connectorManager.dappName
property alias dappIconUrl: connectorManager.dappIconUrl
property alias clientId: connectorManager.clientId

function hasWalletConnected(hostname, address) {
if (!connectorController) return false

Expand All @@ -59,10 +58,10 @@ Item {
if (!connectorController) return false
return connectorController.disconnect(hostname)
}

function updateDAppUrl(url, name) {
if (!url) return

const urlStr = url.toString()
connectorManager.dappUrl = urlStr
connectorManager.dappOrigin = Utils.normalizeOrigin(urlStr)
Expand Down Expand Up @@ -107,7 +106,7 @@ Item {
ConnectorManager {
id: connectorManager
connectorController: root.connectorController // (shared_modules/connector/controller.nim)

dappUrl: ""
dappOrigin: ""
dappName: ""
Expand All @@ -134,16 +133,14 @@ Item {
Eip1193ProviderAdapter {
id: eip1193ProviderAdapter
WebChannel.id: "ethereumProvider"

chainId: "0x" + connectorManager.dappChainId.toString(16) // Convert decimal to hex
networkVersion: connectorManager.dappChainId.toString()
selectedAddress: connectorManager.accounts.length > 0 ? connectorManager.accounts[0] : ""
accounts: connectorManager.accounts
connected: connectorManager.connected

function request(args) {
return connectorManager.request(args)
}
onRequestInternal: (args) => connectorManager.request(args)
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,32 @@ import QtQuick 2.15

QtObject {
id: root

// ============================================================================
// EIP-1193 PUBLIC PROPERTIES (exposed to JS via WebChannel)
// ============================================================================

// EIP-1193 PUBLIC PROPERTIES
readonly property bool isStatus: true
readonly property bool isMetaMask: false
property string chainId: "0x1" // hex format for EIP-1193
property string networkVersion: "1" // decimal format (deprecated but used by some dApps)
property string selectedAddress: "" // current active address
property var accounts: []
property bool connected: false

// ============================================================================

// EIP-1193 EVENTS (for WebChannel)
// ============================================================================

signal connectEvent(var info)
signal disconnectEvent(var error)
signal accountsChangedEvent(var accounts)
signal chainChangedEvent(string chainId)
signal messageEvent(var message)
signal requestCompletedEvent(var payload)
signal requestInternal(var args)

// Internal
signal providerStateChanged() // re-read State

// ============================================================================

// EIP-1193 REQUEST METHOD STUB
// ============================================================================
function request(args) {
console.error("[Eip1193ProviderAdapter] request() not injected - should be overridden by ConnectorBridge")
return JSON.stringify({
jsonrpc: "2.0",
id: args && args.requestId || 0,
error: { code: -32603, message: "Request function not properly injected" }
})
requestInternal(args)
// Return immediately - async response comes via requestCompletedEvent
return { jsonrpc: "2.0", id: args.requestId || 0, result: null }
}
}
Loading