Skip to content
Snippets Groups Projects
Unverified Commit d7e65d5c authored by Kali Kaneko's avatar Kali Kaneko
Browse files

[ui] pseudo-load based on distance

parent ab6360dd
No related branches found
No related tags found
No related merge requests found
......@@ -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
}
}
}
......
......@@ -34,9 +34,9 @@ ThemedPage {
Rectangle {
id: turnOffWarning
visible: false
height: 40
height: 20
width: parent.width
color: Theme.bgColor
color: "white"
Label {
......
......@@ -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)
......
......@@ -96,14 +96,18 @@ func (p *gatewayPool) listLocationFullness(transport string) map[string]float64
return cm
}
if len(p.recommended) != 0 {
for _, gw := range p.recommended {
for idx, gw := range p.recommended {
if gw.gateway.Transport != transport {
continue
}
if _, ok := cm[gw.gateway.Location]; ok {
continue
}
cm[gw.gateway.Location] = gw.Fullness
if gw.Fullness != -1 {
cm[gw.gateway.Location] = gw.Fullness
} else {
cm[gw.gateway.Location] = 1 - float64(idx)/float64(len(p.recommended))
}
}
} else {
for _, location := range locations {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment