Files
amnezia-client/client/ui/qml/Pages2/PageSetupWizardApiQrPairingReceive.qml
T

193 lines
5.6 KiB
QML
Raw Normal View History

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Style 1.0
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
import "../Components"
PageType {
id: root
2026-05-08 08:37:18 +03:00
readonly property int qrRefreshIntervalMs: Math.max(5000, PairingUiController.tvPairingWaitWindowSeconds * 1000)
2026-05-07 21:51:39 +03:00
function scrollPairingToBottom() {
receiveScroll.contentY = Math.max(0, receiveScroll.contentHeight - receiveScroll.height)
}
2026-05-08 08:37:18 +03:00
function beginReceiveFlow() {
PairingUiController.startTvQrSession()
qrRotationTimer.restart()
}
2026-05-07 21:51:39 +03:00
Timer {
id: scrollToBottomRetryTimer
interval: 48
repeat: true
property int retries: 0
onTriggered: {
root.scrollPairingToBottom()
retries++
if (retries >= 12) {
stop()
}
}
onRunningChanged: {
if (!running) {
retries = 0
}
}
}
Timer {
2026-05-08 08:37:18 +03:00
id: qrRotationTimer
interval: root.qrRefreshIntervalMs
2026-05-07 21:51:39 +03:00
repeat: true
2026-05-08 08:37:18 +03:00
running: root.visible
2026-05-07 21:51:39 +03:00
onTriggered: {
PairingUiController.rotateTvQrSession()
2026-05-07 21:51:39 +03:00
}
}
Connections {
target: root
function onVisibleChanged() {
if (!root.visible) {
PairingUiController.cancelAllPairingActivity()
2026-05-07 21:51:39 +03:00
scrollToBottomRetryTimer.stop()
2026-05-08 08:37:18 +03:00
qrRotationTimer.stop()
} else {
Qt.callLater(root.beginReceiveFlow)
}
}
}
2026-05-08 08:37:18 +03:00
Component.onCompleted: {
if (root.visible) {
Qt.callLater(root.beginReceiveFlow)
}
}
FlickableType {
2026-05-07 21:51:39 +03:00
id: receiveScroll
anchors.fill: parent
contentHeight: layout.implicitHeight
2026-05-07 21:51:39 +03:00
Behavior on contentY {
NumberAnimation {
duration: 320
easing.type: Easing.OutCubic
}
}
onContentHeightChanged: {
if (PairingUiController.tvQrCodesCount > 0) {
Qt.callLater(root.scrollPairingToBottom)
}
}
ColumnLayout {
id: layout
width: root.width
2026-05-08 08:37:18 +03:00
spacing: 12
BackButtonType {
Layout.topMargin: 20 + PageController.safeAreaTopMargin
}
Label {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
Layout.topMargin: 8
2026-05-08 08:37:18 +03:00
horizontalAlignment: Text.AlignHCenter
text: qsTr("Scan this QR code with a phone that has an active Amnezia Premium subscription")
font.pixelSize: 17
font.bold: false
color: AmneziaStyle.color.paleGray
wrapMode: Text.Wrap
}
Item {
id: qrBox
Layout.fillWidth: true
2026-05-08 08:37:18 +03:00
Layout.leftMargin: 24
Layout.rightMargin: 24
Layout.topMargin: 16
// Avoid width*0.92 before first layout (width can be 0 → zero height → no QR).
Layout.preferredHeight: PairingUiController.tvQrCodesCount > 0 ? Math.max(200, layout.width - 48) : 0
visible: PairingUiController.tvQrCodesCount > 0
2026-05-08 08:37:18 +03:00
Rectangle {
anchors.fill: parent
2026-05-08 08:37:18 +03:00
radius: 20
color: "#FFFFFF"
2026-05-08 08:37:18 +03:00
Image {
id: qrImage
anchors.fill: parent
2026-05-08 08:37:18 +03:00
anchors.margins: 20
fillMode: Image.PreserveAspectFit
sourceSize: Qt.size(2048, 2048)
2026-05-19 23:11:34 +03:00
source: PairingUiController.tvQrCodesCount > 0 ? PairingUiController.tvQrCodes[0] : ""
}
}
}
2026-05-07 21:51:39 +03:00
ParagraphTextType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
2026-05-08 08:37:18 +03:00
Layout.topMargin: 24
horizontalAlignment: Text.AlignHCenter
color: AmneziaStyle.color.mutedGray
2026-05-08 08:37:18 +03:00
font.pixelSize: 13
text: qsTr("AmneziaVPN → Amnezia Premium →\nPersonal Dashboard → Active Devices →\nAdd Device via QR Code")
2026-05-07 21:51:39 +03:00
wrapMode: Text.Wrap
}
2026-05-07 21:51:39 +03:00
Item {
Layout.fillWidth: true
2026-05-07 21:51:39 +03:00
Layout.preferredHeight: 24 + PageController.safeAreaBottomMargin
}
}
}
Connections {
target: PairingUiController
function onTvQrCodesChanged() {
2026-05-07 21:51:39 +03:00
if (PairingUiController.tvQrCodesCount > 0) {
scrollToBottomRetryTimer.retries = 0
scrollToBottomRetryTimer.start()
Qt.callLater(function() {
root.scrollPairingToBottom()
})
Qt.callLater(function() {
Qt.callLater(function() {
root.scrollPairingToBottom()
})
})
}
}
function onTvPairingConfigReceived() {
2026-05-07 21:51:39 +03:00
scrollToBottomRetryTimer.stop()
2026-05-08 08:37:18 +03:00
qrRotationTimer.stop()
2026-05-07 21:51:39 +03:00
qrImage.source = ""
PageController.showNotificationMessage(qsTr("Configuration received from gateway"))
2026-05-07 21:51:39 +03:00
Qt.callLater(function() {
PageController.closePage()
})
}
function onTvPairingConfigAlreadyAdded() {
scrollToBottomRetryTimer.stop()
qrRotationTimer.restart()
}
}
}