added exportController and PageShare

- added a blank PageSettingsProtocol
This commit is contained in:
vladimir.kuznetsov 2023-06-13 20:03:20 +09:00
parent 3034019d5a
commit be7386f0d7
38 changed files with 1080 additions and 115 deletions

View file

@ -59,7 +59,7 @@ ListView {
menuContent.currentIndex = index
containersDropDown.menuVisible = false
} else {
ContainersModel.setCurrentlyInstalledContainerIndex(proxyContainersModel.mapToSource(index))
ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(index))
InstallController.setShouldCreateServer(false)
goToPage(PageEnum.PageSetupWizardProtocolSettings)
containersDropDown.menuVisible = false

View file

@ -8,8 +8,12 @@ import "../../Components"
Item {
id: root
implicitHeight: col.implicitHeight
implicitWidth: col.implicitWidth
ColumnLayout {
id: col
anchors.fill: parent
anchors.leftMargin: 16
@ -51,13 +55,79 @@ Item {
}
DropDownType {
id: hash
Layout.fillWidth: true
implicitHeight: 74
rootButtonBorderWidth: 0
descriptionText: qsTr("Hash")
headerText: qsTr("Hash")
listView: ListViewType {
rootWidth: root.width
model: ListModel {
ListElement { name : qsTr("SHA512") }
ListElement { name : qsTr("SHA384") }
ListElement { name : qsTr("SHA256") }
ListElement { name : qsTr("SHA3-512") }
ListElement { name : qsTr("SHA3-384") }
ListElement { name : qsTr("SHA3-256") }
ListElement { name : qsTr("whirlpool") }
ListElement { name : qsTr("BLAKE2b512") }
ListElement { name : qsTr("BLAKE2s256") }
ListElement { name : qsTr("SHA1") }
}
currentIndex: 0
clickedFunction: {
hash.text = selectedText
hash.menuVisible = false
}
Component.onCompleted: {
hash.text = selectedText
}
}
}
DropDownType {
id: cipher
Layout.fillWidth: true
implicitHeight: 74
rootButtonBorderWidth: 0
descriptionText: qsTr("Cipher")
headerText: qsTr("Cipher")
listView: ListViewType {
rootWidth: root.width
model: ListModel {
ListElement { name : qsTr("AES-256-GCM") }
ListElement { name : qsTr("AES-192-GCM") }
ListElement { name : qsTr("AES-128-GCM") }
ListElement { name : qsTr("AES-256-CBC") }
ListElement { name : qsTr("AES-192-CBC") }
ListElement { name : qsTr("AES-128-CBC") }
ListElement { name : qsTr("ChaCha20-Poly1305") }
ListElement { name : qsTr("ARIA-256-CBC") }
ListElement { name : qsTr("CAMELLIA-256-CBC") }
ListElement { name : qsTr("none") }
}
currentIndex: 0
clickedFunction: {
cipher.text = selectedText
cipher.menuVisible = false
}
Component.onCompleted: {
cipher.text = selectedText
}
}
}
CheckBoxType {

View file

@ -88,9 +88,10 @@ ListView {
onClicked: {
if (isInstalled) {
ContainersModel.setCurrentlyProcessedContainerIndex(root.model.mapToSource(index))
goToPage(PageEnum.PageSettingsServerProtocol)
} else {
ContainersModel.setCurrentlyInstalledContainerIndex(root.model.mapToSource(index))
ContainersModel.setCurrentlyProcessedContainerIndex(root.model.mapToSource(index))
InstallController.setShouldCreateServer(false)
goToPage(PageEnum.PageSetupWizardProtocolSettings)
}

View file

@ -0,0 +1,177 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Dialogs
import SortFilterProxyModel 0.2
import PageEnum 1.0
import ContainerProps 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
DrawerType {
id: root
property var qrCodes: []
property alias configText: configContent.text
property alias headerText: header.headerText
width: parent.width
height: parent.height * 0.9
Item{
anchors.fill: parent
FlickableType {
anchors.top: parent.top
anchors.bottom: parent.bottom
contentHeight: content.height + 32
ColumnLayout {
id: content
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 20
anchors.leftMargin: 16
anchors.rightMargin: 16
Header2Type {
id: header
Layout.fillWidth: true
}
BasicButtonType {
Layout.fillWidth: true
Layout.topMargin: 16
text: qsTr("Save connection code")
onClicked: {
ExportController.saveFile()
}
}
BasicButtonType {
Layout.fillWidth: true
Layout.topMargin: 8
defaultColor: "transparent"
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
pressedColor: Qt.rgba(1, 1, 1, 0.12)
disabledColor: "#878B91"
textColor: "#D7D8DB"
borderWidth: 1
text: qsTr("Copy")
onClicked: {
configContent.selectAll()
configContent.copy()
configContent.select(0, 0)
}
}
BasicButtonType {
Layout.fillWidth: true
Layout.topMargin: 8
defaultColor: "transparent"
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
pressedColor: Qt.rgba(1, 1, 1, 0.12)
disabledColor: "#878B91"
textColor: "#D7D8DB"
text: showContent ? qsTr("Collapse content") : qsTr("Show content")
onClicked: {
showContent = !showContent
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: configContent.implicitHeight + configContent.anchors.topMargin + configContent.anchors.bottomMargin
radius: 10
color: "#2C2D30"
visible: showContent
height: 24
TextField {
id: configContent
anchors.fill: parent
anchors.margins: 16
height: 24
color: "#D7D8DB"
font.pixelSize: 16
font.weight: Font.Medium
font.family: "PT Root UI VF"
wrapMode: Text.Wrap
enabled: false
background: Rectangle {
anchors.fill: parent
color: "transparent"
}
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: width
Layout.topMargin: 20
color: "white"
Image {
anchors.fill: parent
smooth: false
Timer {
property int idx: 0
interval: 1000
running: qrCodes.length > 0
repeat: true
onTriggered: {
idx++
if (idx >= qrCodes.length) {
idx = 0
}
parent.source = qrCodes[idx]
}
}
Behavior on source {
PropertyAnimation { duration: 200 }
}
visible: qrCodes.length > 0
}
}
ParagraphTextType {
Layout.fillWidth: true
Layout.topMargin: 24
Layout.bottomMargin: 32
horizontalAlignment: Text.AlignHCenter
text: qsTr("To read the QR code in the Amnezia app, select \"Add Server\" → \"I have connection details\"")
}
}
}
}
}

View file

@ -11,6 +11,8 @@ Item {
implicitWidth: content.implicitWidth
implicitHeight: content.implicitHeight
visible: backButtonImage !== ""
RowLayout {
id: content

View file

@ -19,11 +19,12 @@ Item {
property string rootButtonImage: "qrc:/images/controls/chevron-down.svg"
property string rootButtonImageColor: "#494B50"
property string rootButtonDefaultColor: "#1C1D21"
property int rootButtonMaximumWidth
property int rootButtonMaximumWidth: 0
property string rootButtonBorderColor: "#494B50"
property int rootButtonBorderWidth: 1
property real drawerHeight: 0.9
property Component listView
property alias menuVisible: menu.visible
@ -55,7 +56,9 @@ Item {
Layout.leftMargin: 16
LabelTextType {
horizontalAlignment: Text.AlignHCenter
Layout.fillWidth: true
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
visible: root.descriptionText !== ""
@ -65,7 +68,9 @@ Item {
}
ButtonTextType {
horizontalAlignment: Text.AlignHCenter
Layout.fillWidth: true
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
Layout.maximumWidth: rootButtonMaximumWidth ? rootButtonMaximumWidth : implicitWidth
@ -115,7 +120,7 @@ Item {
id: menu
width: parent.width
height: parent.height * 0.9
height: parent.height * drawerHeight
ColumnLayout {
id: header

View file

@ -0,0 +1,107 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import "TextTypes"
ListView {
id: menuContent
property var rootWidth
property var selectedText
property string imageSource
property var clickedFunction
property bool dividerVisible: false
width: rootWidth
height: menuContent.contentItem.height
clip: true
interactive: false
ButtonGroup {
id: buttonGroup
}
delegate: Item {
implicitWidth: rootWidth
implicitHeight: content.implicitHeight
ColumnLayout {
id: content
anchors.fill: parent
spacing: 16
RadioButton {
id: radioButton
implicitWidth: parent.width
implicitHeight: radioButtonContent.implicitHeight
hoverEnabled: true
indicator: Rectangle {
anchors.fill: parent
color: radioButton.hovered ? "#2C2D30" : "#1C1D21"
Behavior on color {
PropertyAnimation { duration: 200 }
}
}
RowLayout {
id: radioButtonContent
anchors.fill: parent
anchors.rightMargin: 16
anchors.leftMargin: 16
z: 1
ParagraphTextType {
Layout.fillWidth: true
Layout.topMargin: 20
Layout.bottomMargin: 20
text: name
}
Image {
source: imageSource ? imageSource : "qrc:/images/controls/check.svg"
visible: imageSource ? true : radioButton.checked
width: 24
height: 24
Layout.rightMargin: 8
}
}
ButtonGroup.group: buttonGroup
checked: menuContent.currentIndex === index
onClicked: {
menuContent.currentIndex = index
menuContent.selectedText = name
if (clickedFunction && typeof clickedFunction === "function") {
clickedFunction()
}
}
}
DividerType {
Layout.fillWidth: true
Layout.bottomMargin: 16
visible: dividerVisible
}
}
Component.onCompleted: {
if (menuContent.currentIndex === index) {
menuContent.selectedText = name
}
}
}
}

View file

@ -23,12 +23,6 @@ RadioButton {
property string defaultBodredColor: "transparent"
property int borderWidth: 0
property string defaultCircleBorderColor: "#878B91"
property string selectedCircleBorderColor: "#A85809"
property string pressedCircleBorderColor: Qt.rgba(251/255, 178/255, 106/255, 0.3)
property string defaultInnerCircleColor: "#FBB26A"
property string imageSource
property bool showImage
@ -61,80 +55,38 @@ RadioButton {
}
Image {
source: imageSource
visible: showImage
source: {
if (showImage) {
return imageSource
} else if (root.pressed) {
return "qrc:/images/controls/radio-button-inner-circle-pressed.png"
} else if (root.checked) {
return "qrc:/images/controls/radio-button-inner-circle.png"
}
return ""
}
anchors.centerIn: parent
width: 24
height: 24
}
Rectangle {
id: outerCircle
width: 24
height: 24
radius: 16
visible: !showImage
Image {
source: {
if (showImage) {
return ""
} else if (root.pressed || root.checked) {
return "qrc:/images/controls/radio-button-pressed.svg"
} else {
return "qrc:/images/controls/radio-button.svg"
}
}
anchors.centerIn: parent
color: "transparent"
border.color: {
if (root.enabled) {
if (root.pressed) {
return pressedCircleBorderColor
} else if (root.checked) {
return selectedCircleBorderColor
}
}
return defaultCircleBorderColor
}
border.width: 1
Behavior on border.color {
PropertyAnimation { duration: 200 }
}
Rectangle {
id: innerCircle
width: 12
height: 12
radius: 16
anchors.centerIn: parent
color: "transparent"
border.color: defaultInnerCircleColor
border.width: {
if (root.enabled) {
if(root.checked) {
return 6
}
return root.pressed ? 6 : 0
} else {
return 0
}
}
Behavior on border.width {
PropertyAnimation { duration: 200 }
}
}
DropShadow {
anchors.fill: innerCircle
horizontalOffset: 0
verticalOffset: 0
radius: 12
samples: 13
color: "#FBB26A"
source: innerCircle
}
width: 24
height: 24
}
}

View file

@ -111,7 +111,7 @@ PageType {
id: menu
width: parent.width
height: parent.height * 0.90
height: parent.height * 0.9
ColumnLayout {
id: serversMenuHeader
@ -247,8 +247,8 @@ PageType {
ColumnLayout {
id: serverRadioButtonContent
anchors.fill: parent
anchors.fill: parent
anchors.rightMargin: 16
anchors.leftMargin: 16

View file

@ -18,7 +18,64 @@ import "../Components/Protocols"
PageType {
id: root
OpenVpnSettings {
FlickableType {
id: fl
anchors.fill: parent
contentHeight: content.height + openVpnSettings.implicitHeight
Column {
id: content
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: 16
ListView {
// todo change id naming
id: container
width: parent.width
height: container.contentItem.height
clip: true
interactive: false
model: SortFilterProxyModel {
id: proxyContainersModel
sourceModel: ContainersModel
filters: [
ValueFilter {
roleName: "isCurrentlyProcessed"
value: true
}
]
}
delegate: Item {
implicitWidth: container.width
implicitHeight: delegateContent.implicitHeight
ColumnLayout {
id: delegateContent
anchors.fill: parent
anchors.rightMargin: 16
anchors.leftMargin: 16
HeaderType {
Layout.fillWidth: true
Layout.topMargin: 20
headerText: name
}
}
}
}
OpenVpnSettings {
id: openVpnSettings
width: parent.width
}
}
}
}

View file

@ -134,7 +134,7 @@ PageType {
text: qsTr("Continue")
onClicked: function() {
ContainersModel.setCurrentlyInstalledContainerIndex(containers.dockerContainer)
ContainersModel.setCurrentlyProcessedContainerIndex(containers.dockerContainer)
goToPage(PageEnum.PageSetupWizardInstalling);
InstallController.install(containers.dockerContainer,
containers.containerDefaultPort,

View file

@ -54,7 +54,7 @@ PageType {
sourceModel: ContainersModel
filters: [
ValueFilter {
roleName: "isCurrentlyInstalled"
roleName: "isCurrentlyProcessed"
value: true
}
]

View file

@ -22,7 +22,7 @@ PageType {
sourceModel: ContainersModel
filters: [
ValueFilter {
roleName: "isCurrentlyInstalled"
roleName: "isCurrentlyProcessed"
value: true
}
]

View file

@ -90,7 +90,7 @@ PageType {
buttonImage: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() {
ContainersModel.setCurrentlyInstalledContainerIndex(proxyContainersModel.mapToSource(index))
ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(index))
goToPage(PageEnum.PageSetupWizardProtocolSettings)
}
}

View file

@ -1,5 +1,330 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Dialogs
Item {
import SortFilterProxyModel 0.2
import PageEnum 1.0
import ContainerProps 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Components"
PageType {
id: root
Connections {
target: ExportController
function onGenerateConfig(isFullAccess) {
if (isFullAccess) {
ExportController.generateFullAccessConfig()
} else {
ExportController.generateConnectionConfig()
}
shareConnectionDrawer.configText = ExportController.getAmneziaCode()
shareConnectionDrawer.qrCodes = ExportController.getQrCodes()
}
}
property bool showContent: false
property list<QtObject> connectionTypesModel: [
amneziaConnectionFormat
]
QtObject {
id: amneziaConnectionFormat
property string name: qsTr("For the AmnesiaVPN app")
property var func: function() {
ExportController.generateConfig(false)
}
}
QtObject {
id: openVpnConnectionFormat
property string name: qsTr("OpenVpn native format")
property var func: function() {
console.log("Item 3 clicked")
}
}
QtObject {
id: wireGuardConnectionFormat
property string name: qsTr("WireGuard native format")
property var func: function() {
console.log("Item 3 clicked")
}
}
FlickableType {
anchors.top: root.top
anchors.bottom: root.bottom
contentHeight: content.height
ColumnLayout {
id: content
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: 16
anchors.leftMargin: 16
HeaderType {
Layout.fillWidth: true
Layout.topMargin: 20
headerText: qsTr("VPN Access")
}
Rectangle {
id: accessTypeSelector
property int currentIndex
Layout.topMargin: 32
implicitWidth: accessTypeSelectorContent.implicitWidth
implicitHeight: accessTypeSelectorContent.implicitHeight
color: "#1C1D21"
radius: 16
RowLayout {
id: accessTypeSelectorContent
spacing: 0
HorizontalRadioButton {
checked: accessTypeSelector.currentIndex === 0
implicitWidth: (root.width - 32) / 2
text: qsTr("Connection")
onClicked: {
accessTypeSelector.currentIndex = 0
}
}
HorizontalRadioButton {
checked: root.currentIndex === 1
implicitWidth: (root.width - 32) / 2
text: qsTr("Full")
onClicked: {
accessTypeSelector.currentIndex = 1
}
}
}
}
ParagraphTextType {
Layout.fillWidth: true
text: qsTr("VPN access without the ability to manage the server")
color: "#878B91"
}
DropDownType {
id: serverSelector
Layout.fillWidth: true
Layout.topMargin: 24
implicitHeight: 74
rootButtonBorderWidth: 0
drawerHeight: 0.4375
descriptionText: qsTr("Server and service")
headerText: qsTr("Server")
listView: ListViewType {
rootWidth: root.width
dividerVisible: true
imageSource: "qrc:/images/controls/chevron-right.svg"
model: ServersModel
currentIndex: ServersModel.getDefaultServerIndex()
clickedFunction: function() {
serverSelector.text = selectedText
ContainersModel.setCurrentlyProcessedServerIndex(currentIndex)
protocolSelector.visible = true
}
Component.onCompleted: {
serverSelector.text = selectedText
ContainersModel.setCurrentlyProcessedServerIndex(currentIndex)
}
}
DrawerType {
id: protocolSelector
width: parent.width
height: parent.height * 0.5
ColumnLayout {
id: header
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 16
anchors.leftMargin: 16
anchors.rightMargin: 16
BackButtonType {
backButtonImage: "qrc:/images/controls/arrow-left.svg"
backButtonFunction: function() {
protocolSelector.visible = false
}
}
}
FlickableType {
anchors.top: header.bottom
anchors.topMargin: 16
contentHeight: col.implicitHeight
Column {
id: col
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: 16
Header2TextType {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 16
anchors.rightMargin: 16
text: qsTr("Protocols and services")
wrapMode: Text.WordWrap
}
ListViewType {
rootWidth: root.width
dividerVisible: true
imageSource: "qrc:/images/controls/chevron-right.svg"
model: SortFilterProxyModel {
id: proxyContainersModel
sourceModel: ContainersModel
filters: [
ValueFilter {
roleName: "isInstalled"
value: true
}
]
}
currentIndex: 0
clickedFunction: function () {
serverSelector.text += ", " + selectedText
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
protocolSelector.visible = false
serverSelector.menuVisible = false
fillConnectionTypeModel()
}
Component.onCompleted: {
serverSelector.text += ", " + selectedText
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
fillConnectionTypeModel()
}
function fillConnectionTypeModel() {
connectionTypesModel = [amneziaConnectionFormat]
if (currentIndex === ContainerProps.containerFromString("OpenVpn")) {
connectionTypesModel.push(openVpnConnectionFormat)
} else if (currentIndex === ContainerProps.containerFromString("wireGuardConnectionType")) {
connectionTypesModel.push(amneziaConnectionFormat)
}
}
}
}
}
}
}
DropDownType {
id: connectionTypeSelector
property int currentIndex
Layout.fillWidth: true
Layout.topMargin: 16
implicitHeight: 74
rootButtonBorderWidth: 0
drawerHeight: 0.4375
visible: accessTypeSelector.currentIndex === 0
enabled: connectionTypesModel.length > 1
descriptionText: qsTr("Connection format")
headerText: qsTr("Connection format")
listView: ListViewType {
id: connectionTypeSelectorListView
rootWidth: root.width
dividerVisible: true
imageSource: "qrc:/images/controls/chevron-right.svg"
model: connectionTypesModel
currentIndex: 0
clickedFunction: function() {
connectionTypeSelector.text = selectedText
connectionTypeSelector.currentIndex = currentIndex
connectionTypeSelector.menuVisible = false
}
Component.onCompleted: {
connectionTypeSelector.text = selectedText
connectionTypeSelector.currentIndex = currentIndex
}
}
}
ShareConnectionDrawer {
id: shareConnectionDrawer
}
BasicButtonType {
Layout.fillWidth: true
Layout.topMargin: 32
text: qsTr("Share")
onClicked: {
if (accessTypeSelector.currentIndex === 0) {
connectionTypesModel[connectionTypeSelector.currentIndex].func()
} else {
ExportController.generateConfig(true)
}
shareConnectionDrawer.visible = true
}
}
}
}
}

View file

@ -78,7 +78,9 @@ PageType {
TabImageButtonType {
isSelected: tabBar.currentIndex === 1
image: "qrc:/images/controls/share-2.svg"
onClicked: {}
onClicked: {
tabBarStackView.goToTabBarPage(PageEnum.PageShare)
}
}
TabImageButtonType {
isSelected: tabBar.currentIndex === 2