diff options
Diffstat (limited to 'gui')
-rw-r--r-- | gui/components/Locations.qml | 183 | ||||
-rw-r--r-- | gui/components/Preferences.qml | 4 | ||||
-rw-r--r-- | gui/main.qml | 49 |
3 files changed, 130 insertions, 106 deletions
diff --git a/gui/components/Locations.qml b/gui/components/Locations.qml index a0e7a30..ce510c5 100644 --- a/gui/components/Locations.qml +++ b/gui/components/Locations.qml @@ -5,10 +5,8 @@ import QtGraphicalEffects 1.0 import "../themes/themes.js" as Theme + /* TODO - [ ] build a better gateway object list (location, user-friendly, country, bridge, etc) - [ ] ui: mark manual override icon somehow? - [ ] ui: auto radiobutton should use also the bridge icon [ ] corner case: manual override, not full list yet [ ] persist bridges [ ] persist manual selection @@ -17,13 +15,12 @@ import "../themes/themes.js" as Theme (I think the backend should discard any manual selection when selecting bridges... unless the current selection provides the bridge, in which case we can maintain it) */ - ThemedPage { id: locationPage title: qsTr("Select Location") - // TODO add ScrollIndicator + // TODO add ScrollIndicator // https://doc.qt.io/qt-5.12//qml-qtquick-controls2-scrollindicator.html //: this is in the radio button for the auto selection @@ -68,7 +65,7 @@ ThemedPage { WrappedRadioButton { id: autoRadioButton anchors.top: recommendedLabel.bottom - text: getAutoLabel() + text: getAutoLabel() ButtonGroup.group: locsel checked: false onClicked: { @@ -84,85 +81,109 @@ ThemedPage { id: manualBox visible: root.locationsModel.length > 0 width: root.width * 0.90 - height: getManualBoxHeight() radius: 10 color: Theme.fgColor + height: root.height * 0.60 + anchors { horizontalCenter: parent.horizontalCenter top: autoBox.bottom margins: 10 } - Rectangle { - anchors { - fill: parent - margins: 10 - } - Label { - id: manualLabel - text: manualSelectionLabel - font.bold: true - } - Label { - id: bridgeWarning - text: onlyBridgesWarning - color: "gray" - visible: isBridgeSelected() - wrapMode: Text.Wrap - anchors { - topMargin: 5 - top: manualLabel.bottom - } - font.pixelSize: Theme.fontSize - 3 - } - ColumnLayout { - id: gatewayListColumn + + ScrollView { + id: frame + clip: true + anchors.fill: parent + ScrollBar.vertical.policy: ScrollBar.AlwaysOff + + Flickable { + id: flickable + contentHeight: getManualBoxHeight() width: parent.width - spacing: 1 - anchors.top: getManualAnchor() - Repeater { - id: gwManualSelectorList - width: parent.width - model: root.locationsModel + ScrollIndicator.vertical: ScrollIndicator { + size: 5 + contentItem: Rectangle { + implicitWidth: 5 + implicitHeight: 100 + color: "grey" + } + } - RowLayout { + Rectangle { + anchors { + fill: parent + margins: 10 + } + Label { + id: manualLabel + text: manualSelectionLabel + font.bold: true + } + Label { + id: bridgeWarning + text: onlyBridgesWarning + color: "gray" + visible: isBridgeSelected() + wrapMode: Text.Wrap + anchors { + topMargin: 5 + top: manualLabel.bottom + } + font.pixelSize: Theme.fontSize - 3 + } + + ColumnLayout { + id: gatewayListColumn width: parent.width - WrappedRadioButton { - text: getLocationLabel(modelData) - location: modelData - ButtonGroup.group: locsel - checked: false - enabled: locationPage.switching ? false : true - onClicked: { - if (ctx.status == "on") { - locationPage.switching = true + spacing: 1 + anchors.top: getManualAnchor() + + Repeater { + id: gwManualSelectorList + width: parent.width + model: root.locationsModel + + RowLayout { + width: parent.width + WrappedRadioButton { + text: getLocationLabel(modelData) + location: modelData + ButtonGroup.group: locsel + checked: false + enabled: locationPage.switching ? false : true + onClicked: { + if (ctx.status == "on") { + locationPage.switching = true + } + root.selectedGateway = location + backend.useLocation(location) + } + } + Item { + Layout.fillWidth: true + } + Image { + height: 16 + width: 16 + visible: isBridgeSelected() + source: "../resources/bridge.png" + Layout.alignment: Qt.AlignRight + Layout.rightMargin: 10 + } + SignalIcon { + quality: getSignalFor(modelData) + Layout.alignment: Qt.AlignRight + Layout.rightMargin: 20 } - root.selectedGateway = location - backend.useLocation(location) } } - Item { - Layout.fillWidth: true - } - Image { - height: 16 - width: 16 - visible: isBridgeSelected() - source: "../resources/bridge.png" - Layout.alignment: Qt.AlignRight - Layout.rightMargin: 10 - } - SignalIcon { - // TODO mocked! - quality: getSignalFor(modelData) - Layout.alignment: Qt.AlignRight - Layout.rightMargin: 20 - } } } - } - } - } + } //flickable + } // scrollview + } // manualbox StateGroup { states: [ @@ -199,7 +220,9 @@ ThemedPage { } function getLocationLabel(location) { - if (!ctx) { return ""} + if (!ctx) { + return "" + } let l = ctx.locationLabels[location] return l[0] + ", " + l[1] } @@ -213,13 +236,13 @@ ThemedPage { } function getSignalFor(location) { - switch(location) { - case "amsterdam": - case "paris": + // this is an ad-hoc solution for the no-menshen, riseup case. + // when menshen is deployed we'll want to tweak the values for each bucket. + let load = ctx.locations[location] + switch (true) { + case (load > 0.5): return "good" - case "newyork": - return "medium" - case "montreal": + case (load > 0.25): return "medium" default: return "low" @@ -244,14 +267,14 @@ ThemedPage { Component.onCompleted: { if (root.selectedGateway == "auto") { - autoRadioButton.checked = true; + autoRadioButton.checked = true } else { let match = false - for (var i=1; i<locsel.buttons.length; i++) { + for (var i = 1; i < locsel.buttons.length; i++) { let b = locsel.buttons[i] if (b.location == root.selectedGateway) { - match = true; - b.checked = true; + match = true + b.checked = true } } } diff --git a/gui/components/Preferences.qml b/gui/components/Preferences.qml index 2b0aae8..cc25101 100644 --- a/gui/components/Preferences.qml +++ b/gui/components/Preferences.qml @@ -34,9 +34,9 @@ ThemedPage { Rectangle { id: turnOffWarning visible: false - height: 40 + height: 20 width: parent.width - color: Theme.bgColor + color: "white" Label { diff --git a/gui/main.qml b/gui/main.qml index d8bfb91..0024670 100644 --- a/gui/main.qml +++ b/gui/main.qml @@ -2,21 +2,11 @@ /* TODO (ui rewrite) - - [x] add systray - - [x] systray status - - [x] splash screen - - [x] splash delay/transitions - - [x] font: monserrat - - [x] nested states - - [x] splash init errors - - [x] gateway selector - - [ ] bridges + See https://0xacab.org/leap/bitmask-vpn/-/issues/523 + - [x] udp support - [ ] minimize/hide from systray - [ ] control actions from systray - [ ] add gateway to systray - - [ ] donation dialog - - [ ] parse ctx flags (need dialog, etc) - - [ ] udp support */ import QtQuick 2.0 import QtQuick.Controls 2.4 @@ -42,7 +32,6 @@ ApplicationWindow { minimumHeight: appHeight maximumHeight: appHeight - title: ctx ? ctx.appName : "VPN" Material.accent: Material.Green @@ -56,6 +45,7 @@ ApplicationWindow { // TODO get from persistance property var selectedGateway: "auto" + // FIXME get svg icons property var icons: { "off": "qrc:/assets/icon/png/white/vpn_off.png", "on": "qrc:/assets/icon/png/white/vpn_on.png", @@ -90,7 +80,6 @@ ApplicationWindow { id: systray } - Connections { target: jsonModel function onDataChanged() { @@ -100,7 +89,8 @@ ApplicationWindow { } ctx = JSON.parse(j) if (ctx != undefined) { - locationsModel = Object.keys(ctx.locations) + locationsModel = getSortedLocations() + console.debug("Got sorted locations:" + locationsModel) } if (ctx.errors) { console.debug("errors, setting root.error") @@ -109,10 +99,10 @@ ApplicationWindow { root.error = "" } if (ctx.donateURL) { - isDonationService = true; + isDonationService = true } if (ctx.donateDialog == 'true') { - showDonationReminder = true; + showDonationReminder = true } // TODO check donation @@ -122,15 +112,9 @@ ApplicationWindow { // // move this to onClick of "close" for widget // backend.donateSeen(); //} - // TODO refactor donate widget into main view (with close window!) - //if (ctx.status == "on") { - // gwNextConnectionText.visible = false - // gwReconnectText.visible = false - // when: vpn.status == "on" - //} /* - TODO libraries need login + TODO libraries need login if (ctx.loginDialog == 'true') { login.visible = true } @@ -141,6 +125,23 @@ ApplicationWindow { } } + function getSortedLocations() { + let obj = ctx.locations + var arr = [] + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + arr.push({ + "key": prop, + "value": obj[prop] + }) + } + } + arr.sort(function (a, b) { + return a.value - b.value + }).reverse() + return Array.from(arr, (k,_) => k.key); + } + onSceneGraphError: function (error, msg) { console.debug("ERROR while initializing scene") console.debug(msg) |