This repository has been archived on 2026-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
powersync-app/nymea-app/ui/appsettings/CloudLoginPage.qml
2018-09-28 11:24:24 +02:00

558 lines
22 KiB
QML

import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import Nymea 1.0
import "../components"
Page {
id: root
header: GuhHeader {
text: qsTr("Cloud login")
onBackPressed: pageStack.pop()
}
Component.onCompleted: {
if (Engine.awsClient.isLoggedIn) {
Engine.awsClient.fetchDevices();
}
}
Connections {
target: Engine.awsClient
onLoginResult: {
busyOverlay.shown = false;
if (error === AWSClient.LoginErrorNoError) {
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 {
anchors.fill: parent
visible: Engine.awsClient.isLoggedIn
Label {
Layout.fillWidth: true
Layout.topMargin: app.margins
Layout.leftMargin: app.margins
Layout.rightMargin: app.margins
wrapMode: Text.WordWrap
text: qsTr("Logged in as %1").arg(Engine.awsClient.username)
}
Button {
Layout.fillWidth: true
Layout.margins: app.margins
text: qsTr("Log out")
onClicked: {
logoutDialog.open()
}
}
ThinDivider {}
Label {
Layout.fillWidth: true
Layout.topMargin: app.margins
Layout.leftMargin: app.margins
Layout.rightMargin: app.margins
wrapMode: Text.WordWrap
text: Engine.awsClient.awsDevices.count === 0 ?
qsTr("There are no boxes connected to your cloud yet.") :
qsTr("There are %n boxes connected to your cloud", "", Engine.awsClient.awsDevices.count)
}
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
model: Engine.awsClient.awsDevices
clip: true
delegate: MeaListItemDelegate {
width: parent.width
text: model.name
subText: model.id
progressive: false
prominentSubText: false
canDelete: true
iconName: "../images/cloud.svg"
secondaryIconName: !model.online ? "../images/cloud-error.svg" : ""
onClicked: {
if (!Engine.connection.connected) {
var page = pageStack.push(Qt.resolvedUrl("../connection/ConnectingPage.qml"))
page.cancel.connect(function() {
Engine.connection.disconnect()
pageStack.pop(root, StackView.Immediate);
pageStack.push(discoveryPage)
})
Engine.connection.connect("cloud://" + model.id)
}
}
onDeleteClicked: {
Engine.awsClient.unpairDevice(model.id);
}
}
BusyIndicator {
anchors.centerIn: parent
visible: Engine.awsClient.awsDevices.busy
}
}
}
MeaDialog {
id: logoutDialog
title: qsTr("Goodbye")
// 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.").arg(app.systemName)
headerIcon: "../images/dialog-warning-symbolic.svg"
standardButtons: Dialog.Cancel | Dialog.Ok
RowLayout {
CheckBox {
id: deleteCheckbox
}
Label {
Layout.fillWidth: true
wrapMode: Text.WordWrap
text: qsTr("Delete my account")
}
}
onAccepted: {
if (deleteCheckbox.checked) {
busyOverlay.shown = true;
Engine.awsClient.deleteAccount()
} else {
Engine.awsClient.logout()
}
}
}
ColumnLayout {
anchors { left: parent.left; right: parent.right; top: parent.top }
visible: !Engine.awsClient.isLoggedIn
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
wrapMode: Text.WordWrap
text: qsTr("Log in to %1:cloud in order to connect to %1 boxes from anywhere.").arg(app.systemName)
}
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
text: "Username (e-mail)"
}
TextField {
id: usernameTextField
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
placeholderText: "john.smith@cooldomain.com"
inputMethodHints: Qt.ImhEmailCharactersOnly
validator: RegExpValidator { regExp:/\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/ }
}
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
text: qsTr("Password")
}
RowLayout {
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
TextField {
id: passwordTextField
Layout.fillWidth: true
echoMode: hiddenPassword ? TextInput.Password : TextInput.Normal
property bool hiddenPassword: true
}
ColorIcon {
Layout.preferredHeight: app.iconSize
Layout.preferredWidth: app.iconSize
name: "../images/eye.svg"
color: passwordTextField.hiddenPassword ? keyColor : app.accentColor
MouseArea {
anchors.fill: parent
onClicked: {
passwordTextField.hiddenPassword = !passwordTextField.hiddenPassword
}
}
}
}
Button {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
text: qsTr("OK")
enabled: usernameTextField.acceptableInput
onClicked: {
busyOverlay.shown = true
Engine.awsClient.login(usernameTextField.text, passwordTextField.text);
}
}
Connections {
target: Engine.awsClient
onLoginResult: {
errorLabel.visible = (error !== AWSClient.LoginErrorNoError)
}
}
Label {
id: errorLabel
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.bottomMargin: app.margins
wrapMode: Text.WordWrap
text: qsTr("Failed to log in. Please try again. Do you perhaps have <a href=\"#\">forgotten your password?</a>")
font.pixelSize: app.smallFont
color: "red"
visible: false
onLinkActivated: {
pageStack.push(resetPasswordComponent, {email: usernameTextField.text})
}
}
ThinDivider {}
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
wrapMode: Text.WordWrap
text: qsTr("Don't have a user yet?")
}
Button {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
text: qsTr("Sign Up")
onClicked: {
pageStack.push(signupPageComponent)
}
}
}
BusyOverlay {
id: busyOverlay
}
Component {
id: signupPageComponent
Page {
id: signupPage
header: GuhHeader {
text: qsTr("Sign up")
onBackPressed: pageStack.pop()
}
Flickable {
anchors.fill: parent
contentHeight: signupColumn.height
interactive: contentHeight > height
ColumnLayout {
id: signupColumn
anchors { left: parent.left; top: parent.top; right: parent.right }
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
wrapMode: Text.WordWrap
text: qsTr("Welcome to %1:cloud.").arg(app.systemName)
color: app.accentColor
font.pixelSize: app.largeFont
}
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
wrapMode: Text.WordWrap
text: qsTr("Please enter your email address and pick a password in order to create a new account.")
}
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
text: "Username (e-mail)"
}
TextField {
id: usernameTextField
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
placeholderText: "john.smith@cooldomain.com"
inputMethodHints: Qt.ImhEmailCharactersOnly
validator: RegExpValidator { regExp:/\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/ }
}
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
text: qsTr("Password")
}
AWSPasswordTextField {
id: passwordTextField
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
Layout.fillWidth: true
}
Button {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
text: qsTr("Sign Up")
enabled: usernameTextField.acceptableInput && passwordTextField.isValidPassword
onClicked: {
busyOverlay.shown = true;
Engine.awsClient.signup(usernameTextField.text, passwordTextField.password)
}
}
}
Connections {
target: Engine.awsClient
onSignupResult: {
busyOverlay.shown = false;
var text;
switch (error) {
case AWSClient.LoginErrorNoError:
pageStack.push(enterCodeComponent)
return;
case AWSClient.LoginErrorInvalidUserOrPass:
text = qsTr("The given username or password are not valid.")
break;
default:
text = qsTr("Uh oh, something went wrong. Please try again.")
}
var errorDialog = Qt.createComponent(Qt.resolvedUrl("../components/ErrorDialog.qml"));
var popup = errorDialog.createObject(app, {text: text})
popup.open()
}
}
}
}
}
Component {
id: enterCodeComponent
Page {
header: GuhHeader {
text: qsTr("Confirm account")
onBackPressed: pageStack.pop()
}
ColumnLayout {
anchors { left: parent.left; top: parent.top; right: parent.right }
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
wrapMode: Text.WordWrap
text: qsTr("Thanks for signing up. We will send you an email with a confirmation code. Please enter that code in the field below.")
}
TextField {
id: confirmationCodeTextField
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
inputMethodHints: Qt.ImhDigitsOnly
}
Button {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
text: qsTr("OK")
onClicked: {
busyOverlay.shown = true;
Engine.awsClient.confirmRegistration(confirmationCodeTextField.text)
}
}
Connections {
target: Engine.awsClient
onConfirmationResult: {
busyOverlay.shown = false;
var text
switch (error) {
case AWSClient.LoginErrorNoError:
pageStack.pop(root)
return;
case AWSClient.LoginErrorUserExists:
text = qsTr("The given user already exists. Did you forget the password?")
break;
case AWSClient.LoginErrorInvalidCode:
text = qsTr("That wasn't the right code. Please try again.")
break;
case AWSClient.LoginErrorUnknownError:
text = qsTr("Uh oh, something went wrong. Please try again.")
break;
}
var errorDialog = Qt.createComponent(Qt.resolvedUrl("../components/ErrorDialog.qml"));
var popup = errorDialog.createObject(app, {text: text})
popup.open()
return;
}
}
}
}
}
Component {
id: resetPasswordComponent
Page {
id: resetPasswordPage
property alias email: emailTextField.text
header: GuhHeader {
text: qsTr("Reset password")
onBackPressed: pageStack.pop()
}
Connections {
target: Engine.awsClient
onForgotPasswordResult: {
busyOverlay.shown = false
if (error !== AWSClient.LoginErrorNoError) {
var errorDialog = Qt.createComponent(Qt.resolvedUrl("../components/ErrorDialog.qml"));
var text = qsTr("Sorry, this wasn't right. Did you misspell the email address?");
if (error === AWSClient.LoginErrorLimitExceeded) {
text = qsTr("Sorry, there were too many attempts. Please try again after some time.")
}
var popup = errorDialog.createObject(app, {text: text})
popup.open()
return;
}
pageStack.push(confirmResetPasswordComponent, {email: emailTextField.text })
}
}
ColumnLayout {
anchors { left: parent.left; top: parent.top; right: parent.right }
spacing: app.margins
Label {
Layout.fillWidth: true; Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
wrapMode: Text.WordWrap
text: qsTr("Password forgotten?")
font.pixelSize: app.largeFont
color: app.accentColor
}
Label {
Layout.fillWidth: true; Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
wrapMode: Text.WordWrap
text: qsTr("No problem. Enter your email address here and we'll send you a confirmation code to change your password.")
}
TextField {
id: emailTextField
Layout.fillWidth: true; Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
}
Button {
Layout.fillWidth: true; Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
text: qsTr("Reset password")
onClicked: {
Engine.awsClient.forgotPassword(emailTextField.text)
busyOverlay.shown = true
}
}
}
BusyOverlay {
id: busyOverlay
}
}
}
Component {
id: confirmResetPasswordComponent
Page {
id: confirmResetPasswordPage
Connections {
target: Engine.awsClient
onConfirmForgotPasswordResult: {
busyOverlay.shown = false
if (error !== AWSClient.LoginErrorNoError) {
var errorDialog = Qt.createComponent(Qt.resolvedUrl("../components/ErrorDialog.qml"));
var popup = errorDialog.createObject(app, {text: qsTr("Sorry, couldn't reset your password. Did you enter the wrong confirmation code?")})
popup.open()
return;
}
var dialog = Qt.createComponent(Qt.resolvedUrl("../components/MeaDialog.qml"));
var popup = dialog.createObject(app, {headerIcon: "../images/tick.svg", title: qsTr("Yay!"), text: qsTr("Your password has been reset.")})
popup.accepted.connect(function() {
pageStack.pop(root);
})
popup.open()
return;
}
}
property string email
header: GuhHeader {
text: qsTr("Reset password")
onBackPressed: pageStack.pop()
}
ColumnLayout {
anchors { left: parent.left; top: parent.top; right: parent.right }
spacing: app.margins
Label {
Layout.fillWidth: true; Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
wrapMode: Text.WordWrap
text: qsTr("Check your email!")
color: app.accentColor
font.pixelSize: app.largeFont
}
Label {
Layout.fillWidth: true; Layout.leftMargin: app.margins; Layout.rightMargin: app.margins;
wrapMode: Text.WordWrap
text: qsTr("Enter the confirmation code you've received and a new password for your user %1.").arg(confirmResetPasswordPage.email)
}
Label {
Layout.fillWidth: true; Layout.leftMargin: app.margins; Layout.rightMargin: app.margins;
text: qsTr("Confirmation code:")
}
TextField {
id: codeTextField
Layout.fillWidth: true; Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
}
Label {
Layout.fillWidth: true; Layout.leftMargin: app.margins; Layout.rightMargin: app.margins;
text: qsTr("Pick a new password:")
}
AWSPasswordTextField {
id: passwordTextField
Layout.fillWidth: true; Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
}
Button {
Layout.fillWidth: true; Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
text: qsTr("Reset password")
enabled: passwordTextField.isValidPassword && codeTextField.text.length > 0
onClicked: {
busyOverlay.shown = true
Engine.awsClient.confirmForgotPassword(confirmResetPasswordPage.email, codeTextField.text, passwordTextField.password)
}
}
BusyOverlay {
id: busyOverlay
}
}
}
}
}