mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-24 02:00:24 +07:00
saving intermediate version
This commit is contained in:
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
||||||
|
<!-- Monitor -->
|
||||||
|
<rect x="2.5" y="3.5" width="14" height="10" rx="2" ry="2" stroke="#D7D8DB" stroke-width="1.8"/>
|
||||||
|
<line x1="9.5" y1="13.5" x2="9.5" y2="16.5" stroke="#D7D8DB" stroke-width="1.8" stroke-linecap="round"/>
|
||||||
|
<rect x="6" y="16.5" width="7" height="1.8" rx="0.9" ry="0.9" fill="#D7D8DB"/>
|
||||||
|
|
||||||
|
<!-- Phone -->
|
||||||
|
<rect x="17.5" y="6" width="4.5" height="9.5" rx="1.2" ry="1.2" stroke="#D7D8DB" stroke-width="1.8"/>
|
||||||
|
<circle cx="19.75" cy="14.2" r="0.6" fill="#D7D8DB"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 628 B |
@@ -238,6 +238,7 @@
|
|||||||
<file>ui/qml/Pages2/PageSettingsApiNativeConfigs.qml</file>
|
<file>ui/qml/Pages2/PageSettingsApiNativeConfigs.qml</file>
|
||||||
<file>ui/qml/Pages2/PageSettingsApiDevices.qml</file>
|
<file>ui/qml/Pages2/PageSettingsApiDevices.qml</file>
|
||||||
<file>images/controls/monitor.svg</file>
|
<file>images/controls/monitor.svg</file>
|
||||||
|
<file>images/controls/monitor-with-phone.svg</file>
|
||||||
<file>ui/qml/Components/ApiPremV1MigrationDrawer.qml</file>
|
<file>ui/qml/Components/ApiPremV1MigrationDrawer.qml</file>
|
||||||
<file>ui/qml/Components/ApiPremV1SubListDrawer.qml</file>
|
<file>ui/qml/Components/ApiPremV1SubListDrawer.qml</file>
|
||||||
<file>ui/qml/Components/OtpCodeDrawer.qml</file>
|
<file>ui/qml/Components/OtpCodeDrawer.qml</file>
|
||||||
|
|||||||
@@ -265,9 +265,9 @@ PageType {
|
|||||||
amneziaVpn,
|
amneziaVpn,
|
||||||
selfHostVpn,
|
selfHostVpn,
|
||||||
backupRestore,
|
backupRestore,
|
||||||
|
shareViaDevice,
|
||||||
fileOpen,
|
fileOpen,
|
||||||
qrScan,
|
qrScan,
|
||||||
shareViaDevice,
|
|
||||||
siteLink
|
siteLink
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -318,6 +318,18 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: shareViaDevice
|
||||||
|
|
||||||
|
property string title: qsTr("Set up your Amnezia Premium VPN using your phone")
|
||||||
|
property string description: qsTr("Which already has a premium subscription")
|
||||||
|
property string imageSource: "qrc:/images/controls/monitor-with-phone.svg"
|
||||||
|
property bool isVisible: true
|
||||||
|
property var handler: function() {
|
||||||
|
PageController.goToPage(PageEnum.PageTransferConfigViaQR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: fileOpen
|
id: fileOpen
|
||||||
|
|
||||||
@@ -351,17 +363,7 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QtObject {
|
|
||||||
id: shareViaDevice
|
|
||||||
|
|
||||||
property string title: qsTr("Get connection via your device")
|
|
||||||
property string description: qsTr("")
|
|
||||||
property string imageSource: "qrc:/images/controls/share-2.svg"
|
|
||||||
property bool isVisible: true
|
|
||||||
property var handler: function() {
|
|
||||||
PageController.goToPage(PageEnum.PageTransferConfigViaQR)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: siteLink
|
id: siteLink
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,6 @@ PageType {
|
|||||||
id: root
|
id: root
|
||||||
objectName: "PageTransferConfigViaQR"
|
objectName: "PageTransferConfigViaQR"
|
||||||
|
|
||||||
property bool showReceiveSection: false
|
|
||||||
property bool showScanSection: false
|
|
||||||
property bool isPosting: false
|
|
||||||
property string postStatusText: ""
|
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.topMargin: 24
|
anchors.topMargin: 24
|
||||||
@@ -31,38 +26,84 @@ PageType {
|
|||||||
Layout.alignment: Qt.AlignLeft
|
Layout.alignment: Qt.AlignLeft
|
||||||
}
|
}
|
||||||
|
|
||||||
HeaderTypeWithButton {
|
Item {
|
||||||
|
id: contentArea
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
Layout.leftMargin: 16
|
Layout.leftMargin: 16
|
||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
headerText: qsTr("Transfer configuration")
|
Layout.bottomMargin: 16
|
||||||
actionButtonImage: (showReceiveSection || showScanSection) ? "qrc:/images/controls/close.svg" : ""
|
|
||||||
actionButtonFunction: function() {
|
ParagraphTextType {
|
||||||
showReceiveSection = false
|
id: qrHeader
|
||||||
showScanSection = false
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
text: qsTr("Scan the QR code with the phone where Amnezia Premium is active")
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: qrContainer
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: qrHeader.bottom
|
||||||
|
anchors.topMargin: 8
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
height: Math.min(qrContainer.width, parent.height - (qrHeader.height + 8) - (bottomHint.implicitHeight + 8))
|
||||||
|
color: AmneziaStyle.color.transparent
|
||||||
|
border.color: AmneziaStyle.color.paleGray
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: qrImage
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: Math.min(parent.width, parent.height)
|
||||||
|
height: width
|
||||||
|
source: TransferController.qrCodeUrl
|
||||||
|
fillMode: Image.Stretch
|
||||||
|
smooth: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CardWithIconsType {
|
SmallTextType {
|
||||||
Layout.fillWidth: true
|
id: bottomHint
|
||||||
Layout.leftMargin: 16
|
anchors.left: parent.left
|
||||||
Layout.rightMargin: 16
|
anchors.right: parent.right
|
||||||
Layout.bottomMargin: 8
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: 8
|
||||||
|
text: qsTr("In the Amnezia app on your phone, tap «+» at the bottom → «QR code»")
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
headerText: qsTr("Get connection via QR")
|
Connections {
|
||||||
bodyText: qsTr("Show a QR code that another device can scan to transfer your config here")
|
target: TransferController
|
||||||
leftImageSource: "qrc:/images/controls/qr-code.svg"
|
function onQrCodeUpdated() { qrImage.source = TransferController.qrCodeUrl }
|
||||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
function onConfigApplied() {
|
||||||
|
PageController.showNotificationMessage(qsTr("Configuration received and applied"))
|
||||||
|
}
|
||||||
|
function onWaitError(message) {
|
||||||
|
PageController.showErrorMessage(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onClicked: {
|
Connections {
|
||||||
showScanSection = false
|
target: ImportController
|
||||||
showReceiveSection = true
|
function onImportErrorOccurred(errorCode, goToPageHome) {
|
||||||
|
PageController.showErrorMessage(errorCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
TransferController.generateNewQrCode()
|
TransferController.generateNewQrCode()
|
||||||
TransferController.startWaitForConfig(ImportController)
|
TransferController.startWaitForConfig(ImportController)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: TransferController.stopWaitForConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
CardWithIconsType {
|
/*CardWithIconsType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.leftMargin: 16
|
Layout.leftMargin: 16
|
||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
@@ -79,158 +120,4 @@ PageType {
|
|||||||
isPosting = false
|
isPosting = false
|
||||||
postStatusText = ""
|
postStatusText = ""
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// Content area fills the rest of the page
|
|
||||||
Item {
|
|
||||||
id: contentArea
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.leftMargin: 16
|
|
||||||
Layout.rightMargin: 16
|
|
||||||
Layout.bottomMargin: 16
|
|
||||||
|
|
||||||
// Receive section (shows generated QR image)
|
|
||||||
Item {
|
|
||||||
id: receiveSection
|
|
||||||
anchors.fill: parent
|
|
||||||
visible: showReceiveSection
|
|
||||||
|
|
||||||
ParagraphTextType {
|
|
||||||
id: qrHeader
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
text: qsTr("Scan this QR code with your device to receive the configuration")
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
spacing: 12
|
|
||||||
|
|
||||||
BusyIndicator { running: true; visible: true; Layout.alignment: Qt.AlignVCenter }
|
|
||||||
ParagraphTextType { text: qsTr("Waiting..."); Layout.fillWidth: true }
|
|
||||||
|
|
||||||
BasicButtonType {
|
|
||||||
text: qsTr("Cancel")
|
|
||||||
Layout.preferredWidth: 120
|
|
||||||
clickedFunc: function() { TransferController.stopWaitForConfig(); showReceiveSection = false }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: qrContainer
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: qrHeader.bottom
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.topMargin: 8
|
|
||||||
anchors.bottomMargin: 56
|
|
||||||
color: AmneziaStyle.color.transparent
|
|
||||||
border.color: AmneziaStyle.color.paleGray
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
Image {
|
|
||||||
id: qrImage
|
|
||||||
anchors.fill: parent
|
|
||||||
source: TransferController.qrCodeUrl
|
|
||||||
fillMode: Image.PreserveAspectFit
|
|
||||||
smooth: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan section (embedded QR scanner)
|
|
||||||
Item {
|
|
||||||
id: scanSection
|
|
||||||
anchors.fill: parent
|
|
||||||
visible: showScanSection
|
|
||||||
|
|
||||||
ParagraphTextType {
|
|
||||||
id: scanHeader
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
text: isPosting ? qsTr("Sending...") : (postStatusText !== "" ? postStatusText : qsTr("Point the camera at the QR code on the other device and hold for a couple of seconds"))
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: scannerRect
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: scanHeader.bottom
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.topMargin: 8
|
|
||||||
color: AmneziaStyle.color.transparent
|
|
||||||
border.color: AmneziaStyle.color.paleGray
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
QRCodeReader {
|
|
||||||
id: qrReader
|
|
||||||
|
|
||||||
onCodeReaded: function(code) {
|
|
||||||
if (!isPosting) {
|
|
||||||
isPosting = true
|
|
||||||
postStatusText = ""
|
|
||||||
TransferController.onTransferQrScanned(code)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
qrReader.setCameraSize(Qt.rect(scannerRect.x,
|
|
||||||
scannerRect.y,
|
|
||||||
scannerRect.width,
|
|
||||||
scannerRect.height))
|
|
||||||
qrReader.startReading()
|
|
||||||
}
|
|
||||||
Component.onDestruction: qrReader.stopReading()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: TransferController
|
|
||||||
function onQrCodeUpdated() {
|
|
||||||
qrImage.source = TransferController.qrCodeUrl
|
|
||||||
}
|
|
||||||
function onScannerShouldStop() {
|
|
||||||
showScanSection = false
|
|
||||||
isPosting = false
|
|
||||||
postStatusText = qsTr("Sent successfully")
|
|
||||||
}
|
|
||||||
function onConfigApplied() {
|
|
||||||
showReceiveSection = false
|
|
||||||
PageController.showNotificationMessage(qsTr("Configuration received and applied"))
|
|
||||||
}
|
|
||||||
function onWaitError(message) {
|
|
||||||
PageController.showErrorMessage(message)
|
|
||||||
}
|
|
||||||
function onPostStarted() {
|
|
||||||
isPosting = true
|
|
||||||
postStatusText = ""
|
|
||||||
}
|
|
||||||
function onPostSucceeded() {
|
|
||||||
isPosting = false
|
|
||||||
postStatusText = qsTr("Sent successfully")
|
|
||||||
}
|
|
||||||
function onPostFailed(message) {
|
|
||||||
isPosting = false
|
|
||||||
postStatusText = message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: ImportController
|
|
||||||
function onImportErrorOccurred(errorCode, goToPageHome) {
|
|
||||||
PageController.showErrorMessage(errorCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onDestruction: {
|
|
||||||
TransferController.stopWaitForConfig()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user