diff --git a/cmd/mist/assets/backButtonDisabled.png b/cmd/mist/assets/backButtonDisabled.png new file mode 100644 index 000000000..428747870 Binary files /dev/null and b/cmd/mist/assets/backButtonDisabled.png differ diff --git a/cmd/mist/assets/backButtonDisabled@2x.png b/cmd/mist/assets/backButtonDisabled@2x.png new file mode 100644 index 000000000..0eaa6daa5 Binary files /dev/null and b/cmd/mist/assets/backButtonDisabled@2x.png differ diff --git a/cmd/mist/assets/backButtonHover.png b/cmd/mist/assets/backButtonHover.png new file mode 100644 index 000000000..8c5226f5a Binary files /dev/null and b/cmd/mist/assets/backButtonHover.png differ diff --git a/cmd/mist/assets/backButtonHover@2x.png b/cmd/mist/assets/backButtonHover@2x.png new file mode 100644 index 000000000..406601ebc Binary files /dev/null and b/cmd/mist/assets/backButtonHover@2x.png differ diff --git a/cmd/mist/assets/browser.png b/cmd/mist/assets/browser.png index 7b3b0870c..074c9ae3c 100644 Binary files a/cmd/mist/assets/browser.png and b/cmd/mist/assets/browser.png differ diff --git a/cmd/mist/assets/browser@2x.png b/cmd/mist/assets/browser@2x.png new file mode 100644 index 000000000..8ca417608 Binary files /dev/null and b/cmd/mist/assets/browser@2x.png differ diff --git a/cmd/mist/assets/ext/mist.js b/cmd/mist/assets/ext/mist.js new file mode 100644 index 000000000..8734f8dc7 --- /dev/null +++ b/cmd/mist/assets/ext/mist.js @@ -0,0 +1,35 @@ +// Copyright (c) 2015, ETHDEV. All rights reserved. +// +// This library 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 2.1 of the License, or (at your option) any later version. +// +// This library 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 this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301 USA + +// this function is included locally, but you can also include separately via a header definition + +console.log("loaded?"); + +document.onkeydown = function(evt) { + evt = evt || window.event; + if (evt.ctrlKey && evt.keyCode == 67) { + window.document.execCommand("copy"); + console.log("Ctrl-C"); + } else if (evt.ctrlKey && evt.keyCode == 88) { + window.document.execCommand("cut"); + console.log("Ctrl-X"); + } if (evt.ctrlKey && evt.keyCode == 86) { + console.log("Ctrl-V"); + } if (evt.ctrlKey && evt.keyCode == 90) { + console.log("Ctrl-Z"); + } +}; \ No newline at end of file diff --git a/cmd/mist/assets/miner.png b/cmd/mist/assets/miner.png deleted file mode 100644 index 58e3f4dfe..000000000 Binary files a/cmd/mist/assets/miner.png and /dev/null differ diff --git a/cmd/mist/assets/mining-icon.png b/cmd/mist/assets/mining-icon.png new file mode 100644 index 000000000..db611e5c0 Binary files /dev/null and b/cmd/mist/assets/mining-icon.png differ diff --git a/cmd/mist/assets/mining-icon@2x.png b/cmd/mist/assets/mining-icon@2x.png new file mode 100644 index 000000000..16466d338 Binary files /dev/null and b/cmd/mist/assets/mining-icon@2x.png differ diff --git a/cmd/mist/assets/qml/main.qml b/cmd/mist/assets/qml/main.qml index e1e6a028f..9a6bf5273 100644 --- a/cmd/mist/assets/qml/main.qml +++ b/cmd/mist/assets/qml/main.qml @@ -40,10 +40,14 @@ ApplicationWindow { // Takes care of loading all default plugins Component.onCompleted: { - catalog = addPlugin("./views/catalog.qml", {noAdd: true, close: false, section: "begin"}); - var wallet = addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "ethereum", active: true}); + catalog = addPlugin("./views/catalog.qml", {noAdd: true, close: false, section: "begin", active: true}); - addPlugin("./views/miner.qml", {noAdd: true, close: false, section: "ethereum", active: true}); + var walletWeb = addPlugin("./views/browser.qml", {noAdd: true, close: false, section: "ethereum", active: false}); + walletWeb.view.url = "http://ethereum-dapp-wallet.meteor.com/"; + walletWeb.menuItem.title = "Wallet"; + + addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "legacy"}); + addPlugin("./views/miner.qml", {noAdd: true, close: false, section: "ethereum", active: false}); addPlugin("./views/transaction.qml", {noAdd: true, close: false, section: "legacy"}); addPlugin("./views/whisper.qml", {noAdd: true, close: false, section: "legacy"}); addPlugin("./views/chain.qml", {noAdd: true, close: false, section: "legacy"}); @@ -60,13 +64,14 @@ ApplicationWindow { function activeView(view, menuItem) { mainSplit.setView(view, menuItem) - if (view.hideUrl) { - //urlPane.visible = false; - //mainView.anchors.top = rootView.top + /*if (view.hideUrl) { + urlPane.visible = false; + mainView.anchors.top = rootView.top } else { - //urlPane.visible = true; - //mainView.anchors.top = divider.bottom - } + urlPane.visible = true; + mainView.anchors.top = divider.bottom + }*/ + } function addViews(view, path, options) { @@ -121,13 +126,10 @@ ApplicationWindow { var domainAlreadyOpen = false; - console.log("requested: " + requestedDomain ) - for(var i = 0; i < mainSplit.views.length; i++) { if (mainSplit.views[i].view.url) { var matches = mainSplit.views[i].view.url.toString().match(/^[a-z]*\:\/\/(?:www\.)?([^\/?#]+)(?:[\/?#]|$)/i); var existingDomain = matches && matches[1]; - console.log("exists: " + existingDomain); if (requestedDomain == existingDomain) { domainAlreadyOpen = true; mainSplit.views[i].view.url = url; @@ -247,79 +249,6 @@ ApplicationWindow { } } - statusBar: StatusBar { - //height: 32 - visible: false - - id: statusBar - Label { - //y: 6 - id: walletValueLabel - - font.pixelSize: 10 - styleColor: "#797979" - } - - /* - Label { - //y: 6 - objectName: "miningLabel" - visible: true - font.pixelSize: 10 - anchors.right: lastBlockLabel.left - anchors.rightMargin: 5 - } - - Label { - id: lastBlockLabel - objectName: "lastBlockLabel" - visible: true - text: "---" - font.pixelSize: 10 - anchors.right: peerGroup.left - anchors.rightMargin: 5 - } - */ - - ProgressBar { - visible: false - id: downloadIndicator - value: 0 - objectName: "downloadIndicator" - y: -4 - x: statusBar.width / 2 - this.width / 2 - width: 160 - } - - Label { - visible: false - objectName: "downloadLabel" - //y: 7 - anchors.left: downloadIndicator.right - anchors.leftMargin: 5 - font.pixelSize: 10 - text: "0 / 0" - } - - - RowLayout { - id: peerGroup - //y: 7 - anchors.right: parent.right - MouseArea { - onDoubleClicked: peerWindow.visible = true - anchors.fill: parent - } - - Label { - id: peerCounterLabel - font.pixelSize: 10 - text: "0 / 0" - } - } - } - - property var blockModel: ListModel { id: blockModel } @@ -445,10 +374,14 @@ ApplicationWindow { property var view; property var path; property var closable; + property var badgeContent; property alias title: label.text property alias icon: icon.source property alias secondaryTitle: secondary.text + property alias badgeNumber: badgeNumberLabel.text + property alias badgeIcon: badgeIconLabel.text + function setSelection(on) { sel.visible = on @@ -462,7 +395,7 @@ ApplicationWindow { label.visible = !on buttonLabel.visible = on } - + width: 192 height: 55 color: "#00000000" @@ -541,7 +474,6 @@ ApplicationWindow { if (parent.closable == true) { closeIcon.visible = sel.visible } - } onExited: { closeIcon.visible = false @@ -550,8 +482,8 @@ ApplicationWindow { Image { id: icon - height: 24 - width: 24 + height: 28 + width: 28 anchors { left: parent.left verticalCenter: parent.verticalCenter @@ -574,18 +506,24 @@ ApplicationWindow { id: label font.family: sourceSansPro.name font.weight: Font.DemiBold - anchors { - left: icon.right - verticalCenter: parent.verticalCenter - leftMargin: 6 - // verticalCenterOffset: -10 - } + elide: Text.ElideRight x:250 color: "#665F5F" font.pixelSize: 14 - } + anchors { + left: icon.right + right: parent.right + verticalCenter: parent.verticalCenter + leftMargin: 6 + rightMargin: 8 + verticalCenterOffset: (secondaryTitle == "") ? 0 : -10; + } + + + } + Text { id: secondary font.family: sourceSansPro.name @@ -604,7 +542,7 @@ ApplicationWindow { visible: false width: 10 height: 10 - color: "#FFFFFF" + color: "#FAFAFA" anchors { fill: icon } @@ -623,9 +561,49 @@ ApplicationWindow { centerIn: parent } color: "#665F5F" - font.pixelSize: 18 + font.pixelSize: 20 text: "\ue082" } + } + + Rectangle { + id: badge + visible: (badgeContent == "icon" || badgeContent == "number" )? true : false + width: 32 + color: "#05000000" + anchors { + right: parent.right; + top: parent.top; + bottom: parent.bottom; + rightMargin: 4; + } + + Text { + id: badgeIconLabel + visible: (badgeContent == "icon") ? true : false; + font.family: simpleLineIcons.name + anchors { + centerIn: parent + } + horizontalAlignment: Text.AlignCenter + color: "#AAA0A0" + font.pixelSize: 20 + text: badgeIcon + } + + Text { + id: badgeNumberLabel + visible: (badgeContent == "number") ? true : false; + anchors { + centerIn: parent + } + horizontalAlignment: Text.AlignCenter + font.family: sourceSansPro.name + font.weight: Font.Light + color: "#AAA0A0" + font.pixelSize: 18 + text: badgeNumber + } } diff --git a/cmd/mist/assets/qml/views/browser.qml b/cmd/mist/assets/qml/views/browser.qml index 631ef5a16..54f5d755e 100644 --- a/cmd/mist/assets/qml/views/browser.qml +++ b/cmd/mist/assets/qml/views/browser.qml @@ -3,7 +3,7 @@ import QtQuick.Controls 1.0; import QtQuick.Controls.Styles 1.0 import QtQuick.Layouts 1.0; import QtWebEngine 1.0 -import QtWebEngine.experimental 1.0 +//import QtWebEngine.experimental 1.0 import QtQuick.Window 2.0; Rectangle { @@ -64,23 +64,15 @@ Rectangle { } function showFullUrlBar(on){ - if (on) { - //appTitle.visible = false - //appDomain.visible = false - - //uriNav.visible = true - clickAnywhereOnApp.visible = true - - navBar.state = "fullUrlVisible" - } else { - //appTitle.visible = true - //appDomain.visible = true - //uriNav.visible = false - clickAnywhereOnApp.visible = false - - navBar.state = "titleVisible" - - } + if (uriNav.focus == false ) { + if (on == false) { + clickAnywhereOnApp.visible = false + navBar.state = "titleVisible" + } else { + clickAnywhereOnApp.visible = true + navBar.state = "fullUrlVisible" + } + } } @@ -90,24 +82,40 @@ Rectangle { Item { objectName: "root" id: root - anchors.fill: parent + anchors { + fill: parent + } + state: "inspectorShown" MouseArea { id: clickAnywhereOnApp z:15 - //hoverEnabled: true - anchors.fill: parent - /*hoverEnabled: true*/ + // Using a secondary screen to catch on mouse exits for the area, because + // there are many hover actions conflicting + + anchors { + top: parent.top + topMargin: 50 + right: parent.right + bottom: parent.bottom + left: parent.left + } + hoverEnabled: true - onClicked: { + onEntered: { showFullUrlBar(false); } - /*Rectangle { - anchors.fill: parent - color: "#88888888" - }*/ + onClicked: { + uriNav.focus = false + showFullUrlBar(false); + } + + // Rectangle { + // anchors.fill: parent + // color: "#88888888" + // } } RowLayout { @@ -121,40 +129,44 @@ Rectangle { Button { id: back - - onClicked: { - webview.goBack() + z: 30 + onClicked: { + webview.goBack() } - anchors{ + anchors { left: parent.left leftMargin: 6 } style: ButtonStyle { - background: Image { - source: "../../backButton.png" - width: 20 - height: 30 - } + background: Image { + source: (webview.canGoBack) ? + (control.hovered ? "../../backButtonHover.png" : "../../backButton.png") : + "../../backButtonDisabled.png" + width: 20 + height: 30 + } } } Rectangle { - id: appInfoPane - height: 28 - color: "#FFFFFF" - radius: 6 - - - MouseArea { + id: appInfoPane + height: 28 + color: "#FFFFFF" + radius: 6 + z:2 + MouseArea { anchors.fill: parent z: 10 hoverEnabled: true onEntered: { - showFullUrlBar(true); - } + showFullUrlBar(true); + } + /*onExited: { + showFullUrlBar(false); + }*/ } @@ -171,14 +183,15 @@ Rectangle { font.bold: true font.capitalization: Font.AllUppercase horizontalAlignment: Text.AlignRight - verticalAlignment: Text.AlignVCenter - + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + anchors { left: parent.left right: parent.horizontalCenter top: parent.top bottom: parent.bottom - rightMargin: 10 + leftMargin: 32 } color: "#928484" } @@ -189,13 +202,15 @@ Rectangle { font.bold: false horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter + elide: Text.ElideLeft anchors { left: parent.horizontalCenter right: parent.right top: parent.top bottom: parent.bottom - leftMargin: 10 + leftMargin: 32 + } color: "#C0AFAF" } @@ -212,7 +227,7 @@ Rectangle { } horizontalAlignment: Text.AlignHCenter - + style: TextFieldStyle { textColor: "#928484" background: Rectangle { @@ -225,16 +240,16 @@ Rectangle { z: 20 activeFocusOnPress: true Keys.onReturnPressed: { - webview.url = this.text; + // if there's no http, add it. + var url = this.text, + matches = url.match(/^([a-z]*\:\/\/)?([^\/.]+)(:?\/)(.*|$)/i), + requestedProtocol = (matches && matches[1] != "undefined")? "" : "http://"; + + webview.url = requestedProtocol + url; } - /* onFocusedChanged: { - if (focused) { - //uriNav.selectAll(); - } - }*/ } - z:2 + } Rectangle { @@ -243,6 +258,7 @@ Rectangle { height: 30 color: "#BDB6B6" radius: 6 + z:1 anchors { left: back.right @@ -251,19 +267,17 @@ Rectangle { rightMargin:10 top: parent.top topMargin: 23 - } - - z:1 + } } Rectangle { id: navBarBackground anchors.fill: parent + z:-1 gradient: Gradient { GradientStop { position: 0.0; color: "#F6F1F2" } GradientStop { position: 1.0; color: "#DED5D5" } } - z:-1 } states: [ @@ -326,8 +340,8 @@ Rectangle { WebEngineView { objectName: "webView" id: webview - experimental.settings.javascriptCanAccessClipboard: true - experimental.settings.localContentCanAccessRemoteUrls: true + //experimental.settings.javascriptCanAccessClipboard: true + //experimental.settings.localContentCanAccessRemoteUrls: true anchors { left: parent.left right: parent.right @@ -337,13 +351,49 @@ Rectangle { z: 10 Timer { - interval: 500; running: true; repeat: true + interval: 2000; running: true; repeat: true onTriggered: { - webview.runJavaScript("try{document.querySelector('meta[name=badge]').getAttribute('content')}catch(e){}", function(badge) { - if (badge) { - menuItem.secondaryTitle = badge; - } - }); + webview.runJavaScript("try{document.querySelector('meta[name=ethereum-dapp-info]').getAttribute('content')}catch(e){}", function(extraInfo) { + if (extraInfo) { + menuItem.secondaryTitle = extraInfo; + } + }); + webview.runJavaScript("try{document.querySelector('meta[name=ethereum-dapp-badge]').getAttribute('content')}catch(e){}", function(badge) { + if (badge) { + if (Number(badge)>0 && Number(badge)<999) { + menuItem.badgeNumber = Number(badge); + menuItem.badgeContent = "number" + } else if (badge == "warning") { + menuItem.badgeIcon = "\ue00e" + menuItem.badgeContent = "icon" + + } else if (badge == "ghost") { + menuItem.badgeIcon = "\ue01a" + menuItem.badgeContent = "icon" + + } else if (badge == "question") { + menuItem.badgeIcon = "\ue05d" + menuItem.badgeContent = "icon" + + } else if (badge == "info") { + menuItem.badgeIcon = "\ue08b" + menuItem.badgeContent = "icon" + + } else if (badge == "check") { + menuItem.badgeIcon = "\ue080" + menuItem.badgeContent = "icon" + + } else if (badge == "gear") { + menuItem.badgeIcon = "\ue09a" + menuItem.badgeContent = "icon" + + } else { + menuItem.badgeContent = "" + } + } else { + menuItem.badgeContent = "" + } + }); } } @@ -353,6 +403,12 @@ Rectangle { menuItem.title = pageTitle; }); + webView.runJavaScript("try{document.querySelector(\"link[rel='icon']\").getAttribute(\"href\")}catch(e){}", function(sideIcon){ + if(sideIcon){ + menuItem.icon = webview.url + sideIcon; + }; + }); + webView.runJavaScript("try{document.querySelector(\"meta[name='ethereum-dapp-url-bar-style']\").getAttribute(\"content\")}catch(e){}", function(topBarStyle){ if (!topBarStyle) { showFullUrlBar(true); @@ -382,10 +438,15 @@ Rectangle { }; }); + + webview.runJavaScript(eth.readFile("bignumber.min.js")); + webview.runJavaScript(eth.readFile("ethereum.js/dist/ethereum.js")); + var cleanTitle = webview.url.toString() var matches = cleanTitle.match(/^[a-z]*\:\/\/([^\/?#]+)(?:[\/?#]|$)/i); var domain = matches && matches[1]; + if (domain) appDomain.text = domain //webview.url.replace("a", "z") if (webview.title) diff --git a/cmd/mist/assets/qml/views/catalog.qml b/cmd/mist/assets/qml/views/catalog.qml index 884493eef..497d69ed1 100644 --- a/cmd/mist/assets/qml/views/catalog.qml +++ b/cmd/mist/assets/qml/views/catalog.qml @@ -85,35 +85,21 @@ Rectangle { property var domain: "ethereum-dapp-catalog.meteor.com" url: protocol + domain - //navigationRequest: WebEngineView.IgnoreRequest - // onLoadingChanged: { - // if (loadRequest.status == WebEngineView.LoadSucceededStatus) { - // webview.runJavaScript(eth.readFile("bignumber.min.js")); - // webview.runJavaScript(eth.readFile("ethereum.js/dist/ethereum.js")); - // } - // } + //experimental.settings.javascriptCanAccessClipboard: true - //onNavigationRequested: { - // detect URL scheme prefix, most likely an external link - //var schemaRE = /^\w+:/; - //if (schemaRE.test(request.url)) { - // request.action = WebView.AcceptRequest; - //} else { - //request.action = WebView.IgnoreRequest; - // delegate request.url here - //} - //} onJavaScriptConsoleMessage: { console.log(sourceID + ":" + lineNumber + ":" + JSON.stringify(message)); } - onNavigationRequested: { + onNavigationRequested: { + // this checks if the domain of the requested link is the same as the catalog's + // If it is, it opens on the same window, if it's not it opens a new tab + var cleanTitle = request.url.toString() var matches = cleanTitle.match(/^[a-z]*\:\/\/([^\/?#]+)(?:[\/?#]|$)/i); var requestedDomain = matches && matches[1]; - console.debug ("NavigationRequested: " + request.url + " navigationType=" + request.navigationType) if(request.navigationType==0){ @@ -126,10 +112,18 @@ Rectangle { } } + // onLoadingChanged: { + // if (loadRequest.status == WebEngineView.LoadSucceededStatus) { + // webview.runJavaScript(eth.readFile("mist.js")); + // } + // } } + + + WebEngineView { id: inspector visible: false @@ -137,6 +131,7 @@ Rectangle { anchors { left: root.left right: root.right + top: root.top bottom: root.bottom } diff --git a/cmd/mist/assets/qml/views/miner.qml b/cmd/mist/assets/qml/views/miner.qml index 6a199a925..e239c7d7b 100644 --- a/cmd/mist/assets/qml/views/miner.qml +++ b/cmd/mist/assets/qml/views/miner.qml @@ -9,7 +9,7 @@ import Ethereum 1.0 Rectangle { id: root property var title: "Miner" - property var iconSource: "../miner.png" + property var iconSource: "../mining-icon.png" property var menuItem color: "#00000000" diff --git a/cmd/mist/assets/qml/views/wallet.qml b/cmd/mist/assets/qml/views/wallet.qml index 59dbae848..2369390c3 100644 --- a/cmd/mist/assets/qml/views/wallet.qml +++ b/cmd/mist/assets/qml/views/wallet.qml @@ -9,7 +9,6 @@ import Ethereum 1.0 Rectangle { id: root property var title: "Wallet" - property var iconSource: "../facet.png" property var menuItem objectName: "walletView"