diff --git a/nymea-app/ui/Nymea.qml b/nymea-app/ui/Nymea.qml
index 79a5ecdc..dfb91162 100644
--- a/nymea-app/ui/Nymea.qml
+++ b/nymea-app/ui/Nymea.qml
@@ -45,6 +45,8 @@ ApplicationWindow {
property int tabCount: 1
}
+ property string privacyPolicyUrl: "https://nymea.io/privacy-statement/en/nymea_privacy.html"
+
RootItem {
id: rootItem
anchors.fill: parent
diff --git a/nymea-app/ui/appsettings/AboutPage.qml b/nymea-app/ui/appsettings/AboutPage.qml
index 7893e9d7..afe61970 100644
--- a/nymea-app/ui/appsettings/AboutPage.qml
+++ b/nymea-app/ui/appsettings/AboutPage.qml
@@ -125,6 +125,13 @@ Page {
pageStack.push(licenseTextComponent)
}
}
+ MeaListItemDelegate {
+ Layout.fillWidth: true
+ text: qsTr("Privacy policy")
+ onClicked: {
+ Qt.openUrlExternally(app.privacyPolicyUrl)
+ }
+ }
}
diff --git a/nymea-app/ui/appsettings/CloudLoginPage.qml b/nymea-app/ui/appsettings/CloudLoginPage.qml
index e6f827a7..f120cedc 100644
--- a/nymea-app/ui/appsettings/CloudLoginPage.qml
+++ b/nymea-app/ui/appsettings/CloudLoginPage.qml
@@ -37,80 +37,84 @@ Page {
}
}
- ColumnLayout {
+ Flickable {
anchors.fill: parent
+ interactive: contentHeight > height
+ contentHeight: childrenRect.height
visible: 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(AWSClient.username)
- }
- Button {
- Layout.fillWidth: true
- Layout.margins: app.margins
- text: qsTr("Log out")
- onClicked: {
- logoutDialog.open()
+ ColumnLayout {
+ width: parent.width
+ 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(AWSClient.username)
}
- }
-
- ThinDivider {}
-
- Label {
- Layout.fillWidth: true
- Layout.topMargin: app.margins
- Layout.leftMargin: app.margins
- Layout.rightMargin: app.margins
- wrapMode: Text.WordWrap
- text: AWSClient.awsDevices.count === 0 ?
- qsTr("There are no boxes connected to your cloud yet.") :
- qsTr("There are %n boxes connected to your cloud", "", AWSClient.awsDevices.count)
- }
- ListView {
- Layout.fillWidth: true
- Layout.fillHeight: true
- clip: true
- model: AWSClient.awsDevices
- 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" : ""
+ Button {
+ Layout.fillWidth: true
+ Layout.margins: app.margins
+ text: qsTr("Log out")
onClicked: {
- print("clicked, connected:", engine.connection.connected, model.id)
- if (!engine.connection.connected) {
- var host = discovery.nymeaHosts.find(model.id)
- engine.connection.connect(host);
+ logoutDialog.open()
+ }
+ }
+
+ ThinDivider {}
+
+ Label {
+ Layout.fillWidth: true
+ Layout.topMargin: app.margins
+ Layout.leftMargin: app.margins
+ Layout.rightMargin: app.margins
+ wrapMode: Text.WordWrap
+ text: AWSClient.awsDevices.count === 0 ?
+ qsTr("There are no boxes connected to your cloud yet.") :
+ qsTr("There are %n boxes connected to your cloud", "", AWSClient.awsDevices.count)
+ }
+ ListView {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ clip: true
+ model: AWSClient.awsDevices
+ 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: {
+ print("clicked, connected:", engine.connection.connected, model.id)
+ if (!engine.connection.connected) {
+ var host = discovery.nymeaHosts.find(model.id)
+ engine.connection.connect(host);
+ }
+ }
+
+ onDeleteClicked: {
+ AWSClient.unpairDevice(model.id);
}
}
- onDeleteClicked: {
- AWSClient.unpairDevice(model.id);
+ BusyIndicator {
+ anchors.centerIn: parent
+ visible: AWSClient.awsDevices.busy
}
}
-
- BusyIndicator {
- anchors.centerIn: parent
- visible: 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)
+ 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. If you decide to delete your account, all your personal information will be removed from %1:cloud and cannot be restored.").arg(app.systemName)
headerIcon: "../images/dialog-warning-symbolic.svg"
standardButtons: Dialog.Cancel | Dialog.Ok
@@ -135,108 +139,126 @@ Page {
}
}
- ColumnLayout {
- anchors { left: parent.left; right: parent.right; top: parent.top }
+ Flickable {
+ anchors.fill: parent
+ interactive: contentHeight > height
+ contentHeight: loginColumn.height
visible: !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
+ ColumnLayout {
+ id: loginColumn
+ anchors { left: parent.left; right: parent.right; top: parent.top }
+ Label {
Layout.fillWidth: true
- echoMode: hiddenPassword ? TextInput.Password : TextInput.Normal
- property bool hiddenPassword: 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)
}
- 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
+ Label {
+ Layout.fillWidth: true
+ Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
+ wrapMode: Text.WordWrap
+ font.pixelSize: app.smallFont
+ text: qsTr("See our privacy policy to find out what information is processed.").arg(app.privacyPolicyUrl)
+ onLinkActivated: {
+ Qt.openUrlExternally(link)
+ }
+ }
+
+ 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
- AWSClient.login(usernameTextField.text, passwordTextField.text);
+ 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
+ AWSClient.login(usernameTextField.text, passwordTextField.text);
+ }
}
- }
- Connections {
- target: AWSClient
- onLoginResult: {
- errorLabel.visible = (error !== AWSClient.LoginErrorNoError)
+ Connections {
+ target: 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 forgotten your password?")
- font.pixelSize: app.smallFont
- color: "red"
- visible: false
- onLinkActivated: {
- pageStack.push(resetPasswordComponent, {email: usernameTextField.text})
+ 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 forgotten your password?")
+ font.pixelSize: app.smallFont
+ color: "red"
+ visible: false
+ onLinkActivated: {
+ pageStack.push(resetPasswordComponent, {email: usernameTextField.text})
+ }
}
- }
- ThinDivider {}
+ 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?")
- }
+ 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)
+ 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
}
@@ -272,7 +294,21 @@ Page {
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.")
+ text: qsTr("Please enter your email address and pick a password in order to create a new account.");
+ onLinkActivated: {
+ print("clicked", link)
+ Qt.openUrlExternally(link)
+ }
+ }
+ Label {
+ Layout.fillWidth: true
+ Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
+ wrapMode: Text.WordWrap
+ font.pixelSize: app.smallFont
+ text: qsTr("See our privacy policy to find out what information is processed. By signing up to %2:cloud you accept those terms and conditions.").arg(app.privacyPolicyUrl).arg(app.systemName)
+ onLinkActivated: {
+ Qt.openUrlExternally(link)
+ }
}
Label {