From 19f0c49d1355b1b7ea9077558b359259274a94c0 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Tue, 19 Mar 2019 13:15:02 +0100 Subject: [PATCH] Add privacy policy --- nymea-app/ui/Nymea.qml | 2 + nymea-app/ui/appsettings/AboutPage.qml | 7 + nymea-app/ui/appsettings/CloudLoginPage.qml | 314 +++++++++++--------- 3 files changed, 184 insertions(+), 139 deletions(-) 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 {