enabled delete account again

This commit is contained in:
Michael Zanetti 2018-09-05 17:33:56 +02:00
parent 303527b75b
commit 59cb232744
10 changed files with 145 additions and 55 deletions

View File

@ -74,9 +74,23 @@ AWSClient::AWSClient(QObject *parent) : QObject(parent),
config.apiEndpoint = "testapi-cloud.guh.io"; config.apiEndpoint = "testapi-cloud.guh.io";
m_configs.append(config); m_configs.append(config);
// Marantec environment
config.clientId = "7rf6da8pcqi1qi8tp1evf933h2";
config.poolId = "eu-west-1_d4DdcqKJ8";
config.identityPoolId = "eu-west-1:d32f6d94-caae-4f08-a193-f9fba8652646";
// Generating certificates is not supported for the Marantec environment
config.certificateEndpoint = "";
config.certificateApiKey = "";
config.certificateVendorId = "";
config.mqttEndpoint = "a27q7a2x15m8h3.iot.eu-west-1.amazonaws.com";
config.region = "eu-west-1";
config.apiEndpoint = "api-cloud.guh.io";
m_configs.append(config);
QSettings settings; QSettings settings;
settings.beginGroup("cloud"); settings.beginGroup("cloud");
m_username = settings.value("username").toString(); m_username = settings.value("username").toString();
m_userId = settings.value("userId").toString();
m_password = settings.value("password").toString(); m_password = settings.value("password").toString();
m_accessToken = settings.value("accessToken").toByteArray(); m_accessToken = settings.value("accessToken").toByteArray();
m_accessTokenExpiry = settings.value("accessTokenExpiry").toDateTime(); m_accessTokenExpiry = settings.value("accessTokenExpiry").toDateTime();
@ -94,7 +108,7 @@ AWSClient::AWSClient(QObject *parent) : QObject(parent),
bool AWSClient::isLoggedIn() const bool AWSClient::isLoggedIn() const
{ {
return !m_username.isEmpty() && !m_password.isEmpty(); return !m_userId.isEmpty() && !m_username.isEmpty() && !m_password.isEmpty();
} }
QString AWSClient::username() const QString AWSClient::username() const
@ -181,18 +195,30 @@ void AWSClient::login(const QString &username, const QString &password)
m_idToken = authenticationResult.value("IdToken").toByteArray(); m_idToken = authenticationResult.value("IdToken").toByteArray();
m_refreshToken = authenticationResult.value("RefreshToken").toByteArray(); m_refreshToken = authenticationResult.value("RefreshToken").toByteArray();
qDebug() << "AWS ID token" << m_idToken;
QList<QByteArray> jwtParts = m_idToken.split('.');
if (jwtParts.count() != 3) {
qWarning() << "JWT token doesn't have 3 parts";
return;
}
// qDebug() << "decoded header:" << QByteArray::fromBase64(jwtParts.at(0));
// qDebug() << "decoded payload:" << QByteArray::fromBase64(jwtParts.at(1));
QJsonDocument tokenPayloadJsonDoc = QJsonDocument::fromJson(QByteArray::fromBase64(jwtParts.at(1)));
m_userId = tokenPayloadJsonDoc.toVariant().toMap().value("cognito:username").toByteArray();
QSettings settings; QSettings settings;
settings.remove("cloud"); settings.remove("cloud");
settings.beginGroup("cloud"); settings.beginGroup("cloud");
settings.setValue("username", m_username); settings.setValue("username", m_username);
settings.setValue("userId", m_userId);
settings.setValue("password", m_password); settings.setValue("password", m_password);
settings.setValue("accessToken", m_accessToken); settings.setValue("accessToken", m_accessToken);
settings.setValue("accessTokenExpiry", m_accessTokenExpiry); settings.setValue("accessTokenExpiry", m_accessTokenExpiry);
settings.setValue("idToken", m_idToken); settings.setValue("idToken", m_idToken);
settings.setValue("refreshToken", m_refreshToken); settings.setValue("refreshToken", m_refreshToken);
qDebug() << "AWS login successful";// << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented)); qDebug() << "AWS login successful. Userid:" << m_userId;// << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented));
emit isLoggedInChanged(); emit isLoggedInChanged();
qDebug() << "Getting cognito ID"; qDebug() << "Getting cognito ID";
@ -202,8 +228,10 @@ void AWSClient::login(const QString &username, const QString &password)
void AWSClient::logout() void AWSClient::logout()
{ {
m_userId.clear();
m_username.clear(); m_username.clear();
m_password.clear(); m_password.clear();
m_devices->clear();
QSettings settings; QSettings settings;
settings.remove("cloud"); settings.remove("cloud");
emit isLoggedInChanged(); emit isLoggedInChanged();
@ -441,7 +469,7 @@ void AWSClient::deleteAccount()
} }
qDebug() << "Deleting account"; qDebug() << "Deleting account";
QUrl url(QString("https://%1/users/profiles/%2").arg(m_configs.at(m_usedConfigIndex).apiEndpoint).arg(m_username)); QUrl url(QString("https://%1/users/profiles/%2").arg(m_configs.at(m_usedConfigIndex).apiEndpoint).arg(m_userId));
QNetworkRequest request(url); QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("x-api-idToken", m_idToken); request.setRawHeader("x-api-idToken", m_idToken);
@ -458,14 +486,17 @@ void AWSClient::deleteAccount()
QByteArray data = reply->readAll(); QByteArray data = reply->readAll();
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
qWarning() << "Error deleting cloud user account:" << reply->error() << reply->errorString() << qUtf8Printable(data); qWarning() << "Error deleting cloud user account:" << reply->error() << reply->errorString() << qUtf8Printable(data);
emit deleteAccountResult(LoginErrorUnknownError);
return; return;
} }
QJsonParseError error; QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError) { if (error.error != QJsonParseError::NoError) {
qWarning() << "Failed to parse JSON from server" << error.errorString() << qUtf8Printable(data); qWarning() << "Failed to parse JSON from server" << error.errorString() << qUtf8Printable(data);
emit deleteAccountResult(LoginErrorUnknownError);
return; return;
} }
emit deleteAccountResult(LoginErrorNoError);
logout(); logout();
qDebug() << "Account deleted" << data; qDebug() << "Account deleted" << data;
}); });
@ -489,9 +520,11 @@ void AWSClient::unpairDevice(const QString &boxId)
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("x-api-idToken", m_idToken); request.setRawHeader("x-api-idToken", m_idToken);
m_devices->setBusy(true);
QNetworkReply *reply = m_nam->deleteResource(request); QNetworkReply *reply = m_nam->deleteResource(request);
connect(reply, &QNetworkReply::finished, this, [this, reply, boxId]() { connect(reply, &QNetworkReply::finished, this, [this, reply, boxId]() {
reply->deleteLater(); reply->deleteLater();
m_devices->setBusy(false);
QByteArray data = reply->readAll(); QByteArray data = reply->readAll();
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
qWarning() << "Error unpairing cloud device:" << reply->error() << reply->errorString() << qUtf8Printable(data); qWarning() << "Error unpairing cloud device:" << reply->error() << reply->errorString() << qUtf8Printable(data);
@ -787,9 +820,11 @@ void AWSClient::fetchDevices()
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("x-api-idToken", m_idToken); request.setRawHeader("x-api-idToken", m_idToken);
m_devices->setBusy(true);
QNetworkReply *reply = m_nam->get(request); QNetworkReply *reply = m_nam->get(request);
connect(reply, &QNetworkReply::finished, this, [this, reply]() { connect(reply, &QNetworkReply::finished, this, [this, reply]() {
reply->deleteLater(); reply->deleteLater();
m_devices->setBusy(false);
QByteArray data = reply->readAll(); QByteArray data = reply->readAll();
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
qWarning() << "Error fetching cloud devices:" << reply->error() << reply->errorString() << qUtf8Printable(data); qWarning() << "Error fetching cloud devices:" << reply->error() << reply->errorString() << qUtf8Printable(data);
@ -931,6 +966,19 @@ QHash<int, QByteArray> AWSDevices::roleNames() const
return roles; return roles;
} }
bool AWSDevices::busy() const
{
return m_busy;
}
void AWSDevices::setBusy(bool busy)
{
if (m_busy != busy) {
m_busy = busy;
emit busyChanged();
}
}
AWSDevice *AWSDevices::getDevice(const QString &uuid) const AWSDevice *AWSDevices::getDevice(const QString &uuid) const
{ {
for (int i = 0; i < m_list.count(); i++) { for (int i = 0; i < m_list.count(); i++) {
@ -977,6 +1025,16 @@ void AWSDevices::remove(const QString &uuid)
emit countChanged(); emit countChanged();
} }
void AWSDevices::clear()
{
beginResetModel();
while (m_list.count() > 0) {
m_list.takeFirst()->deleteLater();
}
endResetModel();
emit countChanged();
}
AWSDevice::AWSDevice(const QString &id, const QString &name, bool online, QObject *parent): AWSDevice::AWSDevice(const QString &id, const QString &name, bool online, QObject *parent):
QObject (parent), QObject (parent),
m_id(id), m_id(id),

View File

@ -33,6 +33,7 @@ private:
class AWSDevices: public QAbstractListModel { class AWSDevices: public QAbstractListModel {
Q_OBJECT Q_OBJECT
Q_PROPERTY(int count READ rowCount NOTIFY countChanged) Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
public: public:
enum Roles { enum Roles {
RoleName, RoleName,
@ -43,14 +44,19 @@ public:
int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;
bool busy() const;
void setBusy(bool busy);
Q_INVOKABLE AWSDevice* getDevice(const QString &uuid) const; Q_INVOKABLE AWSDevice* getDevice(const QString &uuid) const;
Q_INVOKABLE AWSDevice* get(int index) const; Q_INVOKABLE AWSDevice* get(int index) const;
void insert(AWSDevice *device); void insert(AWSDevice *device);
void remove(const QString &uuid); void remove(const QString &uuid);
void clear();
signals: signals:
void countChanged(); void countChanged();
void busyChanged();
private: private:
QList<AWSDevice*> m_list; QList<AWSDevice*> m_list;
bool m_busy = false;
}; };
class AWSConfiguration { class AWSConfiguration {
@ -127,6 +133,7 @@ signals:
void confirmationResult(LoginError error); void confirmationResult(LoginError error);
void forgotPasswordResult(LoginError error); void forgotPasswordResult(LoginError error);
void confirmForgotPasswordResult(LoginError error); void confirmForgotPasswordResult(LoginError error);
void deleteAccountResult(LoginError error);
void isLoggedInChanged(); void isLoggedInChanged();
void confirmationPendingChanged(); void confirmationPendingChanged();

View File

@ -127,14 +127,14 @@ Engine::Engine(QObject *parent) :
connect(m_aws, &AWSClient::devicesFetched, this, [this]() { connect(m_aws, &AWSClient::devicesFetched, this, [this]() {
if (m_jsonRpcClient->connected() && m_jsonRpcClient->cloudConnectionState() == JsonRpcClient::CloudConnectionStateConnected) { if (m_jsonRpcClient->connected() && m_jsonRpcClient->cloudConnectionState() == JsonRpcClient::CloudConnectionStateConnected) {
if (m_aws->awsDevices()->getDevice(m_jsonRpcClient->serverUuid()) == nullptr) { if (m_aws->awsDevices()->getDevice(m_jsonRpcClient->serverUuid()) == nullptr) {
m_jsonRpcClient->setupRemoteAccess(m_aws->idToken(), m_aws->cognitoIdentityId()); m_jsonRpcClient->setupRemoteAccess(m_aws->idToken(), m_aws->userId());
} }
} }
}); });
connect(m_jsonRpcClient, &JsonRpcClient::connectedChanged, this, [this]() { connect(m_jsonRpcClient, &JsonRpcClient::connectedChanged, this, [this]() {
if (m_jsonRpcClient->connected() && m_jsonRpcClient->cloudConnectionState() == JsonRpcClient::CloudConnectionStateConnected) { if (m_jsonRpcClient->connected() && m_jsonRpcClient->cloudConnectionState() == JsonRpcClient::CloudConnectionStateConnected) {
if (m_aws->awsDevices()->getDevice(m_jsonRpcClient->serverUuid()) == nullptr) { if (m_aws->awsDevices()->getDevice(m_jsonRpcClient->serverUuid()) == nullptr) {
m_jsonRpcClient->setupRemoteAccess(m_aws->idToken(), m_aws->cognitoIdentityId()); m_jsonRpcClient->setupRemoteAccess(m_aws->idToken(), m_aws->userId());
} }
} }
}); });

View File

@ -96,7 +96,7 @@ void JsonRpcClient::setNotificationsEnabledResponse(const QVariantMap &params)
void JsonRpcClient::notificationReceived(const QVariantMap &data) void JsonRpcClient::notificationReceived(const QVariantMap &data)
{ {
//JsonRpcClient: Notification received QMap(("id", QVariant(double, 2))("notification", QVariant(QString, "JSONRPC.PushButtonAuthFinished"))("params", QVariant(QVariantMap, QMap(("success", QVariant(bool, true))("token", QVariant(QString, "FJPaAJ8FEtrqcC+/s0s/lAcDubz0OyEtwbRsyFIWM9c="))("transactionId", QVariant(double, 2)))))) qDebug() << "Notification received:" << data;
if (data.value("notification").toString() == "JSONRPC.PushButtonAuthFinished") { if (data.value("notification").toString() == "JSONRPC.PushButtonAuthFinished") {
qDebug() << "Push button auth finished."; qDebug() << "Push button auth finished.";
if (data.value("params").toMap().value("transactionId").toInt() != m_pendingPushButtonTransaction) { if (data.value("params").toMap().value("transactionId").toInt() != m_pendingPushButtonTransaction) {

View File

@ -18,7 +18,7 @@ Page {
ListElement { iconSource: "../images/share.svg"; text: qsTr("Configure things"); page: "EditDevicesPage.qml" } ListElement { iconSource: "../images/share.svg"; text: qsTr("Configure things"); page: "EditDevicesPage.qml" }
ListElement { iconSource: "../images/magic.svg"; text: qsTr("Magic"); page: "MagicPage.qml" } ListElement { iconSource: "../images/magic.svg"; text: qsTr("Magic"); page: "MagicPage.qml" }
ListElement { iconSource: "../images/stock_application.svg"; text: qsTr("App settings"); page: "appsettings/AppSettingsPage.qml" } ListElement { iconSource: "../images/stock_application.svg"; text: qsTr("App settings"); page: "appsettings/AppSettingsPage.qml" }
ListElement { iconSource: "../images/settings.svg"; text: qsTr("System settings"); page: "SettingsPage.qml" } ListElement { iconSource: "../images/settings.svg"; text: qsTr("Box settings"); page: "SettingsPage.qml" }
} }
onClicked: { onClicked: {
@ -173,39 +173,38 @@ Page {
} }
} }
TabBar { }
id: tabBar footer: TabBar {
Layout.fillWidth: true id: tabBar
Material.elevation: 3 Material.elevation: 3
currentIndex: settings.currentMainViewIndex currentIndex: settings.currentMainViewIndex
position: TabBar.Footer position: TabBar.Footer
Layout.preferredHeight: 70 + (app.landscape ? implicitHeight: 70 + (app.landscape ?
((systemProductType === "ios" && Screen.height === 375) ? -10 : -20) : ((systemProductType === "ios" && Screen.height === 375) ? -10 : -20) :
(systemProductType === "ios" && Screen.height === 812) ? 14 : 0) (systemProductType === "ios" && Screen.height === 812) ? 14 : 0)
// FIXME: All this can go away when we require Controls 2.3 (Qt 5.10) or greater as TabBar got a major rework there. // FIXME: All this can go away when we require Controls 2.3 (Qt 5.10) or greater as TabBar got a major rework there.
// Ideally we'd just list the 3 items and set visible to false if the server version isn't good enough but TabBar // Ideally we'd just list the 3 items and set visible to false if the server version isn't good enough but TabBar
// has troubles dealing with that. For now, let's manually fill it and use a timer to initialize the currentIndex. // has troubles dealing with that. For now, let's manually fill it and use a timer to initialize the currentIndex.
Component.onCompleted: { Component.onCompleted: {
var pi = 0; var pi = 0;
if (Engine.jsonRpcClient.ensureServerVersion(1.6)) { if (Engine.jsonRpcClient.ensureServerVersion(1.6)) {
tabEntryComponent.createObject(tabBar, {text: qsTr("Favorites"), iconSource: "../images/starred.svg", pageIndex: pi++}) tabEntryComponent.createObject(tabBar, {text: qsTr("Favorites"), iconSource: "../images/starred.svg", pageIndex: pi++})
}
tabEntryComponent.createObject(tabBar, {text: qsTr("Things"), iconSource: "../images/share.svg", pageIndex: pi++})
tabEntryComponent.createObject(tabBar, {text: qsTr("Scenes"), iconSource: "../images/slideshow.svg", pageIndex: pi++})
initTimer.start()
} }
Timer { id: initTimer; interval: 1; repeat: false; onTriggered: tabBar.currentIndex = Qt.binding(function() {return settings.currentMainViewIndex;})} tabEntryComponent.createObject(tabBar, {text: qsTr("Things"), iconSource: "../images/share.svg", pageIndex: pi++})
tabEntryComponent.createObject(tabBar, {text: qsTr("Scenes"), iconSource: "../images/slideshow.svg", pageIndex: pi++})
initTimer.start()
}
Timer { id: initTimer; interval: 1; repeat: false; onTriggered: tabBar.currentIndex = Qt.binding(function() {return settings.currentMainViewIndex;})}
Component { Component {
id: tabEntryComponent id: tabEntryComponent
MainPageTabButton { MainPageTabButton {
property int pageIndex: 0 property int pageIndex: 0
// height: tabBar.height // height: tabBar.height
onClicked: settings.currentMainViewIndex = pageIndex onClicked: settings.currentMainViewIndex = pageIndex
alignment: app.landscape ? Qt.Horizontal : Qt.Vertical alignment: app.landscape ? Qt.Horizontal : Qt.Vertical
}
} }
} }
} }

View File

@ -8,7 +8,7 @@ import "components"
Page { Page {
id: root id: root
header: GuhHeader { header: GuhHeader {
text: qsTr("System settings") text: qsTr("Box settings")
backButtonVisible: true backButtonVisible: true
onBackPressed: pageStack.pop() onBackPressed: pageStack.pop()
} }

View File

@ -124,7 +124,7 @@ Page {
} }
MeaListItemDelegate { MeaListItemDelegate {
Layout.fillWidth: true Layout.fillWidth: true
visible: settings.showHiddenOption visible: settings.showHiddenOptions
text: qsTr("Developer options") text: qsTr("Developer options")
iconName: "../images/configure.svg" iconName: "../images/configure.svg"
onClicked: pageStack.push(Qt.resolvedUrl("DeveloperOptionsPage.qml")) onClicked: pageStack.push(Qt.resolvedUrl("DeveloperOptionsPage.qml"))

View File

@ -25,10 +25,20 @@ Page {
Engine.awsClient.fetchDevices(); Engine.awsClient.fetchDevices();
} }
} }
onDeleteAccountResult: {
busyOverlay.shown = false;
if (error !== AWSClient.LoginErrorNoError) {
var errorDialog = Qt.createComponent(Qt.resolvedUrl("../components/ErrorDialog.qml"));
var text = qsTr("Sorry, an error happened removing the account. Please try again later.");
var popup = errorDialog.createObject(app, {text: text})
popup.open()
return;
}
}
} }
ColumnLayout { ColumnLayout {
anchors { left: parent.left; top: parent.top; right: parent.right } anchors.fill: parent
visible: Engine.awsClient.isLoggedIn visible: Engine.awsClient.isLoggedIn
Label { Label {
Layout.fillWidth: true Layout.fillWidth: true
@ -64,6 +74,7 @@ Page {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
model: Engine.awsClient.awsDevices model: Engine.awsClient.awsDevices
clip: true
delegate: MeaListItemDelegate { delegate: MeaListItemDelegate {
width: parent.width width: parent.width
text: model.name text: model.name
@ -77,6 +88,11 @@ Page {
Engine.awsClient.unpairDevice(model.id); Engine.awsClient.unpairDevice(model.id);
} }
} }
BusyIndicator {
anchors.centerIn: parent
visible: Engine.awsClient.awsDevices.busy
}
} }
} }
@ -84,28 +100,29 @@ Page {
id: logoutDialog id: logoutDialog
title: qsTr("Goodbye") title: qsTr("Goodbye")
// Deleting user profile not working in cloud yet // Deleting user profile not working in cloud yet
// text: qsTr("Sorry to see you go. If you log out you won't be able to connect to %1 boxes remotely any more. However, you can come back any time, we'll keep your user account. If you whish to completely delete your account and all the data associated with it, check the box below before hitting ok.").arg(app.systemName) text: qsTr("Sorry to see you go. If you log out you won't be able to connect to %1 boxes remotely any more. However, you can come back any time, we'll keep your user account. If you whish to completely delete your account and all the data associated with it, check the box below before hitting ok.").arg(app.systemName)
text: qsTr("Sorry to see you go. If you log out you won't be able to connect to %1 boxes remotely any more. However, you can come back any time.").arg(app.systemName) // text: qsTr("Sorry to see you go. If you log out you won't be able to connect to %1 boxes remotely any more. However, you can come back any time.").arg(app.systemName)
headerIcon: "../images/dialog-warning-symbolic.svg" headerIcon: "../images/dialog-warning-symbolic.svg"
standardButtons: Dialog.Cancel | Dialog.Ok standardButtons: Dialog.Cancel | Dialog.Ok
// RowLayout { RowLayout {
// CheckBox { CheckBox {
// id: deleteCheckbox id: deleteCheckbox
// } }
// Label { Label {
// Layout.fillWidth: true Layout.fillWidth: true
// wrapMode: Text.WordWrap wrapMode: Text.WordWrap
// text: qsTr("Delete my account") text: qsTr("Delete my account")
// } }
// } }
onAccepted: { onAccepted: {
// if (deleteCheckbox.checked) { if (deleteCheckbox.checked) {
// Engine.awsClient.deleteAccount() busyOverlay.shown = true;
// } else { Engine.awsClient.deleteAccount()
} else {
Engine.awsClient.logout() Engine.awsClient.logout()
// } }
} }
} }

View File

@ -25,7 +25,7 @@ Page {
ComboBox { ComboBox {
currentIndex: app.settings.cloudEnvironment currentIndex: app.settings.cloudEnvironment
model: [qsTr("Community"), qsTr("Testing")] model: [qsTr("Community"), qsTr("Testing"), qsTr("Marantec")]
onActivated: { onActivated: {
app.settings.cloudEnvironment = index; app.settings.cloudEnvironment = index;
} }

View File

@ -18,8 +18,12 @@ Page {
Connections { Connections {
target: Engine.jsonRpcClient target: Engine.jsonRpcClient
onCloudConnectionStateChanged: { onCloudConnectionStateChanged: {
print("cloud connection state changed", Engine.jsonRpcClient.cloudConnectionState)
if (Engine.jsonRpcClient.cloudConnectionState == JsonRpcClient.CloudConnectionStateConnected) { if (Engine.jsonRpcClient.cloudConnectionState == JsonRpcClient.CloudConnectionStateConnected) {
d.deploymentStarted = false; d.deploymentStarted = false;
if (Engine.awsClient.awsDevices.getDevice(Engine.jsonRpcClient.serverUuid) === null) {
Engine.jsonRpcClient.setupRemoteAccess(Engine.awsClient.idToken, Engine.awsClient.userId)
}
} }
} }
} }
@ -37,6 +41,11 @@ Page {
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
} }
// Button {
// text: "pair"
// onClicked: Engine.jsonRpcClient.setupRemoteAccess(Engine.awsClient.idToken, Engine.awsClient.userId)
// }
SwitchDelegate { SwitchDelegate {
Layout.fillWidth: true Layout.fillWidth: true
text: qsTr("Cloud connection enabled") text: qsTr("Cloud connection enabled")