mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-08 14:33:23 +00:00
fixed iOS QRCodeReader
This commit is contained in:
@@ -33,6 +33,16 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
void execNetworkWaitLoop(QEventLoop &wait)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_IOS
|
||||||
|
// QEventLoop::ExcludeUserInputEvents is not supported on iOS (Qt warns; can break nested UI).
|
||||||
|
wait.exec();
|
||||||
|
#else
|
||||||
|
wait.exec(QEventLoop::ExcludeUserInputEvents);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
constexpr QLatin1String errorResponsePattern1("No active configuration found for");
|
constexpr QLatin1String errorResponsePattern1("No active configuration found for");
|
||||||
constexpr QLatin1String errorResponsePattern2("No non-revoked public key found for");
|
constexpr QLatin1String errorResponsePattern2("No non-revoked public key found for");
|
||||||
constexpr QLatin1String errorResponsePattern3("Account not found.");
|
constexpr QLatin1String errorResponsePattern3("Account not found.");
|
||||||
@@ -189,7 +199,7 @@ ErrorCode GatewayController::post(const QString &endpoint, const QJsonObject api
|
|||||||
|
|
||||||
QList<QSslError> sslErrors;
|
QList<QSslError> sslErrors;
|
||||||
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
||||||
wait.exec(QEventLoop::ExcludeUserInputEvents);
|
execNetworkWaitLoop(wait);
|
||||||
|
|
||||||
QByteArray encryptedResponseBody = reply->readAll();
|
QByteArray encryptedResponseBody = reply->readAll();
|
||||||
QString replyErrorString = reply->errorString();
|
QString replyErrorString = reply->errorString();
|
||||||
@@ -431,7 +441,7 @@ QStringList GatewayController::getProxyUrls(const QString &serviceType, const QS
|
|||||||
|
|
||||||
connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
||||||
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
||||||
wait.exec(QEventLoop::ExcludeUserInputEvents);
|
execNetworkWaitLoop(wait);
|
||||||
|
|
||||||
if (reply->error() == QNetworkReply::NetworkError::NoError) {
|
if (reply->error() == QNetworkReply::NetworkError::NoError) {
|
||||||
auto encryptedResponseBody = reply->readAll();
|
auto encryptedResponseBody = reply->readAll();
|
||||||
@@ -564,7 +574,7 @@ void GatewayController::bypassProxy(const QString &endpoint, const QString &serv
|
|||||||
|
|
||||||
QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
||||||
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
||||||
wait.exec(QEventLoop::ExcludeUserInputEvents);
|
execNetworkWaitLoop(wait);
|
||||||
|
|
||||||
auto result = replyProcessingFunction(reply, sslErrors);
|
auto result = replyProcessingFunction(reply, sslErrors);
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
@@ -586,7 +596,7 @@ void GatewayController::bypassProxy(const QString &endpoint, const QString &serv
|
|||||||
|
|
||||||
connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
||||||
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
||||||
wait.exec(QEventLoop::ExcludeUserInputEvents);
|
execNetworkWaitLoop(wait);
|
||||||
|
|
||||||
if (reply->error() == QNetworkReply::NetworkError::NoError) {
|
if (reply->error() == QNetworkReply::NetworkError::NoError) {
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|||||||
@@ -12,3 +12,4 @@ QRect QRCodeReader::cameraSize() {
|
|||||||
void QRCodeReader::startReading() {}
|
void QRCodeReader::startReading() {}
|
||||||
void QRCodeReader::stopReading() {}
|
void QRCodeReader::stopReading() {}
|
||||||
void QRCodeReader::setCameraSize(QRect) {}
|
void QRCodeReader::setCameraSize(QRect) {}
|
||||||
|
void QRCodeReader::notifyCodeRead(const QString &) {}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ public slots:
|
|||||||
void startReading();
|
void startReading();
|
||||||
void stopReading();
|
void stopReading();
|
||||||
void setCameraSize(QRect value);
|
void setCameraSize(QRect value);
|
||||||
|
/// Called from AVFoundation delegate on the main queue; emits codeReaded.
|
||||||
|
void notifyCodeRead(const QString &code);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void codeReaded(QString code);
|
void codeReaded(QString code);
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#if !MACOS_NE
|
#if !MACOS_NE
|
||||||
#include "QRCodeReaderBase.h"
|
#include "QRCodeReaderBase.h"
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
#import <AVFoundation/AVFoundation.h>
|
#import <AVFoundation/AVFoundation.h>
|
||||||
|
|
||||||
@@ -27,13 +30,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)startReading {
|
- (BOOL)startReading {
|
||||||
NSError *error;
|
[self stopReading];
|
||||||
|
|
||||||
|
NSError *error = nil;
|
||||||
|
|
||||||
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
|
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
|
||||||
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice: captureDevice error: &error];
|
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice: captureDevice error: &error];
|
||||||
|
|
||||||
if(!deviceInput) {
|
if (!deviceInput) {
|
||||||
NSLog(@"Error %@", error.localizedDescription);
|
NSLog(@"[QRCodeReader] deviceInput failed: %@", error.localizedDescription);
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,14 +71,21 @@
|
|||||||
|
|
||||||
[_captureSession startRunning];
|
[_captureSession startRunning];
|
||||||
|
|
||||||
|
NSLog(@"[QRCodeReader] startReading OK frame=(%.1f,%.1f,%.1f,%.1f) statusBar=%.1f",
|
||||||
|
cameraCGRect.origin.x, cameraCGRect.origin.y, cameraCGRect.size.width, cameraCGRect.size.height, statusBarHeight);
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)stopReading {
|
- (void)stopReading {
|
||||||
[_captureSession stopRunning];
|
if (_captureSession) {
|
||||||
_captureSession = nil;
|
[_captureSession stopRunning];
|
||||||
|
_captureSession = nil;
|
||||||
[_videoPreviewPlayer removeFromSuperlayer];
|
}
|
||||||
|
if (_videoPreviewPlayer) {
|
||||||
|
[_videoPreviewPlayer removeFromSuperlayer];
|
||||||
|
_videoPreviewPlayer = nil;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
|
- (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
|
||||||
@@ -82,7 +94,16 @@
|
|||||||
AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects objectAtIndex:0];
|
AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects objectAtIndex:0];
|
||||||
|
|
||||||
if ([[metadataObject type] isEqualToString: AVMetadataObjectTypeQRCode]) {
|
if ([[metadataObject type] isEqualToString: AVMetadataObjectTypeQRCode]) {
|
||||||
_qrCodeReader->emit codeReaded([metadataObject stringValue].UTF8String);
|
NSString *value = [metadataObject stringValue];
|
||||||
|
if (value.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSLog(@"[QRCodeReader] metadata QR len=%lu", static_cast<unsigned long>(value.length));
|
||||||
|
QRCodeReader *cpp = _qrCodeReader;
|
||||||
|
const QByteArray utf8([value UTF8String]);
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
cpp->notifyCodeRead(QString::fromUtf8(utf8));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,14 +121,23 @@ QRect QRCodeReader::cameraSize() {
|
|||||||
|
|
||||||
void QRCodeReader::setCameraSize(QRect value) {
|
void QRCodeReader::setCameraSize(QRect value) {
|
||||||
m_cameraSize = value;
|
m_cameraSize = value;
|
||||||
|
qInfo() << "[QRCodeReader] setCameraSize" << value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRCodeReader::startReading() {
|
void QRCodeReader::startReading() {
|
||||||
[m_qrCodeReader startReading];
|
const BOOL ok = [m_qrCodeReader startReading];
|
||||||
|
if (!ok) {
|
||||||
|
qWarning() << "[QRCodeReader] startReading failed (see NSLogs)";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRCodeReader::stopReading() {
|
void QRCodeReader::stopReading() {
|
||||||
[m_qrCodeReader stopReading];
|
[m_qrCodeReader stopReading];
|
||||||
|
qInfo() << "[QRCodeReader] stopReading";
|
||||||
|
}
|
||||||
|
|
||||||
|
void QRCodeReader::notifyCodeRead(const QString &code) {
|
||||||
|
emit codeReaded(code);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#include "QRCodeReaderBase.h"
|
#include "QRCodeReaderBase.h"
|
||||||
@@ -124,4 +154,5 @@ QRect QRCodeReader::cameraSize() {
|
|||||||
void QRCodeReader::startReading() {}
|
void QRCodeReader::startReading() {}
|
||||||
void QRCodeReader::stopReading() {}
|
void QRCodeReader::stopReading() {}
|
||||||
void QRCodeReader::setCameraSize(QRect) {}
|
void QRCodeReader::setCameraSize(QRect) {}
|
||||||
|
void QRCodeReader::notifyCodeRead(const QString &) {}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "pairingUiController.h"
|
#include "pairingUiController.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
@@ -82,6 +83,7 @@ void PairingUiController::setTvPairingUiPhase(int phase)
|
|||||||
void PairingUiController::openPairingQrScanner()
|
void PairingUiController::openPairingQrScanner()
|
||||||
{
|
{
|
||||||
#if defined(Q_OS_ANDROID)
|
#if defined(Q_OS_ANDROID)
|
||||||
|
qInfo() << "[PairingUi] openPairingQrScanner (Android native activity)";
|
||||||
AndroidController::instance()->startQrReaderActivity();
|
AndroidController::instance()->startQrReaderActivity();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -89,16 +91,20 @@ void PairingUiController::openPairingQrScanner()
|
|||||||
bool PairingUiController::applyScannedTextAsPairingUuid(const QString &raw)
|
bool PairingUiController::applyScannedTextAsPairingUuid(const QString &raw)
|
||||||
{
|
{
|
||||||
const QString t = raw.trimmed();
|
const QString t = raw.trimmed();
|
||||||
|
qInfo() << "[PairingUi] scan raw len=" << t.size();
|
||||||
if (t.startsWith(QStringLiteral("vpn://"), Qt::CaseInsensitive)) {
|
if (t.startsWith(QStringLiteral("vpn://"), Qt::CaseInsensitive)) {
|
||||||
|
qInfo() << "[PairingUi] scan rejected: looks like vpn:// bundle, not session UUID";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static const QRegularExpression re(QStringLiteral(
|
static const QRegularExpression re(QStringLiteral(
|
||||||
"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}"));
|
"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}"));
|
||||||
const QRegularExpressionMatch m = re.match(t);
|
const QRegularExpressionMatch m = re.match(t);
|
||||||
if (!m.hasMatch()) {
|
if (!m.hasMatch()) {
|
||||||
|
qInfo() << "[PairingUi] scan rejected: no UUID v4 pattern in payload";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const QString uuid = m.captured(0);
|
const QString uuid = m.captured(0);
|
||||||
|
qInfo() << "[PairingUi] scan accepted uuid=" << uuid.left(13) << "...";
|
||||||
emit pairingUuidFromScan(uuid);
|
emit pairingUuidFromScan(uuid);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -367,24 +373,29 @@ void PairingUiController::submitPhonePairing(const QString &qrUuid, int serverIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
const QString trimmedUuid = qrUuid.trimmed();
|
const QString trimmedUuid = qrUuid.trimmed();
|
||||||
|
qInfo() << "[PairingUi] submitPhonePairing serverIndex=" << serverIndex << "uuidLen=" << trimmedUuid.size();
|
||||||
if (trimmedUuid.isEmpty()) {
|
if (trimmedUuid.isEmpty()) {
|
||||||
|
qWarning() << "[PairingUi] submitPhonePairing aborted: empty UUID (paste or scan first)";
|
||||||
emit errorOccurred(ErrorCode::ApiConfigEmptyError);
|
emit errorOccurred(ErrorCode::ApiConfigEmptyError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serverIndex < 0 || serverIndex >= m_serversController->getServersCount()) {
|
if (serverIndex < 0 || serverIndex >= m_serversController->getServersCount()) {
|
||||||
|
qWarning() << "[PairingUi] submitPhonePairing invalid serverIndex";
|
||||||
emit errorOccurred(ErrorCode::InternalError);
|
emit errorOccurred(ErrorCode::InternalError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ServerConfig serverConfig = m_serversController->getServerConfig(serverIndex);
|
const ServerConfig serverConfig = m_serversController->getServerConfig(serverIndex);
|
||||||
if (!serverConfig.isApiV2()) {
|
if (!serverConfig.isApiV2()) {
|
||||||
|
qWarning() << "[PairingUi] submitPhonePairing server is not API v2";
|
||||||
emit errorOccurred(ErrorCode::InternalError);
|
emit errorOccurred(ErrorCode::InternalError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ApiV2ServerConfig *apiV2 = serverConfig.as<ApiV2ServerConfig>();
|
const ApiV2ServerConfig *apiV2 = serverConfig.as<ApiV2ServerConfig>();
|
||||||
if (!apiV2) {
|
if (!apiV2) {
|
||||||
|
qWarning() << "[PairingUi] submitPhonePairing cast to ApiV2ServerConfig failed";
|
||||||
emit errorOccurred(ErrorCode::InternalError);
|
emit errorOccurred(ErrorCode::InternalError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -392,6 +403,7 @@ void PairingUiController::submitPhonePairing(const QString &qrUuid, int serverIn
|
|||||||
QString vpnKey;
|
QString vpnKey;
|
||||||
const ErrorCode keyErr = m_subscriptionController->prepareVpnKeyExport(serverIndex, vpnKey);
|
const ErrorCode keyErr = m_subscriptionController->prepareVpnKeyExport(serverIndex, vpnKey);
|
||||||
if (keyErr != ErrorCode::NoError) {
|
if (keyErr != ErrorCode::NoError) {
|
||||||
|
qWarning() << "[PairingUi] prepareVpnKeyExport failed" << static_cast<int>(keyErr);
|
||||||
emit errorOccurred(keyErr);
|
emit errorOccurred(keyErr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -400,6 +412,7 @@ void PairingUiController::submitPhonePairing(const QString &qrUuid, int serverIn
|
|||||||
const QJsonArray supportedProtocols = apiV2->apiConfig.supportedProtocols;
|
const QJsonArray supportedProtocols = apiV2->apiConfig.supportedProtocols;
|
||||||
const QString apiKey = apiV2->authData.apiKey;
|
const QString apiKey = apiV2->authData.apiKey;
|
||||||
if (apiKey.isEmpty()) {
|
if (apiKey.isEmpty()) {
|
||||||
|
qWarning() << "[PairingUi] submitPhonePairing aborted: empty API key on server card";
|
||||||
emit errorOccurred(ErrorCode::ApiConfigEmptyError);
|
emit errorOccurred(ErrorCode::ApiConfigEmptyError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -435,7 +435,11 @@ bool SubscriptionUiController::getAccountInfo(int serverIndex, bool reload)
|
|||||||
if (reload) {
|
if (reload) {
|
||||||
QEventLoop wait;
|
QEventLoop wait;
|
||||||
QTimer::singleShot(1000, &wait, &QEventLoop::quit);
|
QTimer::singleShot(1000, &wait, &QEventLoop::quit);
|
||||||
|
#ifdef Q_OS_IOS
|
||||||
|
wait.exec();
|
||||||
|
#else
|
||||||
wait.exec(QEventLoop::ExcludeUserInputEvents);
|
wait.exec(QEventLoop::ExcludeUserInputEvents);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
QJsonObject accountInfo;
|
QJsonObject accountInfo;
|
||||||
ErrorCode errorCode = m_subscriptionController->getAccountInfo(serverIndex, accountInfo);
|
ErrorCode errorCode = m_subscriptionController->getAccountInfo(serverIndex, accountInfo);
|
||||||
|
|||||||
@@ -16,10 +16,34 @@ PageType {
|
|||||||
property int qrImageIndex: 0
|
property int qrImageIndex: 0
|
||||||
property bool pairingCameraOpen: false
|
property bool pairingCameraOpen: false
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: pairingCameraKickTimer
|
||||||
|
interval: 180
|
||||||
|
repeat: false
|
||||||
|
onTriggered: root.restartPairingIosCamera()
|
||||||
|
}
|
||||||
|
|
||||||
|
function restartPairingIosCamera() {
|
||||||
|
if (Qt.platform.os !== "ios" || !root.pairingCameraOpen) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (cameraSlot.width < 32 || cameraSlot.height < 32) {
|
||||||
|
console.info("[PairingQr] cameraSlot too small wxh=", cameraSlot.width, cameraSlot.height, "retry")
|
||||||
|
pairingCameraKickTimer.restart()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var p = cameraSlot.mapToItem(root, 0, 0)
|
||||||
|
console.info("[PairingQr] start preview frame", p.x, p.y, cameraSlot.width, cameraSlot.height)
|
||||||
|
pairingQrReader.stopReading()
|
||||||
|
pairingQrReader.setCameraSize(Qt.rect(Math.round(p.x), Math.round(p.y), Math.round(cameraSlot.width), Math.round(cameraSlot.height)))
|
||||||
|
pairingQrReader.startReading()
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: root
|
target: root
|
||||||
function onVisibleChanged() {
|
function onVisibleChanged() {
|
||||||
if (!root.visible) {
|
if (!root.visible) {
|
||||||
|
pairingCameraKickTimer.stop()
|
||||||
pairingQrReader.stopReading()
|
pairingQrReader.stopReading()
|
||||||
root.pairingCameraOpen = false
|
root.pairingCameraOpen = false
|
||||||
PairingUiController.cancelAllPairingActivity()
|
PairingUiController.cancelAllPairingActivity()
|
||||||
@@ -27,6 +51,31 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root
|
||||||
|
function onPairingCameraOpenChanged() {
|
||||||
|
if (!root.pairingCameraOpen) {
|
||||||
|
pairingCameraKickTimer.stop()
|
||||||
|
pairingQrReader.stopReading()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (Qt.platform.os === "ios") {
|
||||||
|
pairingCameraKickTimer.restart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: cameraSlot
|
||||||
|
enabled: Qt.platform.os === "ios" && root.pairingCameraOpen
|
||||||
|
function onWidthChanged() {
|
||||||
|
pairingCameraKickTimer.restart()
|
||||||
|
}
|
||||||
|
function onHeightChanged() {
|
||||||
|
pairingCameraKickTimer.restart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FlickableType {
|
FlickableType {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
contentHeight: layout.implicitHeight
|
contentHeight: layout.implicitHeight
|
||||||
@@ -189,6 +238,7 @@ PageType {
|
|||||||
|
|
||||||
QRCodeReader {
|
QRCodeReader {
|
||||||
id: pairingQrReader
|
id: pairingQrReader
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
onCodeReaded: function(code) {
|
onCodeReaded: function(code) {
|
||||||
if (PairingUiController.applyScannedTextAsPairingUuid(code)) {
|
if (PairingUiController.applyScannedTextAsPairingUuid(code)) {
|
||||||
@@ -205,11 +255,7 @@ PageType {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (Qt.platform.os === "ios") {
|
if (Qt.platform.os === "ios") {
|
||||||
Qt.callLater(function() {
|
pairingCameraKickTimer.restart()
|
||||||
var p = cameraSlot.mapToItem(root, 0, 0)
|
|
||||||
pairingQrReader.setCameraSize(Qt.rect(p.x, p.y, cameraSlot.width, cameraSlot.height))
|
|
||||||
pairingQrReader.startReading()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,34 @@ PageType {
|
|||||||
|
|
||||||
property bool pairingCameraOpen: false
|
property bool pairingCameraOpen: false
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: pairingCameraKickTimer
|
||||||
|
interval: 180
|
||||||
|
repeat: false
|
||||||
|
onTriggered: root.restartPairingIosCamera()
|
||||||
|
}
|
||||||
|
|
||||||
|
function restartPairingIosCamera() {
|
||||||
|
if (Qt.platform.os !== "ios" || !root.pairingCameraOpen) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (cameraSlot.width < 32 || cameraSlot.height < 32) {
|
||||||
|
console.info("[PairingQr] cameraSlot too small wxh=", cameraSlot.width, cameraSlot.height, "retry")
|
||||||
|
pairingCameraKickTimer.restart()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var p = cameraSlot.mapToItem(root, 0, 0)
|
||||||
|
console.info("[PairingQr] start preview frame", p.x, p.y, cameraSlot.width, cameraSlot.height)
|
||||||
|
pairingQrReader.stopReading()
|
||||||
|
pairingQrReader.setCameraSize(Qt.rect(Math.round(p.x), Math.round(p.y), Math.round(cameraSlot.width), Math.round(cameraSlot.height)))
|
||||||
|
pairingQrReader.startReading()
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: root
|
target: root
|
||||||
function onVisibleChanged() {
|
function onVisibleChanged() {
|
||||||
if (!root.visible) {
|
if (!root.visible) {
|
||||||
|
pairingCameraKickTimer.stop()
|
||||||
pairingQrReader.stopReading()
|
pairingQrReader.stopReading()
|
||||||
root.pairingCameraOpen = false
|
root.pairingCameraOpen = false
|
||||||
PairingUiController.cancelAllPairingActivity()
|
PairingUiController.cancelAllPairingActivity()
|
||||||
@@ -26,6 +50,31 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root
|
||||||
|
function onPairingCameraOpenChanged() {
|
||||||
|
if (!root.pairingCameraOpen) {
|
||||||
|
pairingCameraKickTimer.stop()
|
||||||
|
pairingQrReader.stopReading()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (Qt.platform.os === "ios") {
|
||||||
|
pairingCameraKickTimer.restart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: cameraSlot
|
||||||
|
enabled: Qt.platform.os === "ios" && root.pairingCameraOpen
|
||||||
|
function onWidthChanged() {
|
||||||
|
pairingCameraKickTimer.restart()
|
||||||
|
}
|
||||||
|
function onHeightChanged() {
|
||||||
|
pairingCameraKickTimer.restart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FlickableType {
|
FlickableType {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
contentHeight: layout.implicitHeight
|
contentHeight: layout.implicitHeight
|
||||||
@@ -111,6 +160,7 @@ PageType {
|
|||||||
|
|
||||||
QRCodeReader {
|
QRCodeReader {
|
||||||
id: pairingQrReader
|
id: pairingQrReader
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
onCodeReaded: function(code) {
|
onCodeReaded: function(code) {
|
||||||
if (PairingUiController.applyScannedTextAsPairingUuid(code)) {
|
if (PairingUiController.applyScannedTextAsPairingUuid(code)) {
|
||||||
@@ -127,11 +177,7 @@ PageType {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (Qt.platform.os === "ios") {
|
if (Qt.platform.os === "ios") {
|
||||||
Qt.callLater(function() {
|
pairingCameraKickTimer.restart()
|
||||||
var p = cameraSlot.mapToItem(root, 0, 0)
|
|
||||||
pairingQrReader.setCameraSize(Qt.rect(p.x, p.y, cameraSlot.width, cameraSlot.height))
|
|
||||||
pairingQrReader.startReading()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user