diff options
Diffstat (limited to 'gui')
-rw-r--r-- | gui/components/BoldLabel.qml | 15 | ||||
-rw-r--r-- | gui/components/ErrorBox.qml | 33 | ||||
-rw-r--r-- | gui/components/InitErrors.qml | 49 | ||||
-rw-r--r-- | gui/components/LightLabel.qml | 1 | ||||
-rw-r--r-- | gui/components/MainView.qml | 4 | ||||
-rw-r--r-- | gui/components/Splash.qml | 15 | ||||
-rw-r--r-- | gui/components/StatusBox.qml | 89 | ||||
-rw-r--r-- | gui/components/VPNState.qml | 104 | ||||
-rw-r--r-- | gui/gui.qrc | 14 | ||||
-rw-r--r-- | gui/main.qml | 130 | ||||
-rw-r--r-- | gui/resources/alert.svg | 4 | ||||
-rw-r--r-- | gui/resources/fonts/Montserrat-Regular.ttf | bin | 0 -> 245708 bytes | |||
-rw-r--r-- | gui/resources/fonts/Montserrat-SemiBold.ttf | bin | 0 -> 243816 bytes |
13 files changed, 294 insertions, 164 deletions
diff --git a/gui/components/BoldLabel.qml b/gui/components/BoldLabel.qml index 6c6c3c3..d4a6ba3 100644 --- a/gui/components/BoldLabel.qml +++ b/gui/components/BoldLabel.qml @@ -4,18 +4,15 @@ import "../themes/themes.js" as Theme import "../themes" Label { - FontLoader { - id: boldFont - source: "qrc:/oxanium-bold.ttf" + color: "black" + + font { + pixelSize: Theme.fontSize * 1.5 + family: boldFont.name + bold: true } - font.pixelSize: Theme.fontSize * 1.55555 - //font.family: boldFont.name - font.bold: true - //color: Theme.fontColorDark - color: "black" text: parent.text - //wrapMode: Text.WordWrap Accessible.name: text Accessible.role: Accessible.StaticText } diff --git a/gui/components/ErrorBox.qml b/gui/components/ErrorBox.qml new file mode 100644 index 0000000..40c12d0 --- /dev/null +++ b/gui/components/ErrorBox.qml @@ -0,0 +1,33 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtGraphicalEffects 1.0 +import "../themes/themes.js" as Theme + +Item { + id: errorBox + width: parent.width + property var errorText: "" + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: connectionImage.bottom + + // TODO alert icon, by type + + Rectangle { + + id: labelWrapper + color: "transparent" + height: label.paintedHeight + Theme.windowMargin + width: parent.width + anchors.verticalCenter: parent.verticalCenter + + Label { + id: label + width: labelWrapper.width - Theme.windowMargin + anchors.centerIn: parent + text: errorBox.errorText //+ " " + "<b><u>" + alertLinkText + "</b></u>" + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.Wrap + font.pixelSize: Theme.fontSizeSmall + } + } +} diff --git a/gui/components/InitErrors.qml b/gui/components/InitErrors.qml new file mode 100644 index 0000000..2859168 --- /dev/null +++ b/gui/components/InitErrors.qml @@ -0,0 +1,49 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtGraphicalEffects 1.0 + +ErrorBox { + + state: "noerror" + + states: [ + State { + name: "noerror" + when: root.error == "" + PropertyChanges { + target: splashSpinner + visible: true + } + PropertyChanges { + target: splashErrorBox + visible: false + } + }, + State { + name: "nohelpers" + when: root.error == "nohelpers" + PropertyChanges { + target: splashSpinner + visible: false + } + PropertyChanges { + target: splashErrorBox + errorText: qsTr("Could not find helpers. Please check your installation") + visible: true + } + }, + State { + name: "nopolkit" + when: root.error == "nopolkit" + PropertyChanges { + target: splashSpinner + visible: false + } + PropertyChanges { + target: splashErrorBox + errorText: qsTr("Could not find polkit agent.") + visible: true + } + } + ] +} diff --git a/gui/components/LightLabel.qml b/gui/components/LightLabel.qml index 78f82b6..ea723c7 100644 --- a/gui/components/LightLabel.qml +++ b/gui/components/LightLabel.qml @@ -11,7 +11,6 @@ Text { horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter - //lineHeightMode: Text.FixedHeight wrapMode: Text.Wrap Accessible.role: Accessible.StaticText diff --git a/gui/components/MainView.qml b/gui/components/MainView.qml index 7ce723d..1918c7f 100644 --- a/gui/components/MainView.qml +++ b/gui/components/MainView.qml @@ -26,6 +26,10 @@ Page { delegate: ItemDelegate { width: parent.width text: model.text + visible: { + if (isDonationService) {return true} + return model.text != qsTr("Donate") + } highlighted: ListView.isCurrentItem icon.color: "transparent" icon.source: model.icon diff --git a/gui/components/Splash.qml b/gui/components/Splash.qml index b494494..6bdd3ab 100644 --- a/gui/components/Splash.qml +++ b/gui/components/Splash.qml @@ -5,6 +5,7 @@ import QtGraphicalEffects 1.0 Page { id: splash property int timeoutInterval: 1600 + property alias errors: splashErrorBox Column { width: parent.width * 0.8 @@ -24,7 +25,13 @@ Page { fillMode: Image.PreserveAspectFit } - Spinner {} + Spinner { + id: splashSpinner + } + + InitErrors { + id: splashErrorBox + } } Timer { @@ -39,10 +46,10 @@ Page { } function loadMainViewWhenReady() { - console.debug("ready?") + if (root.error != "") { + return + } if (ctx && ctx.isReady) { - console.debug("ready?", ctx.isReady) - // FIXME check errors == None loader.source = "MainView.qml" } else { delay(100, loadMainViewWhenReady) diff --git a/gui/components/StatusBox.qml b/gui/components/StatusBox.qml index fa24cd8..a20b930 100644 --- a/gui/components/StatusBox.qml +++ b/gui/components/StatusBox.qml @@ -19,27 +19,33 @@ Item { Rectangle { id: statusBoxBackground - anchors.fill: parent - anchors.margins: 20 - anchors.bottomMargin: 30 height: 300 radius: 10 color: Theme.bgColor - border.color: Theme.accentOff - border.width: 2 antialiasing: true + anchors { + fill: parent + margins: 20 + bottomMargin: 30 + } + border { + color: Theme.accentOff + width: 2 + } } ToolButton { id: settingsButton objectName: "settingsButton" + font.pixelSize: Qt.application.font.pixelSize * 1.2 opacity: 1 - font.pixelSize: Qt.application.font.pixelSize * 1.6 - anchors.top: parent.top - anchors.left: parent.left - anchors.topMargin: Theme.windowMargin + 10 - anchors.leftMargin: Theme.windowMargin + 10 + anchors { + top: parent.top + left: parent.left + topMargin: Theme.windowMargin + 10 + leftMargin: Theme.windowMargin + 10 + } onClicked: { if (stackView.depth > 1) { @@ -51,75 +57,78 @@ Item { Icon { id: settingsImage - width: 24 - height: 24 - // TODO move arrow left to toolbar top + width: 16 + height: 16 + anchors.centerIn: settingsButton source: stackView.depth > 1 ? "../resources/arrow-left.svg" : "../resources/gear-fill.svg" - anchors.centerIn: settingsButton } } - Column { - id: col - anchors.centerIn: parent - anchors.topMargin: 24 - width: parent.width * 0.8 - + Rectangle { + id: statusLabelWrapper + height: 45 + anchors { + top: statusBoxBackground.top + topMargin: 40 + horizontalCenter: parent.horizontalCenter + } BoldLabel { id: connectionState - text: "" + anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter horizontalAlignment: Text.AlignHCenter + text: "" } + } + + Column { + id: col + width: parent.width * 0.8 + anchors.horizontalCenter: parent.horizontalCenter VerticalSpacer { id: spacerPreImg - visible: false - height: 40 + visible: true + height: 150 } Image { id: connectionImage - height: 200 + height: 160 source: "../resources/spy.gif" + anchors.horizontalCenter: parent.horizontalCenter fillMode: Image.PreserveAspectFit } VerticalSpacer { id: spacerPostImg - visible: false - height: 35 + visible: true + height: 30 } MaterialButton { id: toggleVPN + spacing: 8 + anchors.horizontalCenter: parent.horizontalCenter Layout.alignment: Qt.AlignBottom - font.capitalization: Font.Capitalize - spacing: 8 + + font { + capitalization: Font.Capitalize + family: lightFont.name + bold: false + } onClicked: { if (vpn.state === "on") { - console.debug("should turn off") backend.switchOff() } else if (vpn.state === "off") { - console.debug("should turn on") backend.switchOn() } else { console.debug("unknown state") } } - - - /* - XXX this hijacks click events, so better no pointing for now. - MouseArea { - anchors.fill: toggleVPN - hoverEnabled: true - cursorShape: !hoverEnabled ? Qt.ForbiddenCursor : Qt.PointingHandCursor - } - */ } } } diff --git a/gui/components/VPNState.qml b/gui/components/VPNState.qml index 8856ad4..9d443ce 100644 --- a/gui/components/VPNState.qml +++ b/gui/components/VPNState.qml @@ -4,15 +4,21 @@ import QtQuick.Controls 2.12 import "../themes/themes.js" as Theme StateGroup { + property var initializing: "initializing" + property var off: "off" + property var on: "on" + property var starting: "starting" + property var stopping: "stopping" + property var failed: "failed" - state: ctx ? ctx.status : "off" + state: ctx ? ctx.status : vpnStates.off states: [ State { - name: "initializing" + name: initializing }, State { - name: "off" + name: off PropertyChanges { target: connectionState text: qsTr("Connection\nUnsecured") @@ -24,10 +30,6 @@ StateGroup { PropertyChanges { target: connectionImage source: "../resources/spy.gif" - //anchors.right: parent.right - //anchors.rightMargin: -8 - // XXX need to nulify horizontalcenter somehow, - // it gets fixed to parent.center } PropertyChanges { target: toggleVPN @@ -42,16 +44,14 @@ StateGroup { text: toHuman("off") } StateChangeScript { - script: { - - } + script: {} } }, State { - name: "on" + name: on PropertyChanges { target: connectionState - text: qsTr("Connection\nSecure") + text: qsTr("Connection\nSecured") } PropertyChanges { target: statusBoxBackground @@ -60,17 +60,6 @@ StateGroup { PropertyChanges { target: connectionImage source: "../resources/riseup-icon.svg" - // TODO need to offset the logo or increase the image - // to fixed height - height: 120 - } - PropertyChanges { - target: spacerPreImg - visible: true - } - PropertyChanges { - target: spacerPostImg - visible: true } PropertyChanges { target: toggleVPN @@ -86,20 +75,11 @@ StateGroup { text: toHuman("on") } StateChangeScript { - script: { - - // TODO check donation - //if (needsDonate && !shownDonate) { - // donate.visible = true; - // shownDonate = true; - // backend.donateSeen(); - //} - } + script: {} } }, State { - name: "starting" - //when: toggleVPN.pressed == true + name: starting PropertyChanges { target: connectionState text: qsTr("Connecting") @@ -127,13 +107,11 @@ StateGroup { text: toHuman("connecting") } StateChangeScript { - script: { - - } + script: {} } }, State { - name: "stopping" + name: stopping PropertyChanges { target: connectionState text: "Switching\nOff" @@ -143,6 +121,12 @@ StateGroup { border.color: Theme.accentConnecting } PropertyChanges { + // ?? is this image correct? + target: connectionImage + source: "../resources/birds.svg" + anchors.horizontalCenter: parent.horizontalCenter + } + PropertyChanges { target: systray tooltip: toHuman("stopping") icon.source: icons["wait"] @@ -153,23 +137,39 @@ StateGroup { } }, State { - name: "failed" - // TODO + name: failed } ] - - - /* - transitions: Transition { - from: "off" - to: "starting" - reversible: true - - ParallelAnimation { - ColorAnimation { duration: 500 } + transitions: [ + Transition { + to: on + ColorAnimation { + target: statusBoxBackground + duration: 500 + } + }, + Transition { + to: off + ColorAnimation { + target: statusBoxBackground + duration: 500 + } + }, + Transition { + to: starting + ColorAnimation { + target: statusBoxBackground + duration: 500 + } + }, + Transition { + to: stopping + ColorAnimation { + target: statusBoxBackground + duration: 500 + } } - } - */ + ] function toHuman(st) { switch (st) { case "off": diff --git a/gui/gui.qrc b/gui/gui.qrc index dde4c8f..c794ef1 100644 --- a/gui/gui.qrc +++ b/gui/gui.qrc @@ -3,6 +3,7 @@ <file>main.qml</file> + <!-- gui components --> <file>themes/themes.js</file> <file>components/MainView.qml</file> <file>components/Splash.qml</file> @@ -23,6 +24,10 @@ <file>components/Icon.qml</file> <file>components/MaterialButton.qml</file> <file>components/VPNState.qml</file> + <file>components/InitErrors.qml</file> + <file>components/ErrorBox.qml</file> + + <!-- resources, assets --> <file>resources/icon-noshield.svg</file> <file>resources/location.svg</file> <file>resources/settings.svg</file> @@ -43,8 +48,13 @@ <file>resources/riseup-icon.svg</file> <file>resources/spy.gif</file> <file>resources/quit.svg</file> + <file>resources/alert.svg</file> + + <!-- fonts --> + <file alias="montserrat-light.ttf">resources/fonts/Montserrat-Regular.ttf</file> + <file alias="montserrat-bold.ttf">resources/fonts/Montserrat-SemiBold.ttf</file> - <!-- old, to remove --> + <!-- begin, to remove --> <file>qml/VpnState.qml</file> <file>qml/AboutDialog.qml</file> <file>qml/DonateDialog.qml</file> @@ -57,7 +67,7 @@ <file>qml/VPNSwitch.qml</file> <file>qml/BridgesItem.qml</file> <file>qml/logic.js</file> - <!-- to remove --> + <!-- end, to remove --> <file>assets/icon/png/black/vpn_off.png</file> <file>assets/icon/png/black/vpn_on.png</file> diff --git a/gui/main.qml b/gui/main.qml index 16677a2..f847377 100644 --- a/gui/main.qml +++ b/gui/main.qml @@ -1,21 +1,23 @@ + + /* TODO (ui rewrite) - [x] add systray - [x] systray status - [x] splash screen - - [ ] splash delay/transitions - - [ ] nested states - - [ ] splash init errors - - [ ] font: monserrat - - [ ] donation dialog - - [ ] add gateway to systray - - [ ] control actions from systray + - [x] splash delay/transitions + - [x] font: monserrat + - [x] nested states + - [x] splash init errors - [ ] minimize/hide from systray - - [ ] parse ctx flags (need dialog, etc) - [ ] gateway selector - [ ] bridges + - [ ] control actions from systray + - [ ] add gateway to systray + - [ ] donation dialog + - [ ] parse ctx flags (need dialog, etc) + - [ ] udp support */ - import QtQuick 2.0 import QtQuick.Controls 2.4 import QtQuick.Dialogs 1.2 @@ -40,6 +42,9 @@ ApplicationWindow { Material.accent: Material.Green property var ctx + property var error: "" + property bool isDonationService: false + property bool showDonationReminder: false property var icons: { "off": "qrc:/assets/icon/png/white/vpn_off.png", @@ -48,64 +53,77 @@ ApplicationWindow { "blocked": "qrc:/assets/icon/png/white/vpn_blocked.png" } + FontLoader { + id: lightFont + source: "qrc:/montserrat-light.ttf" + } + + FontLoader { + id: boldFont + source: "qrc:/montserrat-bold.ttf" + } + + font.family: lightFont.name + Loader { - id: loader - asynchronous: true - anchors.fill: parent + id: loader + asynchronous: true + anchors.fill: parent } Systray { - id: systray + id: systray } + Connections { - target: jsonModel - function onDataChanged() { - ctx = JSON.parse(jsonModel.getJson()) + target: jsonModel + function onDataChanged() { + let j = jsonModel.getJson() if (qmlDebug) { - console.debug(jsonModel.getJson()) + console.debug(j) } - - // FIXME -- use nested state machines for all these cases. - - //gwSelector.model = Object.keys(ctx.locations) - - /* - if (ctx.donateDialog == 'true') { - Logic.setNeedsDonate(true); - } - if (ctx.loginDialog == 'true') { - console.debug(jsonModel.getJson()) - console.debug("DEBUG: should display login") - login.visible = true - } - if (ctx.loginOk == 'true') { - loginOk.visible = true - } - if (ctx.errors) { - login.visible = false - if (ctx.errors == "nohelpers") { - showInitFailure( - qsTr("Could not find helpers. Please check your installation")) - } else if (ctx.errors == "nopolkit") { - showInitFailure(qsTr("Could not find polkit agent.")) - } else { - showInitFailure() - } - } - if (ctx.donateURL) { - donateItem.visible = true - } - - if (ctx.status == "on") { - gwNextConnectionText.visible = false - gwReconnectText.visible = false - } - */ - } + ctx = JSON.parse(j) + if (ctx.errors) { + console.debug("errors, setting root.error") + root.error = ctx.errors + } else { + root.error = "" + } + if (ctx.donateURL) { + isDonationService = true; + } + if (ctx.donateDialog == 'true') { + showDonationReminder = true; + } + //gwSelector.model = Object.keys(ctx.locations) + // TODO check donation + //if (needsDonate && !shownDonate) { + // donate.visible = true; + // shownDonate = true; + // // move this to onClick of "close" for widget + // backend.donateSeen(); + //} + // TODO refactor donate widget into main view (with close window!) + //if (ctx.status == "on") { + // gwNextConnectionText.visible = false + // gwReconnectText.visible = false + // when: vpn.status == "on" + //} + + /* + TODO libraries need login + if (ctx.loginDialog == 'true') { + login.visible = true + } + if (ctx.loginOk == 'true') { + loginOk.visible = true + } + */ + } } - onSceneGraphError: function(error, msg) { + onSceneGraphError: function (error, msg) { console.debug("ERROR while initializing scene") console.debug(msg) } diff --git a/gui/resources/alert.svg b/gui/resources/alert.svg new file mode 100644 index 0000000..cd178eb --- /dev/null +++ b/gui/resources/alert.svg @@ -0,0 +1,4 @@ +<svg width="24px" height="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <path fill="#494c4e" d="M12 2l10 20H2L12 2m0-2c-.758 0-1.45.428-1.79 1.106l-10 20c-.31.62-.276 1.356.09 1.946.363.59 1.007.948 1.7.948h20c.693 0 1.337-.36 1.7-.95.365-.59.4-1.325.09-1.945l-10-20C13.45.428 12.756 0 12 0z"/> + <path fill="#494c4e" d="M12 20c-.832 0-1.507-.672-1.507-1.5S11.168 17 12 17s1.507.672 1.507 1.5S12.832 20 12 20zm.985-4.806c-.093.47-.505.806-.985.806s-.892-.337-.985-.806l-.996-5c-.06-.293.017-.598.208-.83.19-.23.476-.364.776-.364h1.99c.302 0 .587.134.777.365.192.23.27.536.21.83l-.995 5z"/> +</svg> diff --git a/gui/resources/fonts/Montserrat-Regular.ttf b/gui/resources/fonts/Montserrat-Regular.ttf Binary files differnew file mode 100644 index 0000000..8d443d5 --- /dev/null +++ b/gui/resources/fonts/Montserrat-Regular.ttf diff --git a/gui/resources/fonts/Montserrat-SemiBold.ttf b/gui/resources/fonts/Montserrat-SemiBold.ttf Binary files differnew file mode 100644 index 0000000..f8a43f2 --- /dev/null +++ b/gui/resources/fonts/Montserrat-SemiBold.ttf |