From cd1d46a26b923260b6c87cc93a0723b8166c609e Mon Sep 17 00:00:00 2001 From: "kali kaneko (leap communications)" <kali@leap.se> Date: Fri, 27 Aug 2021 19:45:41 +0200 Subject: [PATCH] [ui] refactor ui --- bitmask.pro | 9 + docs/hacking-qml.rst | 6 + gui/backend.go | 2 +- gui/components/BoldLabel.qml | 21 ++ gui/components/Footer.qml | 63 ++++++ gui/components/Header.qml | 32 +++ gui/components/Help.qml | 32 +++ gui/components/Home.qml | 8 + gui/components/Icon.qml | 9 + gui/components/LightLabel.qml | 19 ++ gui/components/Locations.qml | 63 ++++++ gui/components/MainView.qml | 131 ++++++++++++ gui/components/MaterialButton.qml | 84 ++++++++ gui/components/Preferences.qml | 23 ++ gui/components/Spinner.qml | 63 ++++++ gui/components/Splash.qml | 64 ++++++ gui/components/StatusBox.qml | 125 +++++++++++ gui/components/Style.qml | 12 ++ gui/components/Systray.qml | 27 +++ gui/components/VPNButtonBase.qml | 56 +++++ gui/components/VPNMouseArea.qml | 37 ++++ gui/components/VPNState.qml | 193 +++++++++++++++++ gui/components/VPNToggle.qml | 338 ++++++++++++++++++++++++++++++ gui/components/VerticalSpacer.qml | 6 + gui/gui.qrc | 46 +++- gui/main.cpp | 21 +- gui/main.qml | 116 ++++++++++ gui/providers/providers.json | 2 +- gui/qml/BackgroundImage.qml | 16 +- gui/qml/BridgesItem.qml | 16 +- gui/qml/VPNSwitch.qml | 1 - gui/qml/VpnState.qml | 13 +- gui/qml/main.qml | 65 +++--- gui/qml/readme.txt | 1 + gui/resources/about.svg | 62 ++++++ gui/resources/arrow-left.svg | 3 + gui/resources/birds.svg | 1 + gui/resources/bridge.png | Bin 0 -> 5543 bytes gui/resources/close.svg | 3 + gui/resources/donate.svg | 4 + gui/resources/gear-fill.svg | 3 + gui/resources/globe.svg | 3 + gui/resources/help.svg | 4 + gui/resources/icon-noshield.svg | 68 ++++++ gui/resources/location.svg | 58 +++++ gui/resources/power.svg | 10 + gui/resources/quit.svg | 4 + gui/resources/reception-0.svg | 3 + gui/resources/reception-2.svg | 3 + gui/resources/reception-4.svg | 3 + gui/resources/riseup-icon.svg | 80 +++++++ gui/resources/riseup-logo.png | Bin 0 -> 4943 bytes gui/resources/settings.svg | 62 ++++++ gui/resources/speed-green.svg | 72 +++++++ gui/resources/speed-red.svg | 72 +++++++ gui/resources/speed-yellow.svg | 72 +++++++ gui/resources/spy.gif | Bin 0 -> 2662 bytes gui/resources/tools.svg | 4 + gui/themes/themes.js | 51 +++++ pkg/backend/init.go | 4 +- pkg/backend/status.go | 1 + 61 files changed, 2301 insertions(+), 69 deletions(-) create mode 100644 docs/hacking-qml.rst create mode 100644 gui/components/BoldLabel.qml create mode 100644 gui/components/Footer.qml create mode 100644 gui/components/Header.qml create mode 100644 gui/components/Help.qml create mode 100644 gui/components/Home.qml create mode 100644 gui/components/Icon.qml create mode 100644 gui/components/LightLabel.qml create mode 100644 gui/components/Locations.qml create mode 100644 gui/components/MainView.qml create mode 100644 gui/components/MaterialButton.qml create mode 100644 gui/components/Preferences.qml create mode 100644 gui/components/Spinner.qml create mode 100644 gui/components/Splash.qml create mode 100644 gui/components/StatusBox.qml create mode 100644 gui/components/Style.qml create mode 100644 gui/components/Systray.qml create mode 100644 gui/components/VPNButtonBase.qml create mode 100644 gui/components/VPNMouseArea.qml create mode 100644 gui/components/VPNState.qml create mode 100644 gui/components/VPNToggle.qml create mode 100644 gui/components/VerticalSpacer.qml create mode 100644 gui/main.qml create mode 100644 gui/qml/readme.txt create mode 100644 gui/resources/about.svg create mode 100644 gui/resources/arrow-left.svg create mode 100644 gui/resources/birds.svg create mode 100644 gui/resources/bridge.png create mode 100644 gui/resources/close.svg create mode 100644 gui/resources/donate.svg create mode 100644 gui/resources/gear-fill.svg create mode 100644 gui/resources/globe.svg create mode 100644 gui/resources/help.svg create mode 100644 gui/resources/icon-noshield.svg create mode 100644 gui/resources/location.svg create mode 100644 gui/resources/power.svg create mode 100644 gui/resources/quit.svg create mode 100644 gui/resources/reception-0.svg create mode 100644 gui/resources/reception-2.svg create mode 100644 gui/resources/reception-4.svg create mode 100644 gui/resources/riseup-icon.svg create mode 100644 gui/resources/riseup-logo.png create mode 100644 gui/resources/settings.svg create mode 100644 gui/resources/speed-green.svg create mode 100644 gui/resources/speed-red.svg create mode 100644 gui/resources/speed-yellow.svg create mode 100644 gui/resources/spy.gif create mode 100644 gui/resources/tools.svg create mode 100644 gui/themes/themes.js diff --git a/bitmask.pro b/bitmask.pro index 627e2d3b..25139440 100644 --- a/bitmask.pro +++ b/bitmask.pro @@ -1,6 +1,9 @@ #TARGET = $$BINARY_NAME +QT += quickcontrols2 +CONFIG += c++11 CONFIG += qt staticlib +CONFIG += qtquickcompiler CONFIG+=force_debug_info CONFIG+=debug_and_release #CONFIG+=release @@ -11,6 +14,12 @@ QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.11 QMAKE_TARGET_BUNDLE_PREFIX = se.leap QMAKE_BUNDLE = $$TARGET +# The following define makes your compiler emit warnings if you use +# any feature of Qt which as been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + !defined(VENDOR_PATH, var):VENDOR_PATH="providers/riseup" message("[qmake] VENDOR_PATH: $$VENDOR_PATH") diff --git a/docs/hacking-qml.rst b/docs/hacking-qml.rst new file mode 100644 index 00000000..7e793ba3 --- /dev/null +++ b/docs/hacking-qml.rst @@ -0,0 +1,6 @@ +QML best practices +================== +* https://github.com/Furkanzmc/QML-Coding-Guide/blob/master/README.md +* lint your qml files:: + + make qmllint diff --git a/gui/backend.go b/gui/backend.go index 04d1293a..bc056b90 100644 --- a/gui/backend.go +++ b/gui/backend.go @@ -83,7 +83,7 @@ func InitializeBitmaskContext(provider string, opts.Obfs4 = obfs4 opts.DisableAutostart = disableAutostart opts.StartVPN = startVPN - backend.InitializeBitmaskContext(opts) + go backend.InitializeBitmaskContext(opts) } //export InitializeTestBitmaskContext diff --git a/gui/components/BoldLabel.qml b/gui/components/BoldLabel.qml new file mode 100644 index 00000000..6c6c3c34 --- /dev/null +++ b/gui/components/BoldLabel.qml @@ -0,0 +1,21 @@ +import QtQuick 2.5 +import QtQuick.Controls 2.14 +import "../themes/themes.js" as Theme +import "../themes" + +Label { + FontLoader { + id: boldFont + source: "qrc:/oxanium-bold.ttf" + } + + 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/Footer.qml b/gui/components/Footer.qml new file mode 100644 index 00000000..2c7c875a --- /dev/null +++ b/gui/components/Footer.qml @@ -0,0 +1,63 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.4 +import QtQuick.Controls.Material 2.1 +import QtQuick.Layouts 1.14 + +ToolBar { + + Material.background: Material.backgroundColor + Material.foreground: "black" + Material.elevation: 0 + visible: stackView.depth > 1 && ctx !== undefined ? false : true + + Item { + + id: footerRow + width: root.width + + ToolButton { + id: gwButton + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: 10 + anchors.left: parent.left + anchors.verticalCenterOffset: 5 + icon.source: stackView.depth > 1 ? "" : "../resources/globe.svg" + onClicked: stackView.push("Locations.qml") + } + + Label { + id: locationLabel + anchors.left: gwButton.right + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: 5 + text: "Seattle" + } + + Item { + Layout.fillWidth: true + height: gwButton.implicitHeight + } + + Image { + id: bridge + height: 24 + width: 24 + source: "../resources/bridge.png" + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: 5 + anchors.right: gwQuality.left + anchors.rightMargin: 10 + } + + Image { + id: gwQuality + height: 24 + width: 24 + source: "../resources/reception-0.svg" + anchors.right: parent.right + anchors.rightMargin: 20 + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: 5 + } + } +} diff --git a/gui/components/Header.qml b/gui/components/Header.qml new file mode 100644 index 00000000..92f4bdde --- /dev/null +++ b/gui/components/Header.qml @@ -0,0 +1,32 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.4 +import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Material 2.1 + +ToolBar { + visible: stackView.depth > 1 + Material.foreground: Material.Black + Material.background: "#ffffff" + Material.elevation: 0 + + contentHeight: settingsButton.implicitHeight + + ToolButton { + id: settingsButton + anchors.left: parent.left + font.pixelSize: Qt.application.font.pixelSize * 1.6 + icon.source: "../resources/arrow-left.svg" + onClicked: { + if (stackView.depth > 1) { + stackView.pop() + } else { + settingsDrawer.open() + } + } + } + + Label { + text: stackView.currentItem.title + anchors.centerIn: parent + } +} diff --git a/gui/components/Help.qml b/gui/components/Help.qml new file mode 100644 index 00000000..aced2731 --- /dev/null +++ b/gui/components/Help.qml @@ -0,0 +1,32 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 + +Page { + title: qsTr("Help") + + Column { + anchors.centerIn: parent + spacing: 10 + + Button { + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("Donate") + onClicked: stackView.push("Donate.qml") + } + Button { + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("Terms of Service") + onClicked: stackView.push("Donate.qml") + } + Button { + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("Contact Support") + onClicked: stackView.push("Donate.qml") + } + Button { + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("Report bug") + onClicked: stackView.push("Donate.qml") + } + } +} diff --git a/gui/components/Home.qml b/gui/components/Home.qml new file mode 100644 index 00000000..c9eab2a1 --- /dev/null +++ b/gui/components/Home.qml @@ -0,0 +1,8 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtGraphicalEffects 1.0 + +Page { + + StatusBox {} +} diff --git a/gui/components/Icon.qml b/gui/components/Icon.qml new file mode 100644 index 00000000..5dfd6ee8 --- /dev/null +++ b/gui/components/Icon.qml @@ -0,0 +1,9 @@ +import QtQuick 2.5 +import QtQuick.Layouts 1.14 +import "../themes/themes.js" as Theme + +Image { + sourceSize.height: 24 + sourceSize.width: 24 + fillMode: Image.PreserveAspectFit +} diff --git a/gui/components/LightLabel.qml b/gui/components/LightLabel.qml new file mode 100644 index 00000000..78f82b65 --- /dev/null +++ b/gui/components/LightLabel.qml @@ -0,0 +1,19 @@ +import QtQuick 2.5 +import QtQuick.Controls 2.14 +import "../themes/themes.js" as Theme + +Text { + font.pixelSize: Theme.fontSize - 2 + font.family: Theme.fontFamily + color: Theme.fontColor + width: parent.width * 0.80 + text: parent.text + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + //lineHeightMode: Text.FixedHeight + wrapMode: Text.Wrap + + Accessible.role: Accessible.StaticText + Accessible.name: text +} diff --git a/gui/components/Locations.qml b/gui/components/Locations.qml new file mode 100644 index 00000000..d3e0f5ad --- /dev/null +++ b/gui/components/Locations.qml @@ -0,0 +1,63 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 + +import "../themes/themes.js" as Theme + +Page { + title: qsTr("Select Location") + + ListView { + id: gwList + focus: true + currentIndex: -1 + anchors.fill: parent + spacing: 1 + + delegate: ItemDelegate { + id: loc + Rectangle { + width: parent.width + height: 1 + color: Theme.borderColor + } + width: parent.width + text: model.text + highlighted: ListView.isCurrentItem + icon.color: "transparent" + icon.source: model.icon + onClicked: { + model.triggered() + stackView.pop() + } + MouseArea { + property var onMouseAreaClicked: function () { + parent.clicked() + } + id: mouseArea + anchors.fill: loc + cursorShape: Qt.PointingHandCursor + onReleased: { + onMouseAreaClicked() + } + } + } + + model: ListModel { + ListElement { + text: qsTr("Paris") + triggered: function () {} + icon: "../resources/reception-4.svg" + } + ListElement { + text: qsTr("Montreal") + triggered: function () {} + icon: "../resources/reception-4.svg" + } + ListElement { + text: qsTr("Seattle") + triggered: function () {} + icon: "../resources/reception-2.svg" + } + } + } +} diff --git a/gui/components/MainView.qml b/gui/components/MainView.qml new file mode 100644 index 00000000..7ce723db --- /dev/null +++ b/gui/components/MainView.qml @@ -0,0 +1,131 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.4 +import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Material 2.1 +import QtQuick.Layouts 1.14 + +Page { + + StackView { + id: stackView + anchors.fill: parent + initialItem: Home {} + } + + Drawer { + id: settingsDrawer + + width: Math.min(root.width, root.height) / 3 * 2 + height: root.height + + ListView { + focus: true + currentIndex: -1 + anchors.fill: parent + + delegate: ItemDelegate { + width: parent.width + text: model.text + highlighted: ListView.isCurrentItem + icon.color: "transparent" + icon.source: model.icon + onClicked: { + settingsDrawer.close() + model.triggered() + } + } + + model: ListModel { + ListElement { + text: qsTr("Preferences") + icon: "../resources/tools.svg" + triggered: function () { + stackView.push("Preferences.qml") + } + } + ListElement { + text: qsTr("Donate") + icon: "../resources/donate.svg" + triggered: function () { + aboutDialog.open() + } + } + ListElement { + text: qsTr("Help") + icon: "../resources/help.svg" + triggered: function () { + stackView.push("Help.qml") + settingsDrawer.close() + } + } // -> can link to another dialog with report bug / support / contribute / FAQ + ListElement { + text: qsTr("About") + icon: "../resources/about.svg" + triggered: function () { + aboutDialog.open() + } + } + ListElement { + text: qsTr("Quit") + icon: "../resources/quit.svg" + triggered: function () { + Qt.callLater(backend.quit) + } + } + } + + ScrollIndicator.vertical: ScrollIndicator {} + } + } + + Drawer { + id: locationsDrawer + + width: root.width + height: root.height + + ListView { + focus: true + currentIndex: -1 + anchors.fill: parent + + delegate: ItemDelegate { + width: parent.width + text: model.text + highlighted: ListView.isCurrentItem + onClicked: { + locationsDrawer.close() + model.triggered() + } + } + + model: ListModel { + ListElement { + text: qsTr("Montreal, CA") + triggered: function () {} + } + ListElement { + text: qsTr("Paris, FR") + triggered: function () {} + } + } + + ScrollIndicator.vertical: ScrollIndicator {} + } + } + + header: Header {} + footer: Footer {} + + Dialog { + id: aboutDialog + title: qsTr("About") + Label { + anchors.fill: parent + text: qsTr("RiseupVPN\nhttps://riseupvpn.net/vpn") + horizontalAlignment: Text.AlignHCenter + } + + standardButtons: StandardButton.Ok + } +} diff --git a/gui/components/MaterialButton.qml b/gui/components/MaterialButton.qml new file mode 100644 index 00000000..25911f33 --- /dev/null +++ b/gui/components/MaterialButton.qml @@ -0,0 +1,84 @@ +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import QtQuick.Controls 2.12 +import QtQuick.Controls.impl 2.12 +import QtQuick.Controls.Material 2.12 +import QtQuick.Controls.Material.impl 2.12 + +T.Button { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + + topInset: 6 + bottomInset: 6 + padding: 12 + horizontalPadding: padding - 4 + spacing: 6 + + icon.width: 24 + icon.height: 24 + icon.color: !enabled ? Material.hintTextColor : flat + && highlighted ? Material.accentColor : highlighted ? Material.primaryHighlightedTextColor : Material.foreground + + Material.elevation: flat ? control.down + || control.hovered ? 2 : 0 : control.down ? 8 : 2 + Material.background: flat ? "transparent" : undefined + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon + text: control.text + font: control.font + + color: !control.enabled ? control.Material.hintTextColor : control.flat + && control.highlighted ? control.Material.accentColor : control.highlighted ? control.Material.primaryHighlightedTextColor : control.Material.foreground + } + + background: Rectangle { + implicitWidth: 64 + implicitHeight: control.Material.buttonHeight + + radius: 4 + border.color: "black" + border.width: 1 + color: !control.enabled ? control.Material.buttonDisabledColor : control.highlighted ? control.Material.highlightedButtonColor : control.Material.buttonColor + + PaddedRectangle { + y: parent.height - 4 + width: parent.width + height: 4 + radius: 2 + topPadding: -2 + clip: true + visible: control.checkable && (!control.highlighted || control.flat) + color: control.checked + && control.enabled ? control.Material.accentColor : control.Material.secondaryTextColor + } + + // The layer is disabled when the button color is transparent so you can do + // Material.background: "transparent" and get a proper flat button without needing + // to set Material.elevation as well + layer.enabled: control.enabled && control.Material.buttonColor.a > 0 + layer.effect: ElevationEffect { + elevation: control.Material.elevation + } + + Ripple { + clipRadius: 2 + width: parent.width + height: parent.height + pressed: control.pressed + anchor: control + active: control.down || control.visualFocus || control.hovered + color: control.flat + && control.highlighted ? control.Material.highlightedRippleColor : control.Material.rippleColor + } + } +} diff --git a/gui/components/Preferences.qml b/gui/components/Preferences.qml new file mode 100644 index 00000000..e5c48286 --- /dev/null +++ b/gui/components/Preferences.qml @@ -0,0 +1,23 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 + +Page { + title: qsTr("Preferences") + + Column { + spacing: 2 + topPadding: root.width * 0.2 + leftPadding: root.width * 0.15 + rightPadding: root.width * 0.15 + + Label { + text: qsTr("Anti-censorship") + font.bold: true + } + + CheckBox { + checked: false + text: qsTr("Use Bridges") + } + } +} diff --git a/gui/components/Spinner.qml b/gui/components/Spinner.qml new file mode 100644 index 00000000..9fc535f9 --- /dev/null +++ b/gui/components/Spinner.qml @@ -0,0 +1,63 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtGraphicalEffects 1.0 + +BusyIndicator { + + id: control + + anchors.horizontalCenter: parent.horizontalCenter + + contentItem: Item { + implicitWidth: 64 + implicitHeight: 64 + + Item { + id: item + x: parent.width / 2 - 32 + y: parent.height / 2 - 32 + width: 64 + height: 64 + opacity: control.running ? 1 : 0 + + Behavior on opacity { + OpacityAnimator { + duration: 250 + } + } + + RotationAnimator { + target: item + running: control.visible && control.running + from: 0 + to: 360 + loops: Animation.Infinite + duration: 6200 + } + + Repeater { + id: repeater + model: 6 + + Rectangle { + x: item.width / 2 - width / 2 + y: item.height / 2 - height / 2 + implicitWidth: 10 + implicitHeight: 10 + radius: 5 + color: "#21be2b" + transform: [ + Translate { + y: -Math.min(item.width, item.height) * 0.5 + 5 + }, + Rotation { + angle: index / repeater.count * 360 + origin.x: 5 + origin.y: 5 + } + ] + } + } + } + } +} diff --git a/gui/components/Splash.qml b/gui/components/Splash.qml new file mode 100644 index 00000000..b4944947 --- /dev/null +++ b/gui/components/Splash.qml @@ -0,0 +1,64 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtGraphicalEffects 1.0 + +Page { + id: splash + property int timeoutInterval: 1600 + + Column { + width: parent.width * 0.8 + anchors.horizontalCenter: parent.horizontalCenter + anchors.topMargin: 24 + + VerticalSpacer { + visible: true + height: root.height * 0.10 + } + + Image { + id: connectionImage + height: 200 + anchors.horizontalCenter: parent.horizontalCenter + source: "../resources/icon-noshield.svg" + fillMode: Image.PreserveAspectFit + } + + Spinner {} + } + + Timer { + id: splashTimer + } + + function delay(delayTime, cb) { + splashTimer.interval = delayTime + splashTimer.repeat = false + splashTimer.triggered.connect(cb) + splashTimer.start() + } + + function loadMainViewWhenReady() { + console.debug("ready?") + if (ctx && ctx.isReady) { + console.debug("ready?", ctx.isReady) + // FIXME check errors == None + loader.source = "MainView.qml" + } else { + delay(100, loadMainViewWhenReady) + } + } + + Timer { + interval: timeoutInterval + running: true + repeat: false + onTriggered: { + loadMainViewWhenReady() + } + } + + Component.onCompleted: { + + } +} diff --git a/gui/components/StatusBox.qml b/gui/components/StatusBox.qml new file mode 100644 index 00000000..fa24cd89 --- /dev/null +++ b/gui/components/StatusBox.qml @@ -0,0 +1,125 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtGraphicalEffects 1.14 +import QtQuick.Layouts 1.14 + +import QtQuick.Templates 2.12 as T +import QtQuick.Controls.impl 2.12 +import QtQuick.Controls.Material 2.12 +import QtQuick.Controls.Material.impl 2.12 +import "../themes/themes.js" as Theme + +Item { + id: statusbox + anchors.fill: parent + + VPNState { + id: vpn + } + + 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 + } + + ToolButton { + id: settingsButton + objectName: "settingsButton" + 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 + + onClicked: { + if (stackView.depth > 1) { + stackView.pop() + } else { + settingsDrawer.open() + } + } + + Icon { + id: settingsImage + width: 24 + height: 24 + // TODO move arrow left to toolbar top + 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 + + BoldLabel { + id: connectionState + text: "" + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + } + + VerticalSpacer { + id: spacerPreImg + visible: false + height: 40 + } + + Image { + id: connectionImage + height: 200 + source: "../resources/spy.gif" + fillMode: Image.PreserveAspectFit + } + + VerticalSpacer { + id: spacerPostImg + visible: false + height: 35 + } + + MaterialButton { + id: toggleVPN + anchors.horizontalCenter: parent.horizontalCenter + Layout.alignment: Qt.AlignBottom + font.capitalization: Font.Capitalize + spacing: 8 + + 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/Style.qml b/gui/components/Style.qml new file mode 100644 index 00000000..acd6036e --- /dev/null +++ b/gui/components/Style.qml @@ -0,0 +1,12 @@ +import "themes.js" as Theme + +Item { + property alias fontFoo: fontFooLoader.name + readonly property color colourBlackground: "#efefef" + + // TODO use theme.background + FontLoader { + id: fontFooLoader + source: "qrc:/resources/fonts/Oxanium-Bold.ttf" + } +} diff --git a/gui/components/Systray.qml b/gui/components/Systray.qml new file mode 100644 index 00000000..6fb10467 --- /dev/null +++ b/gui/components/Systray.qml @@ -0,0 +1,27 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.4 +import Qt.labs.platform 1.0 as Labs + +Labs.SystemTrayIcon { + + visible: systrayVisible + property alias statusItem: statusItem + + menu: Labs.Menu { + + id: systrayMenu + + Labs.MenuItem { + id: statusItem + text: qsTr("Checking status…") + enabled: false + } + + Labs.MenuSeparator {} + + Labs.MenuItem { + text: qsTr("Quit") + onTriggered: backend.quit() + } + } +} diff --git a/gui/components/VPNButtonBase.qml b/gui/components/VPNButtonBase.qml new file mode 100644 index 00000000..6f677102 --- /dev/null +++ b/gui/components/VPNButtonBase.qml @@ -0,0 +1,56 @@ + + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import QtQuick 2.0 +import QtQuick.Controls 2.5 +import QtQuick.Layouts 1.14 +import "../themes/themes.js" as Theme + +RoundButton { + id: root + + property var visualStateItem: root + property var uiState: Theme.uiState + property var loaderVisible: false + property var handleKeyClick: function () { + clicked() + } + + focusPolicy: Qt.StrongFocus + Keys.onPressed: { + if (loaderVisible) { + return + } + + if (event.key === Qt.Key_Return || event.key === Qt.Key_Space) + visualStateItem.state = uiState.statePressed + } + Keys.onReleased: { + if (loaderVisible) { + return + } + if (event.key === Qt.Key_Return || event.key === Qt.Key_Space) { + visualStateItem.state = uiState.stateDefault + } + if (event.key === Qt.Key_Return) + handleKeyClick() + } + + Accessible.role: Accessible.Button + Accessible.onPressAction: handleKeyClick() + Accessible.focusable: true + + onActiveFocusChanged: { + if (!activeFocus) + return visualStateItem.state = uiState.stateDefault + + if (vpnFlickable && typeof (vpnFlickable.ensureVisible) !== "undefined") + return vpnFlickable.ensureVisible(visualStateItem) + } + + background: Rectangle { + color: "transparent" + } +} diff --git a/gui/components/VPNMouseArea.qml b/gui/components/VPNMouseArea.qml new file mode 100644 index 00000000..44d6465e --- /dev/null +++ b/gui/components/VPNMouseArea.qml @@ -0,0 +1,37 @@ +import QtQuick 2.5 +import "../themes/themes.js" as Theme + +MouseArea { + id: mouseArea + + property var targetEl: parent + property var uiState: Theme.uiState + property var onMouseAreaClicked: function () { + parent.clicked() + } + + //function changeState(stateName) { + // if (mouseArea.hoverEnabled) + // targetEl.state = stateName; + //} + anchors.fill: parent + hoverEnabled: true + cursorShape: !hoverEnabled ? Qt.ForbiddenCursor : Qt.PointingHandCursor + //onPressed: { + // console.debug("button pressed") + //changeState(uiState.statePressed) + //} + //onEntered: changeState(uiState.stateHovered) + //onExited: changeState(uiState.stateDefault) + //onCanceled: changeState(uiState.stateDefault) + + + /* + onReleased: { + if (hoverEnabled) { + changeState(uiState.stateDefault); + onMouseAreaClicked(); + } + } +*/ +} diff --git a/gui/components/VPNState.qml b/gui/components/VPNState.qml new file mode 100644 index 00000000..8856ad4a --- /dev/null +++ b/gui/components/VPNState.qml @@ -0,0 +1,193 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.12 + +import "../themes/themes.js" as Theme + +StateGroup { + + state: ctx ? ctx.status : "off" + + states: [ + State { + name: "initializing" + }, + State { + name: "off" + PropertyChanges { + target: connectionState + text: qsTr("Connection\nUnsecured") + } + PropertyChanges { + target: statusBoxBackground + border.color: Theme.accentOff + } + 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 + text: qsTr("Turn on") + } + PropertyChanges { + target: systray + icon.source: icons["off"] + } + PropertyChanges { + target: systray.statusItem + text: toHuman("off") + } + StateChangeScript { + script: { + + } + } + }, + State { + name: "on" + PropertyChanges { + target: connectionState + text: qsTr("Connection\nSecure") + } + PropertyChanges { + target: statusBoxBackground + border.color: Theme.accentOn + } + 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 + text: qsTr("Turn off") + } + PropertyChanges { + target: systray + tooltip: toHuman("on") + icon.source: icons["on"] + } + PropertyChanges { + target: systray.statusItem + text: toHuman("on") + } + StateChangeScript { + script: { + + // TODO check donation + //if (needsDonate && !shownDonate) { + // donate.visible = true; + // shownDonate = true; + // backend.donateSeen(); + //} + } + } + }, + State { + name: "starting" + //when: toggleVPN.pressed == true + PropertyChanges { + target: connectionState + text: qsTr("Connecting") + } + PropertyChanges { + target: statusBoxBackground + border.color: Theme.accentConnecting + } + PropertyChanges { + target: connectionImage + source: "../resources/birds.svg" + anchors.horizontalCenter: parent.horizontalCenter + } + PropertyChanges { + target: toggleVPN + text: qsTr("Cancel") + } + PropertyChanges { + target: systray + tooltip: toHuman("connecting") + icon.source: icons["wait"] + } + PropertyChanges { + target: systray.statusItem + text: toHuman("connecting") + } + StateChangeScript { + script: { + + } + } + }, + State { + name: "stopping" + PropertyChanges { + target: connectionState + text: "Switching\nOff" + } + PropertyChanges { + target: statusBoxBackground + border.color: Theme.accentConnecting + } + PropertyChanges { + target: systray + tooltip: toHuman("stopping") + icon.source: icons["wait"] + } + PropertyChanges { + target: systray.statusItem + text: toHuman("stopping") + } + }, + State { + name: "failed" + // TODO + } + ] + + + /* + transitions: Transition { + from: "off" + to: "starting" + reversible: true + + ParallelAnimation { + ColorAnimation { duration: 500 } + } + } + */ + function toHuman(st) { + switch (st) { + case "off": + //: %1 -> application name + return ctx ? qsTr("%1 off").arg(ctx.appName) : qsTr("off") + case "on": + //: %1 -> application name + return qsTr("%1 on").arg(ctx.appName) + case "connecting": + //: %1 -> application name + return qsTr("Connecting to %1").arg(ctx.appName) + case "stopping": + //: %1 -> application name + return qsTr("Stopping %1").arg(ctx.appName) + case "failed": + //: %1 -> application name + return qsTr("%1 blocking internet").arg( + ctx.appName) // TODO failed is not handled yet + } + } +} diff --git a/gui/components/VPNToggle.qml b/gui/components/VPNToggle.qml new file mode 100644 index 00000000..4773869f --- /dev/null +++ b/gui/components/VPNToggle.qml @@ -0,0 +1,338 @@ + + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import QtQuick 2.5 +import QtQuick.Controls 2.5 + +import "../themes/themes.js" as Theme + +VPNButtonBase { + id: toggleButton + + property var connectionRetryOverX: VPNController.connectionRetry > 1 + property var toggleColor: Theme.vpnToggleDisconnected + property var toolTipTitle: "" + Accessible.name: toolTipTitle + + function handleClick() { + toolTip.close() + if (VPNController.state !== VPNController.StateOff) { + return VPN.deactivate() + } + + return VPN.activate() + } + + onClicked: handleClick() + + // property in VPNButtonBase {} + visualStateItem: toggle + //state: VPNController.state + height: 32 + width: 60 + radius: 16 + hoverEnabled: false + + onActiveFocusChanged: { + if (!focus && toolTip.visible) { + toolTip.close() + } + } + + + /* + states: [ + State { + name: VPNController.StateInitializing + + PropertyChanges { + target: cursor + anchors.leftMargin: 4 + } + + PropertyChanges { + target: toggle + color: "#9E9E9E" + border.color: Theme.white + } + + PropertyChanges { + target: toggleButton + toggleColor: Theme.vpnToggleDisconnected + } + + }, + State { + name: VPNController.StateOff + + PropertyChanges { + target: cursor + anchors.leftMargin: 4 + } + + PropertyChanges { + target: toggle + color: "#9E9E9E" + border.color: Theme.white + } + + PropertyChanges { + target: toggleButton + //% "Turn VPN on" + toolTipTitle: qsTrId("vpn.toggle.on") + } + + }, + State { + name: VPNController.StateConnecting + + PropertyChanges { + target: cursor + anchors.leftMargin: 32 + color: "#998DB2" + } + + PropertyChanges { + target: toggle + color: "#387E8A" + border.color: Theme.ink + } + + PropertyChanges { + target: toggleButton + //% "Turn VPN off" + toolTipTitle: qsTrId("vpn.toggle.off") + toggleColor: Theme.vpnToggleConnected + } + + }, + State { + name: VPNController.StateConfirming + + PropertyChanges { + target: cursor + anchors.leftMargin: 32 + color: connectionRetryOverX ? "#FFFFFF" : "#998DB2" + } + + PropertyChanges { + target: toggle + color: "#387E8A" + border.color: Theme.ink + } + + PropertyChanges { + target: toggleButton + //% "Turn VPN off" + toolTipTitle: qsTrId("vpn.toggle.off") + toggleColor: Theme.vpnToggleConnected + } + + }, + State { + name: VPNController.StateOn + + PropertyChanges { + target: cursor + anchors.leftMargin: 32 + } + + PropertyChanges { + target: toggle + color: "#3FE1B0" + border.color: Theme.ink + } + + PropertyChanges { + target: toggleButton + toolTipTitle: qsTrId("vpn.toggle.off") + toggleColor: Theme.vpnToggleConnected + } + + }, + State { + name: VPNController.StateDisconnecting + + PropertyChanges { + target: cursor + anchors.leftMargin: 4 + } + + PropertyChanges { + target: toggle + color: "#CECECE" + border.color: Theme.white + } + + PropertyChanges { + target: toggleButton + toolTipTitle: qsTrId("vpn.toggle.on") + toggleColor: Theme.vpnToggleDisconnected + } + + }, + State { + name: VPNController.StateSwitching + + PropertyChanges { + target: cursor + anchors.leftMargin: 32 + color: "#998DB2" + } + + PropertyChanges { + target: toggle + color: "#387E8A" + border.color: Theme.ink + } + + PropertyChanges { + target: toggleButton + toggleColor: Theme.vpnToggleConnected + } + + } + ] + transitions: [ + Transition { + ParallelAnimation { + NumberAnimation { + target: cursor + property: "anchors.leftMargin" + duration: 200 + } + + ColorAnimation { + target: cursor + duration: 200 + } + + } + + } + ] + + // Focus rings + VPNFocusBorder { + id: focusHandler + + anchors.fill: toggle + anchors.margins: -4 + radius: height / 2 + border.color: toggleColor.focusBorder + color: "transparent" + opacity: toggleButton.activeFocus && (VPNController.state === VPNController.StateOn || VPNController.state === VPNController.StateOff) ? 1 : 0 + + VPNFocusOutline { + id: vpnFocusOutline + + anchors.fill: focusHandler + focusedComponent: focusHandler + setMargins: -6 + radius: height / 2 + border.width: 7 + color: "transparent" + border.color: toggleColor.focusOutline + opacity: 0.25 + } + + } + + // Faint outline visible on hover and press + Rectangle { + id: hoverPressHandler + + color: "#C2C2C2" + state: toggle.state + opacity: { + if (state === uiState.stateDefault || toggleButton.activeFocus) + return 0; + + if (state === uiState.stateHovered) + return 0.2; + + if (state === uiState.statePressed) + return 0.3; + + } + z: -1 + anchors.fill: toggle + radius: height / 2 + anchors.margins: -5 + + PropertyAnimation on opacity { + duration: 200 + } + + } + */ + function toggleClickable() { + return VPN.state === VPN.StateMain + && (VPNController.state === VPNController.StateOn + || VPNController.state === VPNController.StateOff + || (VPNController.state === VPNController.StateConfirming + && connectionRetryOverX)) + } + + // Toggle background color changes on hover and press + VPNUIStates { + itemToFocus: toggleButton + itemToAnchor: toggle + colorScheme: toggleColor + radius: height / 2 + setMargins: -7 + showFocusRings: false + opacity: toggleClickable() ? 1 : 0 + z: 1 + + Behavior on opacity { + PropertyAnimation { + property: "opacity" + duration: 100 + } + } + } + + Rectangle { + id: cursor + + height: 24 + width: 24 + radius: 12 + anchors.left: parent.left + anchors.top: parent.top + anchors.topMargin: 4 + z: 2 + } + + VPNMouseArea { + id: mouseArea + + targetEl: toggle + anchors.fill: toggle + hoverEnabled: toggleClickable() + cursorShape: Qt.PointingHandCursor + } + + VPNToolTip { + id: toolTip + text: toolTipTitle + } + + background: Rectangle { + id: toggle + + Component.onCompleted: state = uiState.stateDefault + border.width: 0 + anchors.fill: toggleButton + radius: height / 2 + + Behavior on color { + ColorAnimation { + duration: 200 + } + } + } +} diff --git a/gui/components/VerticalSpacer.qml b/gui/components/VerticalSpacer.qml new file mode 100644 index 00000000..455e4daf --- /dev/null +++ b/gui/components/VerticalSpacer.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 + +Rectangle { + color: "transparent" + width: parent.width +} diff --git a/gui/gui.qrc b/gui/gui.qrc index 30997279..dde4c8fd 100644 --- a/gui/gui.qrc +++ b/gui/gui.qrc @@ -1,7 +1,50 @@ <RCC> <qresource prefix="/"> - <file>qml/main.qml</file> + <file>main.qml</file> + + <file>themes/themes.js</file> + <file>components/MainView.qml</file> + <file>components/Splash.qml</file> + <file>components/Home.qml</file> + <file>components/Header.qml</file> + <file>components/Footer.qml</file> + <file>components/StatusBox.qml</file> + <file>components/Spinner.qml</file> + <file>components/Systray.qml</file> + <file>components/Help.qml</file> + <file>components/Locations.qml</file> + <file>components/Preferences.qml</file> + <file>components/BoldLabel.qml</file> + <file>components/LightLabel.qml</file> + <file>components/VPNButtonBase.qml</file> + <file>components/VPNMouseArea.qml</file> + <file>components/VerticalSpacer.qml</file> + <file>components/Icon.qml</file> + <file>components/MaterialButton.qml</file> + <file>components/VPNState.qml</file> + <file>resources/icon-noshield.svg</file> + <file>resources/location.svg</file> + <file>resources/settings.svg</file> + <file>resources/power.svg</file> + <file>resources/close.svg</file> + <file>resources/donate.svg</file> + <file>resources/tools.svg</file> + <file>resources/help.svg</file> + <file>resources/about.svg</file> + <file>resources/bridge.png</file> + <file>resources/gear-fill.svg</file> + <file>resources/reception-0.svg</file> + <file>resources/reception-2.svg</file> + <file>resources/reception-4.svg</file> + <file>resources/arrow-left.svg</file> + <file>resources/globe.svg</file> + <file>resources/birds.svg</file> + <file>resources/riseup-icon.svg</file> + <file>resources/spy.gif</file> + <file>resources/quit.svg</file> + + <!-- old, to remove --> <file>qml/VpnState.qml</file> <file>qml/AboutDialog.qml</file> <file>qml/DonateDialog.qml</file> @@ -14,6 +57,7 @@ <file>qml/VPNSwitch.qml</file> <file>qml/BridgesItem.qml</file> <file>qml/logic.js</file> + <!-- 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.cpp b/gui/main.cpp index d10cb51c..d136c3c1 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -5,6 +5,7 @@ #include <QTranslator> #include <QCommandLineParser> #include <QQuickWindow> +#include <QQuickStyle> #include <QSystemTrayIcon> #include <QtQml> @@ -137,9 +138,8 @@ int main(int argc, char **argv) { exit(0); } - if (hideSystray) { + if (hideSystray) qDebug() << "Not showing systray icon because --no-systray option is set."; - } if (installHelpers) { qDebug() << "Will try to install helpers with sudo"; @@ -159,11 +159,13 @@ int main(int argc, char **argv) { availableSystray = false; } + /* set window icon */ + app.setWindowIcon(QIcon(":/vendor/icon.svg")); + + /* load translations */ QTranslator translator; translator.load(QLocale(), QLatin1String("main"), QLatin1String("_"), QLatin1String(":/i18n")); app.installTranslator(&translator); - /* set window icon */ - app.setWindowIcon(QIcon(":/vendor/icon.svg")); QQmlApplicationEngine engine; @@ -172,6 +174,7 @@ int main(int argc, char **argv) { QJsonModel *model = new QJsonModel; QString desktop = QString::fromStdString(getEnv("XDG_CURRENT_DESKTOP")); + QString debug = QString::fromStdString(getEnv("DEBUG")); /* the backend handler has slots for calling back to Go when triggered by signals in Qml. */ @@ -185,8 +188,10 @@ int main(int argc, char **argv) { /* set some useful flags */ ctx->setContextProperty("systrayVisible", !hideSystray); ctx->setContextProperty("systrayAvailable", availableSystray); + ctx->setContextProperty("qmlDebug", debug == "1"); - engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); + QQuickStyle::setStyle("Material"); + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); /* connect the jsonChanged signal explicitely. In the lambda, we reload the json in the model every time we receive an @@ -215,9 +220,11 @@ int main(int argc, char **argv) { obfs4, disAutostart, toGoStr(startVPN)); /* if requested, enable web api for controlling the VPN */ - if (webAPI) { + if (webAPI) EnableWebAPI(toGoStr(webPort)); - }; + + if (engine.rootObjects().isEmpty()) + return -1; /* kick off your shoes, put your feet up */ return app.exec(); diff --git a/gui/main.qml b/gui/main.qml new file mode 100644 index 00000000..16677a27 --- /dev/null +++ b/gui/main.qml @@ -0,0 +1,116 @@ +/* + 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 + - [ ] minimize/hide from systray + - [ ] parse ctx flags (need dialog, etc) + - [ ] gateway selector + - [ ] bridges +*/ + +import QtQuick 2.0 +import QtQuick.Controls 2.4 +import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Material 2.1 +import QtQuick.Layouts 1.14 + +import "./components" + +ApplicationWindow { + + id: root + + visible: true + width: 360 + height: 520 + minimumWidth: 300 + maximumWidth: 300 + minimumHeight: 500 + maximumHeight: 500 + + title: ctx ? ctx.appName : "VPN" + Material.accent: Material.Green + + property var ctx + + property var icons: { + "off": "qrc:/assets/icon/png/white/vpn_off.png", + "on": "qrc:/assets/icon/png/white/vpn_on.png", + "wait": "qrc:/assets/icon/png/white/vpn_wait_0.png", + "blocked": "qrc:/assets/icon/png/white/vpn_blocked.png" + } + + Loader { + id: loader + asynchronous: true + anchors.fill: parent + } + + Systray { + id: systray + } + + Connections { + target: jsonModel + function onDataChanged() { + ctx = JSON.parse(jsonModel.getJson()) + if (qmlDebug) { + console.debug(jsonModel.getJson()) + } + + // 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 + } + */ + } + } + + onSceneGraphError: function(error, msg) { + console.debug("ERROR while initializing scene") + console.debug(msg) + } + + Component.onCompleted: { + loader.source = "components/Splash.qml" + } +} diff --git a/gui/providers/providers.json b/gui/providers/providers.json index 8592ba05..52fcbf93 100644 --- a/gui/providers/providers.json +++ b/gui/providers/providers.json @@ -15,7 +15,7 @@ "apiURL": "https://api.black.riseup.net/", "geolocationAPI": "https://api.black.riseup.net:9001/json", "caCertString": "-----BEGIN CERTIFICATE-----\nMIIFjTCCA3WgAwIBAgIBATANBgkqhkiG9w0BAQ0FADBZMRgwFgYDVQQKDA9SaXNl\ndXAgTmV0d29ya3MxGzAZBgNVBAsMEmh0dHBzOi8vcmlzZXVwLm5ldDEgMB4GA1UE\nAwwXUmlzZXVwIE5ldHdvcmtzIFJvb3QgQ0EwHhcNMTQwNDI4MDAwMDAwWhcNMjQw\nNDI4MDAwMDAwWjBZMRgwFgYDVQQKDA9SaXNldXAgTmV0d29ya3MxGzAZBgNVBAsM\nEmh0dHBzOi8vcmlzZXVwLm5ldDEgMB4GA1UEAwwXUmlzZXVwIE5ldHdvcmtzIFJv\nb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC76J4ciMJ8Sg0m\nTP7DF2DT9zNe0Csk4myoMFC57rfJeqsAlJCv1XMzBmXrw8wq/9z7XHv6n/0sWU7a\n7cF2hLR33ktjwODlx7vorU39/lXLndo492ZBhXQtG1INMShyv+nlmzO6GT7ESfNE\nLliFitEzwIegpMqxCIHXFuobGSCWF4N0qLHkq/SYUMoOJ96O3hmPSl1kFDRMtWXY\niw1SEKjUvpyDJpVs3NGxeLCaA7bAWhDY5s5Yb2fA1o8ICAqhowurowJpW7n5ZuLK\n5VNTlNy6nZpkjt1QycYvNycffyPOFm/Q/RKDlvnorJIrihPkyniV3YY5cGgP+Qkx\nHUOT0uLA6LHtzfiyaOqkXwc4b0ZcQD5Vbf6Prd20Ppt6ei0zazkUPwxld3hgyw58\nm/4UIjG3PInWTNf293GngK2Bnz8Qx9e/6TueMSAn/3JBLem56E0WtmbLVjvko+LF\nPM5xA+m0BmuSJtrD1MUCXMhqYTtiOvgLBlUm5zkNxALzG+cXB28k6XikXt6MRG7q\nhzIPG38zwkooM55yy5i1YfcIi5NjMH6A+t4IJxxwb67MSb6UFOwg5kFokdONZcwj\nshczHdG9gLKSBIvrKa03Nd3W2dF9hMbRu//STcQxOailDBQCnXXfAATj9pYzdY4k\nha8VCAREGAKTDAex9oXf1yRuktES4QIDAQABo2AwXjAdBgNVHQ4EFgQUC4tdmLVu\nf9hwfK4AGliaet5KkcgwDgYDVR0PAQH/BAQDAgIEMAwGA1UdEwQFMAMBAf8wHwYD\nVR0jBBgwFoAUC4tdmLVuf9hwfK4AGliaet5KkcgwDQYJKoZIhvcNAQENBQADggIB\nAGzL+GRnYu99zFoy0bXJKOGCF5XUXP/3gIXPRDqQf5g7Cu/jYMID9dB3No4Zmf7v\nqHjiSXiS8jx1j/6/Luk6PpFbT7QYm4QLs1f4BlfZOti2KE8r7KRDPIecUsUXW6P/\n3GJAVYH/+7OjA39za9AieM7+H5BELGccGrM5wfl7JeEz8in+V2ZWDzHQO4hMkiTQ\n4ZckuaL201F68YpiItBNnJ9N5nHr1MRiGyApHmLXY/wvlrOpclh95qn+lG6/2jk7\n3AmihLOKYMlPwPakJg4PYczm3icFLgTpjV5sq2md9bRyAg3oPGfAuWHmKj2Ikqch\nTd5CHKGxEEWbGUWEMP0s1A/JHWiCbDigc4Cfxhy56CWG4q0tYtnc2GMw8OAUO6Wf\nXu5pYKNkzKSEtT/MrNJt44tTZWbKV/Pi/N2Fx36my7TgTUj7g3xcE9eF4JV2H/sg\ntsK3pwE0FEqGnT4qMFbixQmc8bGyuakr23wjMvfO7eZUxBuWYR2SkcP26sozF9PF\ntGhbZHQVGZUTVPyvwahMUEhbPGVerOW0IYpxkm0x/eaWdTc4vPpf/rIlgbAjarnJ\nUN9SaWRlWKSdP4haujnzCoJbM7dU9bjvlGZNyXEekgeT0W2qFeGGp+yyUWw8tNsp\n0BuC1b7uW/bBn/xKm319wXVDvBgZgcktMolak39V7DVO\n-----END CERTIFICATE-----", - "timeStamp": "2021-07-09 20:10:58" + "timeStamp": "2021-08-25 00:56:22" } ] } \ No newline at end of file diff --git a/gui/qml/BackgroundImage.qml b/gui/qml/BackgroundImage.qml index 3071bf45..ba2a8af0 100644 --- a/gui/qml/BackgroundImage.qml +++ b/gui/qml/BackgroundImage.qml @@ -3,22 +3,22 @@ import QtQuick.Controls 2.4 Rectangle { - anchors.fill: parent; - anchors.topMargin: 40; + anchors.fill: parent + anchors.topMargin: 40 property var backgroundSrc property var backgroundVisible Image { - source: parent.backgroundSrc; - visible: parent.backgroundVisible; - fillMode: Image.PreserveAspectCrop; - anchors.fill: parent; - opacity: 0.8; + source: parent.backgroundSrc + visible: parent.backgroundVisible + fillMode: Image.PreserveAspectCrop + anchors.fill: parent + opacity: 0.8 } Component.onCompleted: { /* default for riseup, needs customizing */ - backgroundSrc = "qrc:/assets/img/bird.jpg"; + backgroundSrc = "qrc:/assets/img/bird.jpg" } } diff --git a/gui/qml/BridgesItem.qml b/gui/qml/BridgesItem.qml index 1343403a..f7ccb0f1 100644 --- a/gui/qml/BridgesItem.qml +++ b/gui/qml/BridgesItem.qml @@ -26,15 +26,15 @@ Item { anchors.horizontalCenter: parent.horizontalCenter onClicked: { if (checked) { - Logic.setNeedsReconnect(true); - bridgeReconnect.visible = true; - app.useBridges(true); + Logic.setNeedsReconnect(true) + bridgeReconnect.visible = true + app.useBridges(true) } else { // This would also need a "needs reconnect" for de-selecting bridges the next time. // better to wait and see the new connection widgets though - Logic.setNeedsReconnect(false); - bridgeReconnect.visible = false; - app.useBridges(false); + Logic.setNeedsReconnect(false) + bridgeReconnect.visible = false + app.useBridges(false) } } } @@ -45,7 +45,7 @@ Item { color: "grey" text: qsTr("Select a bridge only if you know that you need it to evade censorship in your country or local network.") anchors.horizontalCenter: parent.horizontalCenter - wrapMode: Text.WordWrap + wrapMode: Text.WordWrap visible: !bridgeReconnect.visible } @@ -56,7 +56,7 @@ Item { color: "red" text: qsTr("An obfs4 bridge will be used the next time you connect to the VPN.") anchors.horizontalCenter: parent.horizontalCenter - wrapMode: Text.WordWrap + wrapMode: Text.WordWrap visible: false } } diff --git a/gui/qml/VPNSwitch.qml b/gui/qml/VPNSwitch.qml index 89c455f4..c58836e4 100644 --- a/gui/qml/VPNSwitch.qml +++ b/gui/qml/VPNSwitch.qml @@ -2,7 +2,6 @@ import QtQuick 2.9 import QtQuick.Layouts 1.12 import QtQuick.Controls 2.4 - SwitchDelegate { text: qsTr("") diff --git a/gui/qml/VpnState.qml b/gui/qml/VpnState.qml index a4bb7791..31910c74 100644 --- a/gui/qml/VpnState.qml +++ b/gui/qml/VpnState.qml @@ -14,7 +14,7 @@ StateGroup { State { name: "off" StateChangeScript { - script: Logic.setStatus("off"); + script: Logic.setStatus("off") } PropertyChanges { target: systray @@ -47,16 +47,15 @@ StateGroup { name: "on" StateChangeScript { script: { - Logic.setNeedsReconnect(false); - brReconnect = false; + Logic.setNeedsReconnect(false) + brReconnect = false if (needsDonate && !shownDonate) { - donate.visible = true; - shownDonate = true; - backend.donateSeen(); + donate.visible = true + shownDonate = true + backend.donateSeen() } } - } PropertyChanges { target: systray diff --git a/gui/qml/main.qml b/gui/qml/main.qml index fef68cf2..2c94c80f 100644 --- a/gui/qml/main.qml +++ b/gui/qml/main.qml @@ -1,9 +1,10 @@ import QtQuick 2.9 -import QtQuick.Dialogs 1.2 // TODO use native dialogs in labs.platform +import QtQuick.Dialogs 1.2 +// TODO use native dialogs in labs.platform import QtQuick.Layouts 1.12 import QtQuick.Controls 2.4 -import Qt.labs.platform 1.0 +import Qt.labs.platform 1.0 as Labs import "logic.js" as Logic @@ -24,7 +25,7 @@ ApplicationWindow { property var needsDonate property var shownDonate - onSceneGraphError: function(error, msg) { + onSceneGraphError: function (error, msg) { console.debug("ERROR while initializing scene") console.debug(msg) } @@ -116,8 +117,8 @@ ApplicationWindow { anchors.centerIn: parent spacing: 10 - //width: parent.width + //width: parent.width RadioButton { id: autoSelectionButton checked: !isManualLocation() @@ -161,6 +162,7 @@ ApplicationWindow { color: { "#ffffff" // FIXME locations is not defined when we launch + /* const fullness = ctx.locations[modelData] if (fullness >= 0 && fullness < 0.4) { @@ -181,7 +183,6 @@ ApplicationWindow { color: "#000000" } } - } Text { @@ -190,7 +191,7 @@ ApplicationWindow { width: 180 font.pixelSize: 12 color: "green" - wrapMode: Text.WordWrap + wrapMode: Text.WordWrap text: qsTr("Reconnecting to the selected gateway…") visible: false } @@ -201,31 +202,29 @@ ApplicationWindow { width: 180 font.pixelSize: 12 color: "green" - wrapMode: Text.WordWrap + wrapMode: Text.WordWrap text: qsTr("This gateway will be used for next connection.") visible: false } - } // end column } // end item BridgesItem { id: bridgesTab } - } // end stacklayout Connections { target: jsonModel function onDataChanged() { ctx = JSON.parse(jsonModel.getJson()) + // TODO pass QML_DEBUG variable to be hyper-verbose //console.debug(jsonModel.getJson()) - gwSelector.model = Object.keys(ctx.locations) if (ctx.donateDialog == 'true') { - Logic.setNeedsDonate(true); + Logic.setNeedsDonate(true) } if (ctx.loginDialog == 'true') { console.debug(jsonModel.getJson()) @@ -294,11 +293,11 @@ ApplicationWindow { function hasMultipleGateways() { // could also count the gateways - let provider = Logic.getSelectedProvider(providers); + let provider = Logic.getSelectedProvider(providers) if (provider == "riseup") { - return true; + return true } else { - return false; + return false } } @@ -319,35 +318,34 @@ ApplicationWindow { } function showMainWindow() { - bar.currentIndex = 0 - app.visible = true - app.show() - app.raise() + bar.currentIndex = 0 + app.visible = true + app.show() + app.raise() } Component.onCompleted: { Logic.debugInit() loginDone = false allowEmptyPass = Logic.shouldAllowEmptyPass(providers) - needsRestart = false; - shownDonate = false; + needsRestart = false + shownDonate = false /* this is a temporary workaround until general GUI revamp for 0.21.8 */ - let provider = Logic.getSelectedProvider(providers); + let provider = Logic.getSelectedProvider(providers) if (provider == "calyx") { - background.color = "#8EA844"; - background.backgroundVisible = false; - gwSelector.visible = false; - manualSelectionButton.visible = false; + background.color = "#8EA844" + background.backgroundVisible = false + gwSelector.visible = false + manualSelectionButton.visible = false } if (!systrayAvailable) { - app.visible = true - app.raise() + app.visible = true + app.raise() } } - property var icons: { "off": "qrc:/assets/icon/png/white/vpn_off.png", "on": "qrc:/assets/icon/png/white/vpn_on.png", @@ -364,6 +362,7 @@ ApplicationWindow { id: systray visible: systrayVisible + /* the systray menu cannot be buried in a child qml file because * otherwise the ids are not available * from other components @@ -501,9 +500,8 @@ ApplicationWindow { if (Qt.platform.os === "windows") { let appname = ctx ? ctx.appName : "VPN" Logic.showNotification( - ctx, - appname - + " is up and running. Please use system tray icon to control it.") + ctx, appname + + " is up and running. Please use system tray icon to control it.") } } } @@ -560,13 +558,12 @@ ApplicationWindow { } function useBridges(value) { - if (value==true) { + if (value == true) { backend.setTransport("obfs4") } else { backend.setTransport("openvpn") } } - property alias brReconnect:bridgesTab.displayReconnect - + property alias brReconnect: bridgesTab.displayReconnect } diff --git a/gui/qml/readme.txt b/gui/qml/readme.txt new file mode 100644 index 00000000..e7d468c7 --- /dev/null +++ b/gui/qml/readme.txt @@ -0,0 +1 @@ +This folder will be deprecated. diff --git a/gui/resources/about.svg b/gui/resources/about.svg new file mode 100644 index 00000000..9a47ce3e --- /dev/null +++ b/gui/resources/about.svg @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + width="90.946px" height="90.945px" viewBox="0 0 90.946 90.945" style="enable-background:new 0 0 90.946 90.945;" + xml:space="preserve"> +<g> + <g> + <polygon points="68.801,9.457 67.946,12.356 69.498,11.851 "/> + <polygon points="46.716,25.955 47.535,28.557 48.722,27.438 "/> + <path d="M79.788,35.755c-2.208,1.979-5.452,4.616-8.333,7.148c-0.317-4.402-1.093-8.953-1.093-12.952 + c0.009-6.419,0.688-15.586-0.876-16.621l-1.574,0.004c-1.254,1.424-0.876,8.642-1.177,14.274 + c-0.217,4.113-0.603,9.976-0.784,15.173c-2.353-1.979-4.863-3.852-6.821-5.812c-3.533-3.542-8.271-8.913-9.739-8.579L48.484,29.3 + c0.062,1.509,4.896,5.131,7.826,8.408c2.861,3.194,6.629,8.42,9.923,11.714c0.232,0.23,0.511,0.374,0.803,0.46 + c0.471,0.319,1.045,0.516,1.67,0.516c0.584,0,1.088-0.205,1.528-0.492c0.356-0.078,0.698-0.21,0.981-0.466 + c3.325-3.013,5.982-7.323,9.005-10.343c3.541-3.532,9.07-8.318,8.739-9.787l-0.91-0.904 + C86.543,28.471,83.063,32.829,79.788,35.755z"/> + <polygon points="68.361,55.795 70.085,51.603 67.378,51.762 "/> + <polygon points="88.666,27.691 90.061,28.529 90.946,26.198 "/> + <polygon points="22.144,35.151 21.449,37.545 23,38.05 "/> + <polygon points="43.411,54.25 44.23,51.647 42.224,53.131 "/> + <path d="M31.815,62.665c-1.958,1.96-4.471,3.835-6.823,5.812c-0.18-5.196-0.568-11.059-0.783-15.174 + c-0.303-5.63,0.078-12.848-1.179-14.272l-1.572-0.005c-1.566,1.032-0.886,10.203-0.879,16.622c0.003,3.997-0.772,8.55-1.09,12.952 + c-2.882-2.532-6.125-5.169-8.333-7.148c-3.272-2.927-6.755-7.286-8.262-7.35l-0.911,0.905c-0.332,1.469,5.202,6.255,8.739,9.788 + c3.022,3.016,5.681,7.329,9.007,10.343c0.28,0.25,0.624,0.388,0.979,0.465c0.441,0.287,0.943,0.493,1.527,0.493 + c0.626,0,1.201-0.196,1.671-0.516c0.294-0.087,0.573-0.23,0.803-0.461c3.296-3.294,7.063-8.518,9.925-11.714 + c2.929-3.277,7.76-6.899,7.825-8.407l-0.907-0.91C40.084,53.753,35.348,59.125,31.815,62.665z"/> + <polygon points="22.585,81.488 23.568,77.456 20.86,77.296 "/> + <polygon points="0,51.892 0.885,54.223 2.281,53.386 "/> + </g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +</svg> diff --git a/gui/resources/arrow-left.svg b/gui/resources/arrow-left.svg new file mode 100644 index 00000000..9d885017 --- /dev/null +++ b/gui/resources/arrow-left.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left" viewBox="0 0 16 16"> + <path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z"/> +</svg> \ No newline at end of file diff --git a/gui/resources/birds.svg b/gui/resources/birds.svg new file mode 100644 index 00000000..cb2a1df0 --- /dev/null +++ b/gui/resources/birds.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 174.92 102.4"><title>Asset 1</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><g id="C0eYCH.tif"><image id="Layer_1-3" data-name="Layer 1" width="277" height="129" transform="translate(12.45) rotate(9.34) scale(0.59)" xlink:href="data:image/png;base64,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"/></g></g></g></svg> \ No newline at end of file diff --git a/gui/resources/bridge.png b/gui/resources/bridge.png new file mode 100644 index 0000000000000000000000000000000000000000..d0a2c80189a6a60166aef9d785bcbd6e144bd32b GIT binary patch literal 5543 zcmeHLX;f3!7EV+|844;?iug=ZEtAR3L?#lDnNWcM!75ty-sA?ZW@>U{0)1MG6IR8! zB3OmufVF4~SP=#5fLe8xiWE^15v^DeEKVR6>A3+RzWVHQt=E6TO2|3q+uz>jJA3cL z&2ni>grl9i9f?G8lthNcgTHRXYuHfm-e?kcl1PIdq{*h@@vw=a(`%KO3Z>wwI+TK% zF(rv)zTEmnT;@$Lho#p9l^*0PZaFuchgCPsUVY@qdfCoBWz)0IpF11n>O#qU^6oQ- zM69P{+r|ZrUnwWJ`t2*MUAd>Ex-|dBlfzwc3G|5h0iuTU#p0`w+xtPj&G{G4_Q1QQ zH>!kbT|uW$JwiTNaQ@7Wdr<Jj(2>3ferrMv{oU&iY(5&){l_;ma;}_;t$SQtesUZ9 z!<S!;^e@q_z1WOoG|1eRq>f&<GJ8ptO=SIs?fEwfB<>y(hxuW@UDp>5AwThnd2;;g zYTu2ABCgfV%8eAa4qw_lyY^6bbxfD>_X{JMoY-eelNS`_)F+5+1a13w?%MzOK}*{1 zVOV*<oy-`#vGm=WdWSt;OQ)Ydkk4_6J>5VSvR5C@bC`4DhoXX?x5un_oIjTH?TKUl zW0G!>rLcji5smlM`NXAsCs{u{ed1uV&6J9Z!KV(lW@%>g&WVO^o$Q<+xy0p{YhKsv z3SGTpH*{yZ)>f`vJT-jH3ip|$;Fh%!X+t{WX6|eBp%g@9jU89_U|y6e>O)P~zkVbq zH5Q~)se`x>dGRoV@7p1R1|3}Im3Zc)Dl{X1QS7oc#V!pC7s^tRjWa@h8u_Q{-Q;*@ z(S7XXW*cW8*DF7g3l=4Ms7{ab&GfiahlC~W$u8rzCeGQNG<U!IvRS<EkU77ctIsx$ zhW5_9TECumZ&gmCu4YP(pSJK(ro?}Pf4GVNu%i9_>6h?5IqHi2g-+Y6yh0+zaz(4S zT{pc)HJ|wA!p<u0(-{AF3_8?iJaDz+`;H~D=|yL%6F1RjsUPLI?-<px>wZhk?Vwdo z@z+y$ehz-0L`pq8-Oo*0Y5!TN4S77rw)n2hZr7yI=k)TscIY?pgMZpi8JdoI)`sy8 zZM(U(bVvNNj4^?ycTDQw5pRwMtLiIqxi>B<6%yOLx}_s(Ce|&`)s+`_bjCgXmD}C6 z@W9X0Z_^&Won~LYq#?LxT;7sEC&y2#dj{{j|J5bwZr@B2iM$vK36V-dLY}8TNct`F z*NP*LPx7do6?lTW@vT-$)0#ZtG-p?1jgL!SaDi)*k#X>$eKu#jH$5|b?$M*GE5BZ} zqImCHd($bM<fdD<w%?{scm{cwWVAPyj=R?;ZfhVvQ*PX?)Hz7~&Ys@BE|`AA=V1kP zu@^NfT#D=r@cbMzXYTu?vomc|<Ftn6XCB>AM->ZWDO=Gpc!btDR-Ghlp5Nr=`+;4% zpuHey^!Nog%kJJE)4cBZg01hci#De=xqT<SgB)Bj?UHo4=kgn$e;rp5*j#ihbwzPf zVew<}6Z_*fYIJi8XW5!#)GsK(3s(w#3XTP*Pg&(M>YdB6X`QxXk3`Zp&v0evC*}@y zU3bH_XVJB**_F#b=6P=!k~UNIRPJ{Bs!fvPm1hCpx7H4KHV@rfl6j<dh%!K;#Y;Lz zIA0n{-|L@!*mg!6X>e?rA~Mq@_c!S6&pOy$J4MdrHeI##4VRzt=aY(R61#@-`9s2^ zHk7xuw@FRfo~>9%$6zc$pTD!{xR6A0T7iLfG&Op%P_9+eVTBe!>1MSKv?~%x6lm7L z^0_EZLC|DOBc|Rvbc9O56k_U!e$k9*T?m?jMW*S|gtQo$JZ-LApr8f@*on+SK%ho( zm||9|GzOtrOttU|!DnI`qEajne6E-}HCjpu(dtnOht8ohXklh-9*Y`aM-k~2N@09x zcpn8AiK!_#t`kC#$z-CN*mSKv8Da_q0*JwaSS%Vq&<v>>95&N5hW7}HUXD=IAlG9$ z9Mftj1SgDWjkuUf1?!YPa<D27GlR)K2gKMyZ@?9h1PnM}KL7x+7z{p*!J@GQkhMKn zjgIcO))@L!1bRYdSO+ob3`nhh!NP!t%^UFdQVW9&+zL=UYS0?>ax`ons=?p0cB)eu z4c0!529%hx#H~^&ArO?sv$aixBwE^UL&%tnsdW|$0&R^{$op|Rqh4jfDC7{TLe(G; z17K#pfX6ZAzyZCmA7bS%fdF^?{4b!N>t%_>qN^}eD>o8OC81&}5wB38m17E_<s%Gp z89WYyO=Bq-JQ|0|LuiPA$D#??EUsM6;`14No)wiuW58jJ93`j#IUNH$avq{Y7=ADf zWrLID@OTUwBIh79rjq3cvk--Xfv~M8V)YoP1XyJq6+xu{R7x0TA_{~{<0%j}jRW&p zG(N&t(s(Q;Psw5UDOqf#g^D-_VUScJrn2aaff=a^#+6#VT1=gcX^iH91sSGB6L6Ri zjmc#R*nGYpi^2EfvN?hQ&=gc}07*`8G8uFh%d(=73&Q~;43Z5~!^tS5(<ECKh+`3g z%>ZFxqBa1tWghHB7@|jET&tI9wJI@{h?PQ6T1tu{>MIuEWUbs{XaS=NqTc!{E*MUR zEJG3WD)3*J5>m7#&Hu(T0PSZ9(&Hwrer~Kj7MX*}@mKS_4BXEY4|<&e*QZMUW>f!x z6ZNKRB(T-$Q?2|bpda^+dK;1ovq(juSek$kmiNkUfajqK%Mkz_dza)XuqGJ=-L|jP zp3h@1Nn^GjU%_SaxHMRx<b&J;HG!ZAN>lhLnGBf8<uet%8PU&f&?<2gtVe^AK@Na( z2Bl>=XNs34`@CO_#gu}A9PwqagbW6?_joBHh-j$Kw<jW6PIR=;S^yEzl7tc>^Ae0Y zoeD$sFADQKQT_|g%Dyit|IXYR)@vQ2)un=>O~GSLnpe7i39y%8GA2hg2JNdtw}$k} zVs-C;n0x2IeFm;asQ-TKOADfM{=uKVbo&QA0O~hRUQ6FMa=nr3wG?<Q@SE&<BiCyw z@LJ$E+4X;u%WmKa8`Xe+^i1ISIsA-sF?jYKihK|eO6nngbIW(F2Q$NUk<$z$lKm*+ zMJ8o$A--9(#U;^Uw!aP=<-~JICFLf9FIe7^ga*kXPqo&RM}-7A+cd^H+S%2T_Yc3E zRFJ!|%K6(2r`(K>x(<Jq+j(L6j>0by&pO|XRp~ptOX9~Dc;CD{xpCyk^;sJ_en69( zxA-T|oBD;rJ6)C1O=V#dVFzP<lhWDIrF~(9$9u~kF)NV3N~iWkS7mfb<<q0%x)T+p z(G}@7cdwVPx;5A~Z_h)7v5Zw4*P=V)9+kJPwRX1etr@NQ4Zr-XJwP?ooe1^$@Ypnb z|40M0t26xYmdmT<j#bf*0u56g@7sH3o#fpwb%FzGzm)xZQ`4QSAo7^@o(WssV-iX~ z|7rcF4P`?v@+%d-M^myM%5@DA+3gFnD+Ge-l24C+AhIcMavgoCB?tb!)5iV};rkP8 Sg1doOBuQ9I=-%Mj>3;$X%Q1HV literal 0 HcmV?d00001 diff --git a/gui/resources/close.svg b/gui/resources/close.svg new file mode 100644 index 00000000..ead8e169 --- /dev/null +++ b/gui/resources/close.svg @@ -0,0 +1,3 @@ +<svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M6.22566 4.81096C5.83514 4.42044 5.20197 4.42044 4.81145 4.81096C4.42092 5.20148 4.42092 5.83465 4.81145 6.22517L10.5862 11.9999L4.81151 17.7746C4.42098 18.1651 4.42098 18.7983 4.81151 19.1888C5.20203 19.5793 5.8352 19.5793 6.22572 19.1888L12.0004 13.4141L17.7751 19.1888C18.1656 19.5793 18.7988 19.5793 19.1893 19.1888C19.5798 18.7983 19.5798 18.1651 19.1893 17.7746L13.4146 11.9999L19.1893 6.22517C19.5799 5.83465 19.5799 5.20148 19.1893 4.81096C18.7988 4.42044 18.1657 4.42044 17.7751 4.81096L12.0004 10.5857L6.22566 4.81096Z" fill="black"/> +</svg> diff --git a/gui/resources/donate.svg b/gui/resources/donate.svg new file mode 100644 index 00000000..35d7c2be --- /dev/null +++ b/gui/resources/donate.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" standalone="no"?> +<svg width="1024px" height="1024px" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon"> + <path d="M880 310H732.4c13.6-21.4 21.6-46.8 21.6-74 0-76.1-61.9-138-138-138-41.4 0-78.7 18.4-104 47.4-25.3-29-62.6-47.4-104-47.4-76.1 0-138 61.9-138 138 0 27.2 7.9 52.6 21.6 74H144c-17.7 0-32 14.3-32 32v200c0 4.4 3.6 8 8 8h40v344c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V550h40c4.4 0 8-3.6 8-8V342c0-17.7-14.3-32-32-32zm-334-74c0-38.6 31.4-70 70-70s70 31.4 70 70-31.4 70-70 70h-70v-70zm-138-70c38.6 0 70 31.4 70 70v70h-70c-38.6 0-70-31.4-70-70s31.4-70 70-70zM180 482V378h298v104H180zm48 68h250v308H228V550zm568 308H546V550h250v308zm48-376H546V378h298v104z"/> +</svg> diff --git a/gui/resources/gear-fill.svg b/gui/resources/gear-fill.svg new file mode 100644 index 00000000..2aa36a1d --- /dev/null +++ b/gui/resources/gear-fill.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-gear-fill" viewBox="0 0 16 16"> + <path d="M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.283-.698-2.686.705-1.987 1.987l.169.311c.446.82.023 1.841-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1a1.464 1.464 0 0 1 .872 2.105l-.17.31c-.698 1.283.705 2.686 1.987 1.987l.311-.169a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.283.698 2.686-.705 1.987-1.987l-.169-.311a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.698-1.283-.705-2.686-1.987-1.987l-.311.169a1.464 1.464 0 0 1-2.105-.872l-.1-.34zM8 10.93a2.929 2.929 0 1 1 0-5.86 2.929 2.929 0 0 1 0 5.858z"/> +</svg> \ No newline at end of file diff --git a/gui/resources/globe.svg b/gui/resources/globe.svg new file mode 100644 index 00000000..150a01eb --- /dev/null +++ b/gui/resources/globe.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-globe2" viewBox="0 0 16 16"> + <path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 1.855-.143.268-.276.56-.395.872.705.157 1.472.257 2.282.287V1.077zM4.249 3.539c.142-.384.304-.744.481-1.078a6.7 6.7 0 0 1 .597-.933A7.01 7.01 0 0 0 3.051 3.05c.362.184.763.349 1.198.49zM3.509 7.5c.036-1.07.188-2.087.436-3.008a9.124 9.124 0 0 1-1.565-.667A6.964 6.964 0 0 0 1.018 7.5h2.49zm1.4-2.741a12.344 12.344 0 0 0-.4 2.741H7.5V5.091c-.91-.03-1.783-.145-2.591-.332zM8.5 5.09V7.5h2.99a12.342 12.342 0 0 0-.399-2.741c-.808.187-1.681.301-2.591.332zM4.51 8.5c.035.987.176 1.914.399 2.741A13.612 13.612 0 0 1 7.5 10.91V8.5H4.51zm3.99 0v2.409c.91.03 1.783.145 2.591.332.223-.827.364-1.754.4-2.741H8.5zm-3.282 3.696c.12.312.252.604.395.872.552 1.035 1.218 1.65 1.887 1.855V11.91c-.81.03-1.577.13-2.282.287zm.11 2.276a6.696 6.696 0 0 1-.598-.933 8.853 8.853 0 0 1-.481-1.079 8.38 8.38 0 0 0-1.198.49 7.01 7.01 0 0 0 2.276 1.522zm-1.383-2.964A13.36 13.36 0 0 1 3.508 8.5h-2.49a6.963 6.963 0 0 0 1.362 3.675c.47-.258.995-.482 1.565-.667zm6.728 2.964a7.009 7.009 0 0 0 2.275-1.521 8.376 8.376 0 0 0-1.197-.49 8.853 8.853 0 0 1-.481 1.078 6.688 6.688 0 0 1-.597.933zM8.5 11.909v3.014c.67-.204 1.335-.82 1.887-1.855.143-.268.276-.56.395-.872A12.63 12.63 0 0 0 8.5 11.91zm3.555-.401c.57.185 1.095.409 1.565.667A6.963 6.963 0 0 0 14.982 8.5h-2.49a13.36 13.36 0 0 1-.437 3.008zM14.982 7.5a6.963 6.963 0 0 0-1.362-3.675c-.47.258-.995.482-1.565.667.248.92.4 1.938.437 3.008h2.49zM11.27 2.461c.177.334.339.694.482 1.078a8.368 8.368 0 0 0 1.196-.49 7.01 7.01 0 0 0-2.275-1.52c.218.283.418.597.597.932zm-.488 1.343a7.765 7.765 0 0 0-.395-.872C9.835 1.897 9.17 1.282 8.5 1.077V4.09c.81-.03 1.577-.13 2.282-.287z"/> +</svg> \ No newline at end of file diff --git a/gui/resources/help.svg b/gui/resources/help.svg new file mode 100644 index 00000000..06569c87 --- /dev/null +++ b/gui/resources/help.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" standalone="no"?> +<svg width="1024px" height="1024px" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon"> + <path d="M824.2 699.9a301.55 301.55 0 0 0-86.4-60.4C783.1 602.8 812 546.8 812 484c0-110.8-92.4-201.7-203.2-200-109.1 1.7-197 90.6-197 200 0 62.8 29 118.8 74.2 155.5a300.95 300.95 0 0 0-86.4 60.4C345 754.6 314 826.8 312 903.8a8 8 0 0 0 8 8.2h56c4.3 0 7.9-3.4 8-7.7 1.9-58 25.4-112.3 66.7-153.5A226.62 226.62 0 0 1 612 684c60.9 0 118.2 23.7 161.3 66.8C814.5 792 838 846.3 840 904.3c.1 4.3 3.7 7.7 8 7.7h56a8 8 0 0 0 8-8.2c-2-77-33-149.2-87.8-203.9zM612 612c-34.2 0-66.4-13.3-90.5-37.5a126.86 126.86 0 0 1-37.5-91.8c.3-32.8 13.4-64.5 36.3-88 24-24.6 56.1-38.3 90.4-38.7 33.9-.3 66.8 12.9 91 36.6 24.8 24.3 38.4 56.8 38.4 91.4 0 34.2-13.3 66.3-37.5 90.5A127.3 127.3 0 0 1 612 612zM361.5 510.4c-.9-8.7-1.4-17.5-1.4-26.4 0-15.9 1.5-31.4 4.3-46.5.7-3.6-1.2-7.3-4.5-8.8-13.6-6.1-26.1-14.5-36.9-25.1a127.54 127.54 0 0 1-38.7-95.4c.9-32.1 13.8-62.6 36.3-85.6 24.7-25.3 57.9-39.1 93.2-38.7 31.9.3 62.7 12.6 86 34.4 7.9 7.4 14.7 15.6 20.4 24.4 2 3.1 5.9 4.4 9.3 3.2 17.6-6.1 36.2-10.4 55.3-12.4 5.6-.6 8.8-6.6 6.3-11.6-32.5-64.3-98.9-108.7-175.7-109.9-110.9-1.7-203.3 89.2-203.3 199.9 0 62.8 28.9 118.8 74.2 155.5-31.8 14.7-61.1 35-86.5 60.4-54.8 54.7-85.8 126.9-87.8 204a8 8 0 0 0 8 8.2h56.1c4.3 0 7.9-3.4 8-7.7 1.9-58 25.4-112.3 66.7-153.5 29.4-29.4 65.4-49.8 104.7-59.7 3.9-1 6.5-4.7 6-8.7z"/> +</svg> diff --git a/gui/resources/icon-noshield.svg b/gui/resources/icon-noshield.svg new file mode 100644 index 00000000..815a0d61 --- /dev/null +++ b/gui/resources/icon-noshield.svg @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="128" + height="128" + viewBox="0 0 33.866666 33.866668" + version="1.1" + id="svg896" + inkscape:version="1.0.2 (e86c870879, 2021-01-15)" + sodipodi:docname="icon-noshield.svg"> + <defs + id="defs890" /> + <sodipodi:namedview + id="base" + pagecolor="#d7d7d7" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:zoom="3.3834377" + inkscape:cx="-34.426658" + inkscape:cy="43.45762" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + units="px" + inkscape:window-width="1920" + inkscape:window-height="1032" + inkscape:window-x="0" + inkscape:window-y="25" + inkscape:window-maximized="1" + inkscape:document-rotation="0"> + <inkscape:grid + type="xygrid" + id="grid1471" + empspacing="4" /> + </sodipodi:namedview> + <metadata + id="metadata893"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-263.13332)"> + <path + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583" + d="m 17.51831,273.60678 c 0,0 -0.315707,-0.61165 -0.336761,-0.69601 -0.02106,-0.0844 -0.189431,-0.94909 -0.189431,-0.94909 l 0.210485,-0.37963 0.463046,-0.696 0.673531,-0.52727 0.168377,-0.0633 1.620684,-0.61164 0.147331,-0.14764 -0.168385,-0.25308 -0.231523,-0.12655 -0.424879,-0.10907 -1.064407,-0.10907 -0.825967,0.007 -0.568293,0.12654 -0.505146,-0.18981 -0.63143,-0.0844 -0.9261,-0.0211 -0.463054,-0.0211 -0.778761,0.29527 -1.178677,1.37091 -0.147339,0.52727 -0.08418,0.464 -0.399908,0.86473 -0.252577,0.82254 -0.126285,0.88582 v 0.18982 l -0.610384,0.92799 -0.336761,0.69601 v 0.99126 l 0.10523,2.04581 0.189431,0.73821 0.378861,0.6749 0.4841,0.44292 0.210477,0.8647 0.799815,1.77155 0.947154,1.13886 0.06311,0.0633 0.336761,1.70835 -1.157623,2.10911 -0.363408,0.28169 -0.272426,0.22054 -0.467179,-0.0129 -0.260603,0.13452 -0.316122,0.0134 -0.190994,0.19047 -0.408963,-0.0616 -0.404409,-0.0196 -0.3119827,0.24606 -0.04492,0.36556 0.2073657,-0.23472 0.348864,-0.10158 0.03654,0.33552 0.551268,-0.18726 0.316122,-0.0134 0.557721,0.0667 c 0,0 0.483518,-0.0316 0.567216,-0.0407 0.0837,-0.009 0.597276,0.0411 0.597276,0.0411 l 0.376644,-0.041 0.199723,0.0844 0.267456,-0.0716 0.290265,0.13818 0.418488,-0.0455 0.05401,-0.28169 -0.01596,-0.14678 0.28571,0.0962 0.232049,0.18692 0.150642,0.21701 -0.0088,-0.27495 -0.182953,-0.31946 c 0,0 -0.125159,-0.17737 -0.208857,-0.16824 -0.0837,0.009 -0.408971,-0.0616 -0.408971,-0.0616 l -0.223321,0.088 -0.243857,-0.10085 -0.239677,0.13226 -0.220665,-0.0822 -0.106491,-0.20049 -0.153322,-0.0471 0.164763,-0.42962 0.378861,-0.52859 0.505146,-0.84364 0.442,-0.5273 0.168385,-0.21088 c 0,0 0.210477,-0.31633 0.210477,-0.40071 0,-0.0844 0.04212,-0.97016 0.04212,-0.97016 l -0.273623,-0.56947 -0.126285,-0.46402 2.441546,0.59059 h 0.147331 l 2.083731,1.49744 0.294669,0.37959 0.10523,1.49729 -0.04212,0.33746 -0.147338,0.27419 -0.105358,0.16875 -0.09101,0.23675 -0.06215,0.1583 -0.386712,0.11988 -0.393086,-0.0709 -0.238209,-0.0294 -0.437428,0.0633 -0.184118,0.19713 -0.07084,0.24475 0.05712,0.24744 0.09172,-0.24769 0.124641,-0.16724 0.121984,-0.0388 0.0094,0.21174 0.163957,0.10406 0.338995,-0.15563 0.166646,-0.0242 0.05409,0.22658 0.508999,-0.01 0.345035,-0.11394 0.282886,0.0443 0.410893,0.047 0.142823,-0.0417 0.112881,-0.10156 0.182442,0.37841 0.0024,-0.42654 -0.176722,-0.48581 -0.256358,-0.15463 0.04324,-0.12712 -0.189423,-0.35849 0.02106,-1.37079 1.052392,1.2444 1.389154,1.09674 c 0,0 0.947146,0.33749 1.03133,0.33749 0.08419,0 0.736677,-0.0844 0.736677,-0.0844 l 0.420954,-0.69598 -0.315715,-0.94908 0.126284,-0.31642 -0.673531,-0.88574 -1.426794,-1.45279 -0.341213,-1.14141 0.02106,-0.78037 -0.315707,-0.82257 -0.357816,-0.65376 0.210477,-0.65377 -0.168377,-0.94904 -0.717785,-1.61568 0.265151,-0.0448 -0.444984,-0.77034 0.289101,-0.0918 -0.508218,-0.82847 0.213764,-0.11524 -0.380944,-0.62543 0.124202,-0.0696 -0.460971,-0.37337 0.168384,-0.0875 -1.199723,-0.84051 z" + id="path5892" + inkscape:connector-curvature="0" + sodipodi:nodetypes="csccccccccccccccccccccccccccccccccccccccccccccccccccccccscccccccccccccsccccccccccccscccccccccccccccccccccccccccccccccccccccccccscccccccccccccccccccccccc" /> + </g> +</svg> diff --git a/gui/resources/location.svg b/gui/resources/location.svg new file mode 100644 index 00000000..f738eb65 --- /dev/null +++ b/gui/resources/location.svg @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + width="31.603px" height="31.603px" viewBox="0 0 31.603 31.603" style="enable-background:new 0 0 31.603 31.603;" + xml:space="preserve"> +<g> + <g> + <path d="M7.703,15.973c0,0,5.651-5.625,5.651-10.321C13.354,2.53,10.824,0,7.703,0S2.052,2.53,2.052,5.652 + C2.052,10.614,7.703,15.973,7.703,15.973z M4.758,5.652c0-1.628,1.319-2.946,2.945-2.946s2.945,1.318,2.945,2.946 + c0,1.626-1.319,2.944-2.945,2.944S4.758,7.278,4.758,5.652z"/> + <path d="M28.59,7.643l-0.459,0.146l-2.455,0.219l-0.692,1.106l-0.501-0.16l-1.953-1.76l-0.285-0.915l-0.377-0.977L20.639,4.2 + l-1.446-0.283L19.159,4.58l1.418,1.384l0.694,0.817l-0.782,0.408l-0.636-0.188l-0.951-0.396l0.033-0.769l-1.25-0.514L17.27,7.126 + l-1.258,0.286l0.125,1.007l1.638,0.316l0.284-1.609l1.353,0.201l0.629,0.368h1.011l0.69,1.384l1.833,1.859l-0.134,0.723 + l-1.478-0.189l-2.553,1.289l-1.838,2.205l-0.239,0.976h-0.661l-1.229-0.566l-1.194,0.566l0.297,1.261l0.52-0.602l0.913-0.027 + l-0.064,1.132l0.757,0.22l0.756,0.85l1.234-0.347l1.41,0.222l1.636,0.441l0.819,0.095l1.384,1.573l2.675,1.574l-1.729,3.306 + l-1.826,0.849l-0.693,1.889l-2.643,1.765l-0.282,1.019c6.753-1.627,11.779-7.693,11.779-14.95 + C31.194,13.038,30.234,10.09,28.59,7.643z"/> + <path d="M17.573,24.253l-1.12-2.078l1.028-2.146l-1.028-0.311l-1.156-1.159l-2.56-0.573l-0.85-1.779v1.057h-0.375l-1.625-2.203 + c-0.793,0.949-1.395,1.555-1.47,1.629L7.72,17.384l-0.713-0.677c-0.183-0.176-3.458-3.315-5.077-7.13 + c-0.966,2.009-1.52,4.252-1.52,6.63c0,8.502,6.891,15.396,15.393,15.396c0.654,0,1.296-0.057,1.931-0.135l-0.161-1.864 + c0,0,0.707-2.77,0.707-2.863C18.28,26.646,17.573,24.253,17.573,24.253z"/> + <path d="M14.586,3.768l1.133,0.187l2.75-0.258l0.756-0.834l1.068-0.714l1.512,0.228l0.551-0.083 + c-1.991-0.937-4.207-1.479-6.553-1.479c-1.096,0-2.16,0.128-3.191,0.345c0.801,0.875,1.377,1.958,1.622,3.163L14.586,3.768z + M16.453,2.343l1.573-0.865l1.009,0.582l-1.462,1.113l-1.394,0.141L15.55,2.907L16.453,2.343z"/> + </g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +</svg> diff --git a/gui/resources/power.svg b/gui/resources/power.svg new file mode 100644 index 00000000..158bc3c9 --- /dev/null +++ b/gui/resources/power.svg @@ -0,0 +1,10 @@ +<?xml version='1.0' encoding='utf-8'?> +<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'> +<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" xmlns:xlink="http://www.w3.org/1999/xlink" enable-background="new 0 0 512 512"> + <g> + <g> + <path d="m256,501c-120.6,0-218.7-98.1-218.7-218.7 0-91.6 57.9-174.1 144.2-205.4 10.6-3.9 22.3,1.6 26.2,12.2 3.8,10.6-1.6,22.3-12.2,26.2-70.1,25.5-117.3,92.6-117.3,167 0,98.1 79.8,177.8 177.8,177.8 98.1,0 177.8-79.8 177.8-177.8 0-74.4-47.1-141.6-117.3-167-10.6-3.8-16.1-15.6-12.2-26.2 3.8-10.6 15.6-16.1 26.2-12.2 86.2,31.3 144.2,113.8 144.2,205.4 0,120.6-98.1,218.7-218.7,218.7z"/> + <path d="m256,308.8c-11.3,0-20.4-9.1-20.4-20.4v-257c0-11.3 9.1-20.4 20.4-20.4 11.3,0 20.4,9.1 20.4,20.4v256.9c0,11.3-9.1,20.5-20.4,20.5z"/> + </g> + </g> +</svg> diff --git a/gui/resources/quit.svg b/gui/resources/quit.svg new file mode 100644 index 00000000..2fbd5201 --- /dev/null +++ b/gui/resources/quit.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" standalone="no"?> +<svg width="1024px" height="1024px" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon"> + <path d="M705.6 124.9a8 8 0 0 0-11.6 7.2v64.2c0 5.5 2.9 10.6 7.5 13.6a352.2 352.2 0 0 1 62.2 49.8c32.7 32.8 58.4 70.9 76.3 113.3a355 355 0 0 1 27.9 138.7c0 48.1-9.4 94.8-27.9 138.7a355.92 355.92 0 0 1-76.3 113.3 353.06 353.06 0 0 1-113.2 76.4c-43.8 18.6-90.5 28-138.5 28s-94.7-9.4-138.5-28a353.06 353.06 0 0 1-113.2-76.4A355.92 355.92 0 0 1 184 650.4a355 355 0 0 1-27.9-138.7c0-48.1 9.4-94.8 27.9-138.7 17.9-42.4 43.6-80.5 76.3-113.3 19-19 39.8-35.6 62.2-49.8 4.7-2.9 7.5-8.1 7.5-13.6V132c0-6-6.3-9.8-11.6-7.2C178.5 195.2 82 339.3 80 506.3 77.2 745.1 272.5 943.5 511.2 944c239 .5 432.8-193.3 432.8-432.4 0-169.2-97-315.7-238.4-386.7zM480 560h64c4.4 0 8-3.6 8-8V88c0-4.4-3.6-8-8-8h-64c-4.4 0-8 3.6-8 8v464c0 4.4 3.6 8 8 8z"/> +</svg> diff --git a/gui/resources/reception-0.svg b/gui/resources/reception-0.svg new file mode 100644 index 00000000..885bf3bb --- /dev/null +++ b/gui/resources/reception-0.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-reception-0" viewBox="0 0 16 16"> + <path d="M0 13.5a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5zm4 0a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5zm4 0a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5zm4 0a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"/> +</svg> \ No newline at end of file diff --git a/gui/resources/reception-2.svg b/gui/resources/reception-2.svg new file mode 100644 index 00000000..7dca57ac --- /dev/null +++ b/gui/resources/reception-2.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-reception-2" viewBox="0 0 16 16"> + <path d="M0 11.5a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-2zm4-3a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-5zm4 5a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5zm4 0a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"/> +</svg> \ No newline at end of file diff --git a/gui/resources/reception-4.svg b/gui/resources/reception-4.svg new file mode 100644 index 00000000..611bdf1b --- /dev/null +++ b/gui/resources/reception-4.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-reception-4" viewBox="0 0 16 16"> + <path d="M0 11.5a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-2zm4-3a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-5zm4-3a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-8zm4-3a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v11a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-11z"/> +</svg> \ No newline at end of file diff --git a/gui/resources/riseup-icon.svg b/gui/resources/riseup-icon.svg new file mode 100644 index 00000000..a19c6c61 --- /dev/null +++ b/gui/resources/riseup-icon.svg @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="128" + height="128" + viewBox="0 0 33.866666 33.866668" + version="1.1" + id="svg896" + inkscape:version="0.92.2 (5c3e80d, 2017-08-06)" + sodipodi:docname="riseupvpn-launcher.svg"> + <defs + id="defs890" /> + <sodipodi:namedview + id="base" + pagecolor="#d7d7d7" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:zoom="5.12" + inkscape:cx="26.899914" + inkscape:cy="56.22909" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + units="px" + inkscape:window-width="1869" + inkscape:window-height="1025" + inkscape:window-x="51" + inkscape:window-y="27" + inkscape:window-maximized="1"> + <inkscape:grid + type="xygrid" + id="grid1471" + empspacing="4" /> + </sodipodi:namedview> + <metadata + id="metadata893"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-263.13332)"> + <path + style="fill:#006cb2;fill-opacity:1;stroke-width:0.26458335" + d="M 15.617988,295.66418 C 9.9401302,292.50672 5.6959906,287.52131 4.7342129,282.87951 4.4622971,281.56718 4.4516145,281.24899 4.4519256,274.47112 l 2.394e-4,-6.47461 0.5616386,-0.36177 c 2.3734615,-1.52883 4.8841786,-2.55103 7.4419094,-3.06699 5.221864,-1.05337 10.639669,0.003 15.485448,3.16684 l 0.398232,0.25998 v 6.50684 c 0,6.8044 -0.01093,7.13134 -0.280843,8.43104 -0.956329,4.6043 -4.632206,9.09553 -10.057782,12.28874 -1.576255,0.9277 -1.527525,0.91863 -2.382844,0.44299 z" + id="path5137" + inkscape:connector-curvature="0" + sodipodi:nodetypes="csccssscssscc" /> + <path + inkscape:connector-curvature="0" + style="fill:#007cc3;fill-opacity:1;stroke-width:0.26458335" + d="m 16.396917,264.17336 c -1.317958,-4.7e-4 -2.635612,0.13103 -3.941076,0.39437 -2.5577318,0.51596 -5.068528,1.53812 -7.4419895,3.06696 l -0.5615828,0.36177 -4.707e-4,6.47466 c -2.394e-4,6.77787 0.010371,7.096 0.2822554,8.40832 0.9617776,4.64181 5.2059168,9.62724 10.8837756,12.7847 h 1.19e-4 c 0.368953,0.20517 0.569745,0.32326 0.805249,0.31706 v -31.80747 c -0.0088,-2e-5 -0.01755,-4.8e-4 -0.02641,-4.8e-4 z" + id="path887" /> + <path + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458338" + d="m 16.989143,272.54844 c 0,0 -0.315707,-0.61165 -0.336761,-0.69601 -0.02106,-0.0844 -0.189431,-0.94909 -0.189431,-0.94909 l 0.210485,-0.37963 0.463046,-0.696 0.673531,-0.52727 0.168377,-0.0633 1.620684,-0.61164 0.147331,-0.14764 -0.168385,-0.25308 -0.231523,-0.12655 -0.424879,-0.10907 -1.064407,-0.10907 -0.825967,0.007 -0.568293,0.12654 -0.505146,-0.18981 -0.63143,-0.0844 -0.9261,-0.0211 -0.463054,-0.0211 -0.778761,0.29527 -1.178677,1.37091 -0.147339,0.52727 -0.08418,0.464 -0.399908,0.86473 -0.252577,0.82254 -0.126285,0.88582 v 0.18982 l -0.610384,0.92799 -0.336761,0.69601 v 0.99126 l 0.10523,2.04581 0.189431,0.73821 0.378861,0.6749 0.4841,0.44292 0.210477,0.8647 0.799815,1.77155 0.947154,1.13886 0.06311,0.0633 0.336761,1.70835 -1.157623,2.10911 -0.363408,0.28169 -0.272426,0.22054 -0.467179,-0.0129 -0.260603,0.13452 -0.316122,0.0134 -0.190994,0.19047 -0.408963,-0.0616 -0.4044091,-0.0196 -0.311982,0.24606 -0.044916,0.36556 0.207365,-0.23472 0.3488649,-0.10158 0.03654,0.33552 0.5512672,-0.18726 0.316122,-0.0134 0.557721,0.0667 c 0,0 0.483518,-0.0316 0.567216,-0.0407 0.0837,-0.009 0.597276,0.0411 0.597276,0.0411 l 0.376644,-0.041 0.199723,0.0844 0.267456,-0.0716 0.290265,0.13818 0.418488,-0.0455 0.05401,-0.28169 -0.01596,-0.14678 0.28571,0.0962 0.232049,0.18692 0.150642,0.21701 -0.0088,-0.27495 -0.182953,-0.31946 c 0,0 -0.125159,-0.17737 -0.208857,-0.16824 -0.0837,0.009 -0.408971,-0.0616 -0.408971,-0.0616 l -0.223321,0.088 -0.243857,-0.10085 -0.239677,0.13226 -0.220665,-0.0822 -0.106491,-0.20049 -0.153322,-0.0471 0.164763,-0.42962 0.378861,-0.52859 0.505146,-0.84364 0.442,-0.5273 0.168385,-0.21088 c 0,0 0.210477,-0.31633 0.210477,-0.40071 0,-0.0844 0.04212,-0.97016 0.04212,-0.97016 l -0.273623,-0.56947 -0.126285,-0.46402 2.441546,0.59059 h 0.147331 l 2.083731,1.49744 0.294669,0.37959 0.10523,1.49729 -0.04212,0.33746 -0.147338,0.27419 -0.105358,0.16875 -0.09101,0.23675 -0.06215,0.1583 -0.386712,0.11988 -0.393086,-0.0709 -0.238209,-0.0294 -0.437428,0.0633 -0.184118,0.19713 -0.07084,0.24475 0.05712,0.24744 0.09172,-0.24769 0.124641,-0.16724 0.121984,-0.0388 0.0094,0.21174 0.163957,0.10406 0.338995,-0.15563 0.166646,-0.0242 0.05409,0.22658 0.508999,-0.01 0.345035,-0.11394 0.282886,0.0443 0.410893,0.047 0.142823,-0.0417 0.112881,-0.10156 0.182442,0.37841 0.0024,-0.42654 -0.176722,-0.48581 -0.256358,-0.15463 0.04324,-0.12712 -0.189423,-0.35849 0.02106,-1.37079 1.052392,1.2444 1.389154,1.09674 c 0,0 0.947146,0.33749 1.03133,0.33749 0.08419,0 0.736677,-0.0844 0.736677,-0.0844 l 0.420954,-0.69598 -0.315715,-0.94908 0.126284,-0.31642 -0.673531,-0.88574 -1.426794,-1.45279 -0.341213,-1.14141 0.02106,-0.78037 -0.315707,-0.82257 -0.357816,-0.65376 0.210477,-0.65377 -0.168377,-0.94904 -0.717785,-1.61568 0.265151,-0.0448 -0.444984,-0.77034 0.289101,-0.0918 -0.508218,-0.82847 0.213764,-0.11524 -0.380944,-0.62543 0.124202,-0.0696 -0.460971,-0.37337 0.168384,-0.0875 -1.199723,-0.84051 z" + id="path5892" + inkscape:connector-curvature="0" + sodipodi:nodetypes="csccccccccccccccccccccccccccccccccccccccccccccccccccccccscccccccccccccsccccccccccccscccccccccccccccccccccccccccccccccccccccccccscccccccccccccccccccccccc" /> + </g> +</svg> diff --git a/gui/resources/riseup-logo.png b/gui/resources/riseup-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e68cfe2cdc341fdb24013b7a9d3e3a17c105bc5f GIT binary patch literal 4943 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 R_wQd^7ACgFjfOr+{{#0Q)r<fD literal 0 HcmV?d00001 diff --git a/gui/resources/settings.svg b/gui/resources/settings.svg new file mode 100644 index 00000000..0469ed45 --- /dev/null +++ b/gui/resources/settings.svg @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 478.703 478.703" style="enable-background:new 0 0 478.703 478.703;" xml:space="preserve"> +<g> + <g> + <path d="M454.2,189.101l-33.6-5.7c-3.5-11.3-8-22.2-13.5-32.6l19.8-27.7c8.4-11.8,7.1-27.9-3.2-38.1l-29.8-29.8 + c-5.6-5.6-13-8.7-20.9-8.7c-6.2,0-12.1,1.9-17.1,5.5l-27.8,19.8c-10.8-5.7-22.1-10.4-33.8-13.9l-5.6-33.2 + c-2.4-14.3-14.7-24.7-29.2-24.7h-42.1c-14.5,0-26.8,10.4-29.2,24.7l-5.8,34c-11.2,3.5-22.1,8.1-32.5,13.7l-27.5-19.8 + c-5-3.6-11-5.5-17.2-5.5c-7.9,0-15.4,3.1-20.9,8.7l-29.9,29.8c-10.2,10.2-11.6,26.3-3.2,38.1l20,28.1 + c-5.5,10.5-9.9,21.4-13.3,32.7l-33.2,5.6c-14.3,2.4-24.7,14.7-24.7,29.2v42.1c0,14.5,10.4,26.8,24.7,29.2l34,5.8 + c3.5,11.2,8.1,22.1,13.7,32.5l-19.7,27.4c-8.4,11.8-7.1,27.9,3.2,38.1l29.8,29.8c5.6,5.6,13,8.7,20.9,8.7c6.2,0,12.1-1.9,17.1-5.5 + l28.1-20c10.1,5.3,20.7,9.6,31.6,13l5.6,33.6c2.4,14.3,14.7,24.7,29.2,24.7h42.2c14.5,0,26.8-10.4,29.2-24.7l5.7-33.6 + c11.3-3.5,22.2-8,32.6-13.5l27.7,19.8c5,3.6,11,5.5,17.2,5.5l0,0c7.9,0,15.3-3.1,20.9-8.7l29.8-29.8c10.2-10.2,11.6-26.3,3.2-38.1 + l-19.8-27.8c5.5-10.5,10.1-21.4,13.5-32.6l33.6-5.6c14.3-2.4,24.7-14.7,24.7-29.2v-42.1 + C478.9,203.801,468.5,191.501,454.2,189.101z M451.9,260.401c0,1.3-0.9,2.4-2.2,2.6l-42,7c-5.3,0.9-9.5,4.8-10.8,9.9 + c-3.8,14.7-9.6,28.8-17.4,41.9c-2.7,4.6-2.5,10.3,0.6,14.7l24.7,34.8c0.7,1,0.6,2.5-0.3,3.4l-29.8,29.8c-0.7,0.7-1.4,0.8-1.9,0.8 + c-0.6,0-1.1-0.2-1.5-0.5l-34.7-24.7c-4.3-3.1-10.1-3.3-14.7-0.6c-13.1,7.8-27.2,13.6-41.9,17.4c-5.2,1.3-9.1,5.6-9.9,10.8l-7.1,42 + c-0.2,1.3-1.3,2.2-2.6,2.2h-42.1c-1.3,0-2.4-0.9-2.6-2.2l-7-42c-0.9-5.3-4.8-9.5-9.9-10.8c-14.3-3.7-28.1-9.4-41-16.8 + c-2.1-1.2-4.5-1.8-6.8-1.8c-2.7,0-5.5,0.8-7.8,2.5l-35,24.9c-0.5,0.3-1,0.5-1.5,0.5c-0.4,0-1.2-0.1-1.9-0.8l-29.8-29.8 + c-0.9-0.9-1-2.3-0.3-3.4l24.6-34.5c3.1-4.4,3.3-10.2,0.6-14.8c-7.8-13-13.8-27.1-17.6-41.8c-1.4-5.1-5.6-9-10.8-9.9l-42.3-7.2 + c-1.3-0.2-2.2-1.3-2.2-2.6v-42.1c0-1.3,0.9-2.4,2.2-2.6l41.7-7c5.3-0.9,9.6-4.8,10.9-10c3.7-14.7,9.4-28.9,17.1-42 + c2.7-4.6,2.4-10.3-0.7-14.6l-24.9-35c-0.7-1-0.6-2.5,0.3-3.4l29.8-29.8c0.7-0.7,1.4-0.8,1.9-0.8c0.6,0,1.1,0.2,1.5,0.5l34.5,24.6 + c4.4,3.1,10.2,3.3,14.8,0.6c13-7.8,27.1-13.8,41.8-17.6c5.1-1.4,9-5.6,9.9-10.8l7.2-42.3c0.2-1.3,1.3-2.2,2.6-2.2h42.1 + c1.3,0,2.4,0.9,2.6,2.2l7,41.7c0.9,5.3,4.8,9.6,10,10.9c15.1,3.8,29.5,9.7,42.9,17.6c4.6,2.7,10.3,2.5,14.7-0.6l34.5-24.8 + c0.5-0.3,1-0.5,1.5-0.5c0.4,0,1.2,0.1,1.9,0.8l29.8,29.8c0.9,0.9,1,2.3,0.3,3.4l-24.7,34.7c-3.1,4.3-3.3,10.1-0.6,14.7 + c7.8,13.1,13.6,27.2,17.4,41.9c1.3,5.2,5.6,9.1,10.8,9.9l42,7.1c1.3,0.2,2.2,1.3,2.2,2.6v42.1H451.9z"/> + <path d="M239.4,136.001c-57,0-103.3,46.3-103.3,103.3s46.3,103.3,103.3,103.3s103.3-46.3,103.3-103.3S296.4,136.001,239.4,136.001 + z M239.4,315.601c-42.1,0-76.3-34.2-76.3-76.3s34.2-76.3,76.3-76.3s76.3,34.2,76.3,76.3S281.5,315.601,239.4,315.601z"/> + </g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +</svg> diff --git a/gui/resources/speed-green.svg b/gui/resources/speed-green.svg new file mode 100644 index 00000000..a25de124 --- /dev/null +++ b/gui/resources/speed-green.svg @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 512.001 512.001" style="enable-background:new 0 0 512.001 512.001;" xml:space="preserve"> +<polyline style="fill:#CFF09E;" points="233.225,420.726 270.89,383.061 288.971,401.143 310.88,303.847 213.584,325.756 + 231.665,343.837 174.547,400.955 "/> +<g> + <path style="fill:#507C5C;" d="M233.226,435.168c-3.697,0-7.391-1.41-10.212-4.23c-5.64-5.64-5.64-14.784,0-20.424l37.663-37.665 + c5.489-5.488,14.293-5.635,19.962-0.443l11.135-49.454l-49.452,11.135c2.431,2.656,3.787,6.132,3.787,9.748 + c0,3.83-1.522,7.504-4.23,10.212l-57.119,57.118c-5.641,5.64-14.783,5.641-20.425,0c-5.64-5.64-5.64-14.784,0-20.424l46.906-46.906 + l-7.869-7.869c-3.722-3.722-5.124-9.175-3.66-14.231c1.466-5.056,5.564-8.915,10.7-10.072l97.296-21.909 + c4.824-1.086,9.881,0.375,13.385,3.878c3.502,3.502,4.965,8.554,3.878,13.385l-21.908,97.296 + c-1.157,5.136-5.016,9.234-10.072,10.699c-5.058,1.464-10.508,0.062-14.231-3.66l-7.869-7.869l-27.451,27.453 + C240.618,433.758,236.922,435.168,233.226,435.168z"/> + <path style="fill:#507C5C;" d="M256,512.001c-141.159,0-256-114.841-256-256s114.841-256,256-256 + c53.115,0,104.062,16.122,147.333,46.62c6.519,4.595,8.079,13.606,3.483,20.125c-4.595,6.519-13.607,8.08-20.125,3.485 + C348.318,43.181,303.126,28.885,256,28.885c-125.232,0-227.116,101.884-227.116,227.116S130.768,483.117,256,483.117 + s227.116-101.884,227.116-227.116c0-34.43-7.503-67.493-22.3-98.275c-3.456-7.189-0.43-15.817,6.759-19.273 + c7.191-3.453,15.817-0.429,19.274,6.759c16.691,34.719,25.152,71.993,25.152,110.789C512,397.16,397.159,512.001,256,512.001z"/> + <path style="fill:#507C5C;" d="M230.725,434.831c-0.728,0-1.464-0.055-2.205-0.169c-42.217-6.469-80.975-27.931-109.135-60.43 + c-28.458-32.843-44.132-74.831-44.132-118.232c0-99.664,81.083-180.747,180.747-180.747s180.747,81.083,180.747,180.747 + c0,7.976-6.467,14.442-14.442,14.442c-7.975,0-14.442-6.466-14.442-14.442c0-83.737-68.126-151.863-151.863-151.863 + s-151.863,68.126-151.863,151.863c0,74.329,55.353,138.863,128.757,150.11c7.884,1.209,13.295,8.579,12.088,16.462 + C243.889,429.718,237.735,434.831,230.725,434.831z"/> +</g> +<path style="fill:#CFF09E;" d="M256,164.947c50.208,0,91.054,40.846,91.054,91.054h75.253c0-91.701-74.604-166.305-166.305-166.305 + S89.695,164.3,89.695,256.001h75.253C164.946,205.793,205.792,164.947,256,164.947z"/> +<g> + <path style="fill:#507C5C;" d="M422.334,270.443c-0.007,0-0.017,0-0.029,0h-75.251c-7.975,0-14.442-6.466-14.442-14.442 + c0-42.243-34.368-76.612-76.612-76.612s-76.612,34.368-76.612,76.612c0,7.976-6.467,14.442-14.442,14.442H89.695 + c-7.975,0-14.442-6.466-14.442-14.442c0-99.664,81.083-180.747,180.747-180.747c99.342,0,180.223,80.566,180.744,179.788 + c0.022,0.318,0.03,0.637,0.03,0.96C436.776,263.977,430.31,270.443,422.334,270.443z M360.511,241.559h46.671 + c-7.298-76.989-72.315-137.421-151.183-137.421S112.113,164.57,104.816,241.559h46.671c7.065-51.36,51.24-91.054,104.511-91.054 + S353.447,190.199,360.511,241.559z"/> + <path style="fill:#507C5C;" d="M216.293,187.292c-3.238,0-6.496-1.083-9.188-3.309l-59.817-49.406 + c-6.149-5.079-7.017-14.182-1.938-20.331c5.079-6.149,14.181-7.019,20.331-1.938l59.817,49.406 + c6.149,5.079,7.017,14.182,1.938,20.331C224.58,185.502,220.453,187.292,216.293,187.292z"/> + <path style="fill:#507C5C;" d="M295.707,187.292c-4.161,0-8.287-1.788-11.143-5.245c-5.081-6.149-4.211-15.252,1.938-20.331 + l59.817-49.406c6.151-5.081,15.252-4.211,20.331,1.938c5.081,6.149,4.211,15.252-1.938,20.331l-59.817,49.406 + C302.203,186.207,298.946,187.292,295.707,187.292z"/> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +</svg> diff --git a/gui/resources/speed-red.svg b/gui/resources/speed-red.svg new file mode 100644 index 00000000..8ceb8580 --- /dev/null +++ b/gui/resources/speed-red.svg @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 512.001 512.001" style="enable-background:new 0 0 512.001 512.001;" xml:space="preserve"> +<polyline style="fill:#F4B2B0;" points="233.225,420.726 270.89,383.061 288.971,401.143 310.88,303.847 213.584,325.756 + 231.665,343.837 174.547,400.955 "/> +<g> + <path style="fill:#B3404A;" d="M233.226,435.168c-3.697,0-7.391-1.41-10.212-4.23c-5.64-5.64-5.64-14.784,0-20.424l37.663-37.665 + c5.489-5.488,14.293-5.635,19.962-0.443l11.135-49.454l-49.452,11.135c2.431,2.656,3.787,6.132,3.787,9.748 + c0,3.83-1.522,7.504-4.23,10.212l-57.119,57.118c-5.641,5.64-14.783,5.641-20.425,0c-5.64-5.64-5.64-14.784,0-20.424l46.906-46.906 + l-7.869-7.869c-3.722-3.722-5.124-9.175-3.66-14.231c1.466-5.056,5.564-8.915,10.7-10.072l97.296-21.909 + c4.824-1.086,9.881,0.375,13.385,3.878c3.502,3.502,4.965,8.554,3.878,13.385l-21.908,97.296 + c-1.157,5.136-5.016,9.234-10.072,10.699c-5.058,1.464-10.508,0.062-14.231-3.66l-7.869-7.869l-27.451,27.453 + C240.618,433.758,236.922,435.168,233.226,435.168z"/> + <path style="fill:#B3404A;" d="M256,512.001c-141.159,0-256-114.841-256-256s114.841-256,256-256 + c53.115,0,104.062,16.122,147.333,46.62c6.519,4.595,8.079,13.606,3.483,20.125c-4.595,6.519-13.607,8.08-20.125,3.485 + C348.318,43.181,303.126,28.885,256,28.885c-125.232,0-227.116,101.884-227.116,227.116S130.768,483.117,256,483.117 + s227.116-101.884,227.116-227.116c0-34.43-7.503-67.493-22.3-98.275c-3.456-7.189-0.43-15.817,6.759-19.273 + c7.191-3.453,15.817-0.429,19.274,6.759c16.691,34.719,25.152,71.993,25.152,110.789C512,397.16,397.159,512.001,256,512.001z"/> + <path style="fill:#B3404A;" d="M230.725,434.831c-0.728,0-1.464-0.055-2.205-0.169c-42.217-6.469-80.975-27.931-109.135-60.43 + c-28.458-32.843-44.132-74.831-44.132-118.232c0-99.664,81.083-180.747,180.747-180.747s180.747,81.083,180.747,180.747 + c0,7.976-6.467,14.442-14.442,14.442c-7.975,0-14.442-6.466-14.442-14.442c0-83.737-68.126-151.863-151.863-151.863 + s-151.863,68.126-151.863,151.863c0,74.329,55.353,138.863,128.757,150.11c7.884,1.209,13.295,8.579,12.088,16.462 + C243.889,429.718,237.735,434.831,230.725,434.831z"/> +</g> +<path style="fill:#F4B2B0;" d="M256,164.947c50.208,0,91.054,40.846,91.054,91.054h75.253c0-91.701-74.604-166.305-166.305-166.305 + S89.695,164.3,89.695,256.001h75.253C164.946,205.793,205.792,164.947,256,164.947z"/> +<g> + <path style="fill:#B3404A;" d="M422.334,270.443c-0.007,0-0.017,0-0.029,0h-75.251c-7.975,0-14.442-6.466-14.442-14.442 + c0-42.243-34.368-76.612-76.612-76.612s-76.612,34.368-76.612,76.612c0,7.976-6.467,14.442-14.442,14.442H89.695 + c-7.975,0-14.442-6.466-14.442-14.442c0-99.664,81.083-180.747,180.747-180.747c99.342,0,180.223,80.566,180.744,179.788 + c0.022,0.318,0.03,0.637,0.03,0.96C436.776,263.977,430.31,270.443,422.334,270.443z M360.511,241.559h46.671 + c-7.298-76.989-72.315-137.421-151.183-137.421S112.113,164.57,104.816,241.559h46.671c7.065-51.36,51.24-91.054,104.511-91.054 + S353.447,190.199,360.511,241.559z"/> + <path style="fill:#B3404A;" d="M216.293,187.292c-3.238,0-6.496-1.083-9.188-3.309l-59.817-49.406 + c-6.149-5.079-7.017-14.182-1.938-20.331c5.079-6.149,14.181-7.019,20.331-1.938l59.817,49.406 + c6.149,5.079,7.017,14.182,1.938,20.331C224.58,185.502,220.453,187.292,216.293,187.292z"/> + <path style="fill:#B3404A;" d="M295.707,187.292c-4.161,0-8.287-1.788-11.143-5.245c-5.081-6.149-4.211-15.252,1.938-20.331 + l59.817-49.406c6.151-5.081,15.252-4.211,20.331,1.938c5.081,6.149,4.211,15.252-1.938,20.331l-59.817,49.406 + C302.203,186.207,298.946,187.292,295.707,187.292z"/> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +</svg> diff --git a/gui/resources/speed-yellow.svg b/gui/resources/speed-yellow.svg new file mode 100644 index 00000000..377a2d26 --- /dev/null +++ b/gui/resources/speed-yellow.svg @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 512.001 512.001" style="enable-background:new 0 0 512.001 512.001;" xml:space="preserve"> +<polyline style="fill:#FEE187;" points="233.225,420.726 270.89,383.061 288.971,401.143 310.88,303.847 213.584,325.756 + 231.665,343.837 174.547,400.955 "/> +<g> + <path style="fill:#FFC61B;" d="M233.226,435.168c-3.697,0-7.391-1.41-10.212-4.23c-5.64-5.64-5.64-14.784,0-20.424l37.663-37.665 + c5.489-5.488,14.293-5.635,19.962-0.443l11.135-49.454l-49.452,11.135c2.431,2.656,3.787,6.132,3.787,9.748 + c0,3.83-1.522,7.504-4.23,10.212l-57.119,57.118c-5.641,5.64-14.783,5.641-20.425,0c-5.64-5.64-5.64-14.784,0-20.424l46.906-46.906 + l-7.869-7.869c-3.722-3.722-5.124-9.175-3.66-14.231c1.466-5.056,5.564-8.915,10.7-10.072l97.296-21.909 + c4.824-1.086,9.881,0.375,13.385,3.878c3.502,3.502,4.965,8.554,3.878,13.385l-21.908,97.296 + c-1.157,5.136-5.016,9.234-10.072,10.699c-5.058,1.464-10.508,0.062-14.231-3.66l-7.869-7.869l-27.451,27.453 + C240.618,433.758,236.922,435.168,233.226,435.168z"/> + <path style="fill:#FFC61B;" d="M256,512.001c-141.159,0-256-114.841-256-256s114.841-256,256-256 + c53.115,0,104.062,16.122,147.333,46.62c6.519,4.595,8.079,13.606,3.483,20.125c-4.595,6.519-13.607,8.08-20.125,3.485 + C348.318,43.181,303.126,28.885,256,28.885c-125.232,0-227.116,101.884-227.116,227.116S130.768,483.117,256,483.117 + s227.116-101.884,227.116-227.116c0-34.43-7.503-67.493-22.3-98.275c-3.456-7.189-0.43-15.817,6.759-19.273 + c7.191-3.453,15.817-0.429,19.274,6.759c16.691,34.719,25.152,71.993,25.152,110.789C512,397.16,397.159,512.001,256,512.001z"/> + <path style="fill:#FFC61B;" d="M230.725,434.831c-0.728,0-1.464-0.055-2.205-0.169c-42.217-6.469-80.975-27.931-109.135-60.43 + c-28.458-32.843-44.132-74.831-44.132-118.232c0-99.664,81.083-180.747,180.747-180.747s180.747,81.083,180.747,180.747 + c0,7.976-6.467,14.442-14.442,14.442c-7.975,0-14.442-6.466-14.442-14.442c0-83.737-68.126-151.863-151.863-151.863 + s-151.863,68.126-151.863,151.863c0,74.329,55.353,138.863,128.757,150.11c7.884,1.209,13.295,8.579,12.088,16.462 + C243.889,429.718,237.735,434.831,230.725,434.831z"/> +</g> +<path style="fill:#FEE187;" d="M256,164.947c50.208,0,91.054,40.846,91.054,91.054h75.253c0-91.701-74.604-166.305-166.305-166.305 + S89.695,164.3,89.695,256.001h75.253C164.946,205.793,205.792,164.947,256,164.947z"/> +<g> + <path style="fill:#FFC61B;" d="M422.334,270.443c-0.007,0-0.017,0-0.029,0h-75.251c-7.975,0-14.442-6.466-14.442-14.442 + c0-42.243-34.368-76.612-76.612-76.612s-76.612,34.368-76.612,76.612c0,7.976-6.467,14.442-14.442,14.442H89.695 + c-7.975,0-14.442-6.466-14.442-14.442c0-99.664,81.083-180.747,180.747-180.747c99.342,0,180.223,80.566,180.744,179.788 + c0.022,0.318,0.03,0.637,0.03,0.96C436.776,263.977,430.31,270.443,422.334,270.443z M360.511,241.559h46.671 + c-7.298-76.989-72.315-137.421-151.183-137.421S112.113,164.57,104.816,241.559h46.671c7.065-51.36,51.24-91.054,104.511-91.054 + S353.447,190.199,360.511,241.559z"/> + <path style="fill:#FFC61B;" d="M216.293,187.292c-3.238,0-6.496-1.083-9.188-3.309l-59.817-49.406 + c-6.149-5.079-7.017-14.182-1.938-20.331c5.079-6.149,14.181-7.019,20.331-1.938l59.817,49.406 + c6.149,5.079,7.017,14.182,1.938,20.331C224.58,185.502,220.453,187.292,216.293,187.292z"/> + <path style="fill:#FFC61B;" d="M295.707,187.292c-4.161,0-8.287-1.788-11.143-5.245c-5.081-6.149-4.211-15.252,1.938-20.331 + l59.817-49.406c6.151-5.081,15.252-4.211,20.331,1.938c5.081,6.149,4.211,15.252-1.938,20.331l-59.817,49.406 + C302.203,186.207,298.946,187.292,295.707,187.292z"/> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +</svg> diff --git a/gui/resources/spy.gif b/gui/resources/spy.gif new file mode 100644 index 0000000000000000000000000000000000000000..733d3eb514155744d432b508e4bef358580a9984 GIT binary patch literal 2662 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 U+fZ5{H@NgailymJUpgQFJ2C#&egFUf literal 0 HcmV?d00001 diff --git a/gui/resources/tools.svg b/gui/resources/tools.svg new file mode 100644 index 00000000..41c63a15 --- /dev/null +++ b/gui/resources/tools.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" standalone="no"?> +<svg width="1024px" height="1024px" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon"> + <path d="M876.6 239.5c-.5-.9-1.2-1.8-2-2.5-5-5-13.1-5-18.1 0L684.2 409.3l-67.9-67.9L788.7 169c.8-.8 1.4-1.6 2-2.5 3.6-6.1 1.6-13.9-4.5-17.5-98.2-58-226.8-44.7-311.3 39.7-67 67-89.2 162-66.5 247.4l-293 293c-3 3-2.8 7.9.3 11l169.7 169.7c3.1 3.1 8.1 3.3 11 .3l292.9-292.9c85.5 22.8 180.5.7 247.6-66.4 84.4-84.5 97.7-213.1 39.7-311.3zM786 499.8c-58.1 58.1-145.3 69.3-214.6 33.6l-8.8 8.8-.1-.1-274 274.1-79.2-79.2 230.1-230.1s0 .1.1.1l52.8-52.8c-35.7-69.3-24.5-156.5 33.6-214.6a184.2 184.2 0 0 1 144-53.5L537 318.9a32.05 32.05 0 0 0 0 45.3l124.5 124.5a32.05 32.05 0 0 0 45.3 0l132.8-132.8c3.7 51.8-14.4 104.8-53.6 143.9z"/> +</svg> diff --git a/gui/themes/themes.js b/gui/themes/themes.js new file mode 100644 index 00000000..265af9a4 --- /dev/null +++ b/gui/themes/themes.js @@ -0,0 +1,51 @@ +.pragma library + +const borderColor = "#6D6D6E"; +const fontColor = "#6D6D6E"; +const fontColorDark = "#3D3D3D"; +const fontFamily = "Metropolis"; +const fontBoldFamily = "OxaniumBold"; +const fontInterFamily = "InterUI"; +const fontSize = 15; +const fontSizeLarge = 22; +const fontSizeSmall = 13; +const fontSizeSmallest = 11; +const fontWeightBold = 600; +const iconSize = 16; +const labelLineHeight = 22; +const cityListTopMargin = 18; +const controllerInterLineHeight = 18; +const hSpacing = 20; +const vSpacing = 24; +const vSpacingSmall = 16; +const listSpacing = 8; +const maxTextWidth = 296; +const windowMargin = 16; +const popupMargin = 24; +const desktopAppHeight = 520; +const desktopAppWidth = 360; +const darkFocusBorder = fontColor; +const lightFocusBorder = "#d5d3e0"; + +const accentOff = "#af0909"; +const accentConnecting = "#FFCC33"; +const accentOn = "#669933"; + +const blue = "#0060DF"; +const blueHovered = "#0250BB"; +const bluePressed = "#054096"; +const blueDisabled = "#a3c0f3"; +const blueFocusOutline = "#4d0a84ff"; +const blueFocusBorder = "#0a84ff"; + +const blueButton = { + "defaultColor" : blue, + "buttonHovered": blueHovered, + "buttonPressed": bluePressed, + "buttonDisabled": blueDisabled, + "focusBgColor": blue, + "focusOutline": blueFocusOutline, + "focusBorder": blueFocusBorder, +}; + +const bgColor = "white"; diff --git a/pkg/backend/init.go b/pkg/backend/init.go index b7469c1a..fcde725b 100644 --- a/pkg/backend/init.go +++ b/pkg/backend/init.go @@ -29,10 +29,11 @@ func initializeContext(opts *InitOpts) { DonateDialog: false, Version: version.VERSION, Status: st, + IsReady: false, } errCh := make(chan string) - go trigger(OnStatusChanged) go checkErrors(errCh) + // isReady is set after Bitmask initialization initializeBitmask(errCh, opts) go trigger(OnStatusChanged) ctx.delayCheckForGateways() @@ -86,6 +87,7 @@ func initializeBitmask(errCh chan string, opts *InitOpts) { errCh <- "nopolkit" } ctx.bm = b + ctx.IsReady = true } func setConfigOpts(opts *InitOpts, conf *config.Config) { diff --git a/pkg/backend/status.go b/pkg/backend/status.go index 1ec5c4fe..0ffd8530 100644 --- a/pkg/backend/status.go +++ b/pkg/backend/status.go @@ -49,6 +49,7 @@ type connectionCtx struct { CurrentLocation string `json:"currentLocation"` CurrentCountry string `json:"currentCountry"` ManualLocation bool `json:"manualLocation"` + IsReady bool `json:"isReady"` bm bitmask.Bitmask autostart bitmask.Autostart cfg *config.Config -- GitLab