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

[ui] refactor ui

parent 76585f82
No related branches found
No related tags found
No related merge requests found
Showing
with 848 additions and 1 deletion
#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")
......
QML best practices
==================
* https://github.com/Furkanzmc/QML-Coding-Guide/blob/master/README.md
* lint your qml files::
make qmllint
......@@ -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
......
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
}
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
}
}
}
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
}
}
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")
}
}
}
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtGraphicalEffects 1.0
Page {
StatusBox {}
}
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
}
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
}
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"
}
}
}
}
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
}
}
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
}
}
}
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")
}
}
}
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
}
]
}
}
}
}
}
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: {
}
}
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
}
*/
}
}
}
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"
}
}
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()
}
}
}
/* 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"
}
}
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