2020-09-22 15:12:48 +00:00
import QtQuick 2.13
2020-09-28 18:33:37 +00:00
import QtQuick . Controls 2.13
2020-09-22 15:12:48 +00:00
import QtQuick . Layouts 1.13
2020-09-22 19:16:44 +00:00
import QtWebEngine 1.10
import QtWebChannel 1.13
2020-09-28 18:33:37 +00:00
import Qt . labs . settings 1.0
import QtQuick . Controls . Styles 1.0
import QtQuick . Dialogs 1.2
2021-09-30 09:43:29 +00:00
2021-09-28 15:04:06 +00:00
import utils 1.0
2021-10-27 21:27:49 +00:00
import shared . controls 1.0
2021-09-30 09:43:29 +00:00
2021-10-27 21:27:49 +00:00
import shared 1.0
import shared . status 1.0
2021-10-01 15:58:36 +00:00
2021-09-30 09:43:29 +00:00
import "popups"
import "controls"
import "views"
import "panels"
import "stores"
2021-10-01 15:58:36 +00:00
import "../Chat/popups"
2020-09-22 15:12:48 +00:00
2020-09-28 18:33:37 +00:00
// Code based on https://code.qt.io/cgit/qt/qtwebengine.git/tree/examples/webengine/quicknanobrowser/BrowserWindow.qml?h=5.15
// Licensed under BSD
2020-10-08 18:08:50 +00:00
Rectangle {
2020-09-28 18:33:37 +00:00
id: browserWindow
2021-10-22 20:49:47 +00:00
property var globalStore
2020-09-28 18:33:37 +00:00
property Item currentWebView: tabs . currentIndex < tabs . count ? tabs . getTab ( tabs . currentIndex ) . item : null
2020-10-22 17:34:14 +00:00
2020-09-28 18:33:37 +00:00
property Component browserDialogComponent: BrowserDialog {
onClosing: destroy ( )
}
2020-11-16 16:44:23 +00:00
property Component jsDialogComponent: JSDialogWindow { }
2020-10-19 20:26:16 +00:00
property bool currentTabConnected: false
2020-09-28 18:33:37 +00:00
2020-10-19 19:00:43 +00:00
property Component accessDialogComponent: BrowserConnectionModal {
currentTab: tabs . getTab ( tabs . currentIndex ) && tabs . getTab ( tabs . currentIndex ) . item
x: browserWindow . width - width - Style . current . halfPadding
y: browserHeader . y + browserHeader . height + Style . current . halfPadding
2020-09-25 19:05:07 +00:00
}
2020-10-02 17:23:33 +00:00
// TODO we'll need a new dialog at one point because this one is not using the same call, but it's good for now
2021-10-22 20:49:47 +00:00
property Component sendTransactionModalComponent: SignTransactionModal {
store: browserWindow . globalStore
}
2020-09-25 19:05:07 +00:00
2020-10-05 16:24:43 +00:00
property Component signMessageModalComponent: SignMessageModal { }
2020-10-02 17:23:33 +00:00
property MessageDialog sendingError: MessageDialog {
id: sendingError
//% "Error sending the transaction"
title: qsTrId ( "error-sending-the-transaction" )
icon: StandardIcon . Critical
standardButtons: StandardButton . Ok
}
2020-10-02 17:30:27 +00:00
2020-10-05 16:24:43 +00:00
property MessageDialog signingError: MessageDialog {
id: signingError
2021-02-18 16:36:05 +00:00
//% "Error signing message"
title: qsTrId ( "error-signing-message" )
2020-10-05 16:24:43 +00:00
icon: StandardIcon . Critical
standardButtons: StandardButton . Ok
}
2020-09-28 18:33:37 +00:00
property QtObject defaultProfile: WebEngineProfile {
storageName: "Profile"
offTheRecord: false
2020-10-20 20:24:41 +00:00
httpUserAgent: {
2020-10-21 16:50:21 +00:00
if ( appSettings . compatibilityMode ) {
2020-10-20 20:24:41 +00:00
// 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; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0"
}
return ""
}
2020-09-28 18:33:37 +00:00
useForGlobalCertificateVerification: true
userScripts: [
WebEngineScript {
injectionPoint: WebEngineScript . DocumentCreation
2021-10-25 20:29:36 +00:00
sourceUrl: Qt . resolvedUrl ( "./helpers/provider.js" )
2021-09-30 09:43:29 +00:00
worldId: WebEngineScript . MainWorld // TODO: check https://doc.qt.io/qt-5/qml-qtwebengine-webenginescript.html#worldId-prop
2020-09-28 18:33:37 +00:00
}
]
}
property QtObject otrProfile: WebEngineProfile {
offTheRecord: true
persistentCookiesPolicy: WebEngineProfile . NoPersistentCookies
2020-10-07 19:28:45 +00:00
httpUserAgent: defaultProfile . httpUserAgent
2020-09-28 18:33:37 +00:00
userScripts: [
WebEngineScript {
injectionPoint: WebEngineScript . DocumentCreation
2021-10-25 20:29:36 +00:00
sourceUrl: Qt . resolvedUrl ( "./helpers/provider.js" )
2021-09-30 09:43:29 +00:00
worldId: WebEngineScript . MainWorld // TODO: check https://doc.qt.io/qt-5/qml-qtwebengine-webenginescript.html#worldId-prop
2020-09-28 18:33:37 +00:00
}
]
}
2021-09-30 09:43:29 +00:00
function openUrlInNewTab ( url ) {
browserWindow . addNewTab ( )
determineRealURL ( url )
2020-09-28 18:33:37 +00:00
}
2020-11-20 12:45:41 +00:00
function addNewDownloadTab ( ) {
tabs . createDownloadTab ( tabs . count !== 0 ? currentWebView.profile : defaultProfile ) ;
tabs . currentIndex = tabs . count - 1 ;
}
2020-10-08 18:36:44 +00:00
function addNewTab ( ) {
2020-10-21 19:55:40 +00:00
tabs . createEmptyTab ( tabs . count !== 0 ? currentWebView.profile : defaultProfile ) ;
2020-10-08 18:36:44 +00:00
tabs . currentIndex = tabs . count - 1 ;
browserHeader . addressBar . forceActiveFocus ( ) ;
browserHeader . addressBar . selectAll ( ) ;
}
2021-09-30 09:43:29 +00:00
function onDownloadRequested ( download ) {
downloadBar . isVisible = true
download . accept ( ) ;
DownloadsStore . addDownload ( download )
2021-04-20 12:09:53 +00:00
}
2021-09-30 09:43:29 +00:00
function determineRealURL ( url ) {
return Web3ProviderStore . determineRealURL ( url )
2020-09-28 18:33:37 +00:00
}
2021-09-30 09:43:29 +00:00
onCurrentWebViewChanged: {
findBar . reset ( ) ;
browserHeader . addressBar . text = Web3ProviderStore . obtainAddress ( currentWebView . url )
2020-09-28 18:33:37 +00:00
}
2020-10-09 17:56:42 +00:00
2021-09-30 09:43:29 +00:00
Layout.fillHeight: true
Layout.fillWidth: true
color: Style . current . inputBackground
border.width: 0
2020-09-28 18:33:37 +00:00
2021-09-30 09:43:29 +00:00
WebProviderObj { id: provider }
BrowserShortcutActions {
id: keyboardShortcutActions
2020-09-28 18:33:37 +00:00
}
2021-09-30 09:43:29 +00:00
WebChannel {
id: channel
registeredObjects: [ provider ]
2020-09-28 18:33:37 +00:00
}
2020-10-07 20:14:55 +00:00
BrowserHeader {
id: browserHeader
2020-10-08 18:08:50 +00:00
anchors.top: parent . top
anchors.topMargin: tabs . tabHeight + tabs . anchors . topMargin
z: 52
2020-10-09 17:56:42 +00:00
addNewTab: browserWindow . addNewTab
2021-09-30 09:43:29 +00:00
favoriteComponent: favoritesBar
currentFavorite: currentWebView && BookmarksStore . getCurrentFavorite ( currentWebView . url )
dappBrowserAccName: WalletStore . dappBrowserAccount . name
dappBrowserAccIcon: WalletStore . dappBrowserAccount . iconColor
onAddNewFavoritelClicked: {
if ( ! browserHeader . currentFavorite ) {
// remove "add favorite" button at the end, add new bookmark, add "add favorite" button back
2021-10-14 14:29:33 +00:00
BookmarksStore . deleteBookmark ( "" )
2021-09-30 09:43:29 +00:00
BookmarksStore . addBookmark ( currentWebView . url , currentWebView . title )
BookmarksStore . addBookmark ( "" , qsTr ( "Add Favorite" ) )
2021-08-17 17:03:03 +00:00
}
2021-09-30 09:43:29 +00:00
addFavoriteModal . modifiyModal = true
addFavoriteModal . toolbarMode = true
addFavoriteModal . x = xPos - 30
addFavoriteModal . y = browserHeader . y + browserHeader . height + 4
addFavoriteModal . ogUrl = browserHeader . currentFavorite ? browserHeader.currentFavorite.url : currentWebView . url
addFavoriteModal . ogName = browserHeader . currentFavorite ? browserHeader.currentFavorite.name : currentWebView . title
addFavoriteModal . open ( )
2020-09-28 18:33:37 +00:00
}
2021-09-30 09:43:29 +00:00
}
2020-09-28 18:33:37 +00:00
2021-09-30 09:43:29 +00:00
BrowserTabView {
id: tabs
2020-10-08 18:08:50 +00:00
anchors.top: parent . top
anchors.topMargin: Style . current . halfPadding
2020-09-28 18:33:37 +00:00
anchors.bottom: devToolsView . top
2020-10-08 20:13:14 +00:00
anchors.bottomMargin: browserHeader . height
2020-09-28 18:33:37 +00:00
anchors.left: parent . left
anchors.right: parent . right
2021-09-30 09:43:29 +00:00
z: 50
tabComponent: webEngineView
2020-10-20 13:54:47 +00:00
}
2020-09-28 18:33:37 +00:00
ProgressBar {
id: progressBar
height: 3
from: 0
to: 100
visible: value != 0 && value != 100
value: ( currentWebView && currentWebView . loadProgress < 100 ) ? currentWebView.loadProgress : 0
anchors.bottom: parent . bottom
anchors.bottomMargin: Style . current . padding
anchors.right: parent . right
anchors.rightMargin: Style . current . padding
}
2020-09-22 19:16:44 +00:00
WebEngineView {
2020-09-28 18:33:37 +00:00
id: devToolsView
2020-10-21 14:49:13 +00:00
visible: appSettings . devToolsEnabled
2020-09-28 18:33:37 +00:00
height: visible ? 400 : 0
inspectedView: visible && tabs . currentIndex < tabs . count ? tabs . getTab ( tabs . currentIndex ) . item : null
anchors.left: parent . left
anchors.right: parent . right
anchors.bottom: parent . bottom
2020-09-22 19:16:44 +00:00
onNewViewRequested: function ( request ) {
2020-09-28 18:33:37 +00:00
var tab = tabs . createEmptyTab ( currentWebView . profile ) ;
tabs . currentIndex = tabs . count - 1 ;
request . openIn ( tab . item ) ;
}
2020-11-19 19:57:37 +00:00
z: 100
2020-09-28 18:33:37 +00:00
}
2021-09-30 09:43:29 +00:00
AddFavoriteModal {
id: addFavoriteModal
}
FavoriteMenu {
id: favoriteMenu
openInNewTab: function ( url ) {
browserWindow . openUrlInNewTab ( url )
}
2020-10-19 20:16:02 +00:00
}
2020-09-28 18:33:37 +00:00
MessageDialog {
id: sslDialog
property var certErrors: [ ]
icon: StandardIcon . Warning
standardButtons: StandardButton . No | StandardButton . Yes
2021-02-18 16:36:05 +00:00
//% "Server's certificate not trusted"
title: qsTrId ( "server-s-certificate-not-trusted" )
//% "Do you wish to continue?"
text: qsTrId ( "do-you-wish-to-continue-" )
//% "If you wish so, you may continue with an unverified certificate. Accepting an unverified certificate means you may not be connected with the host you tried to connect to.\nDo you wish to override the security check and continue?"
detailedText: qsTrId ( "if-you-wish-so--you-may-continue-with-an-unverified-certificate--accepting-an-unverified-certificate-means-you-may-not-be-connected-with-the-host-you-tried-to-connect-to--ndo-you-wish-to-override-the-security-check-and-continue-" )
2020-09-28 18:33:37 +00:00
onYes: {
certErrors . shift ( ) . ignoreCertificateError ( ) ;
presentError ( ) ;
}
onNo: reject ( )
onRejected: reject ( )
function reject ( ) {
certErrors . shift ( ) . rejectCertificate ( ) ;
presentError ( ) ;
}
function enqueue ( error ) {
certErrors . push ( error ) ;
presentError ( ) ;
}
function presentError ( ) {
visible = certErrors . length > 0
}
}
2020-10-22 17:34:14 +00:00
DownloadBar {
id: downloadBar
anchors.bottom: parent . bottom
z: 60
2021-09-30 09:43:29 +00:00
downloadsModel: DownloadsStore . downloadModel
onOpenDownloadClicked: {
if ( downloadComplete ) {
return DownloadsStore . openFile ( index )
}
DownloadsStore . openDirectory ( index )
}
2020-10-22 17:34:14 +00:00
}
2020-09-28 18:33:37 +00:00
FindBar {
id: findBar
visible: false
anchors.right: parent . right
2020-10-09 17:56:42 +00:00
anchors.top: browserHeader . bottom
z: 60
2020-09-28 18:33:37 +00:00
onFindNext: {
if ( text )
currentWebView && currentWebView . findText ( text ) ;
else if ( ! visible )
visible = true ;
}
onFindPrevious: {
if ( text )
currentWebView && currentWebView . findText ( text , WebEngineView . FindBackward ) ;
else if ( ! visible )
visible = true ;
}
}
Rectangle {
id: statusBubble
color: "oldlace"
property int padding: 8
visible: false
anchors.left: parent . left
anchors.bottom: parent . bottom
width: statusText . paintedWidth + padding
height: statusText . paintedHeight + padding
Text {
id: statusText
anchors.centerIn: statusBubble
elide: Qt . ElideMiddle
Timer {
id: hideStatusText
interval: 750
onTriggered: {
statusText . text = "" ;
statusBubble . visible = false ;
}
}
2020-09-22 19:16:44 +00:00
}
2020-09-22 15:12:48 +00:00
}
2021-09-30 09:43:29 +00:00
DownloadMenu {
id: downloadMenu
}
Component {
id: favoritesBar
FavoritesBar {
bookmarkModel: BookmarksStore . bookmarksModel
}
}
Component {
id: webEngineView
BrowserWebEngineView { }
}
Connections {
target: currentWebView
onUrlChanged: {
browserHeader . addressBar . text = Web3ProviderStore . obtainAddress ( currentWebView . url )
}
}
Connections {
2021-10-14 14:29:33 +00:00
target: BookmarksStore . bookmarksModel
onModelChanged: {
2021-09-30 09:43:29 +00:00
browserHeader . currentFavorite = Qt . binding ( function ( ) { return BookmarksStore . getCurrentFavorite ( currentWebView . url ) } )
}
}
2020-09-22 15:12:48 +00:00
}