From 4381b70a2fd15f89822a06a67f959754f5e7e2d0 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Thu, 6 Sep 2018 00:52:00 +0200 Subject: [PATCH] some improvements in the cloud login --- .../discovery/nymeadiscovery.cpp | 27 ++- nymea-app/ui/Nymea.qml | 1 + nymea-app/ui/appsettings/CloudLoginPage.qml | 188 ++++++++++-------- .../ui/components/AWSPasswordTextField.qml | 55 ++++- 4 files changed, 174 insertions(+), 97 deletions(-) diff --git a/libnymea-app-core/discovery/nymeadiscovery.cpp b/libnymea-app-core/discovery/nymeadiscovery.cpp index 3dc00bfa..af141d43 100644 --- a/libnymea-app-core/discovery/nymeadiscovery.cpp +++ b/libnymea-app-core/discovery/nymeadiscovery.cpp @@ -40,22 +40,41 @@ void NymeaDiscovery::setDiscovering(bool discovering) return; m_discovering = discovering; - // For zeroconf we'll ignore it as zeroconf doesn't do active discovery but just listens for changes in the net all the time + // If we have zeroconf skip upnp. ZeroConf will not do an active discovery and if it's available it'll always have good data + if (!m_zeroConf->available()) { + if (discovering) { + m_upnp->discover(); + } else { + m_upnp->stopDiscovery(); + } + } if (discovering) { - m_upnp->discover(); + // If there's no Zeroconf, use UPnP instead + if (!m_zeroConf->available()) { + m_upnp->discover(); + } + + // Always start Bluetooth discovery if HW is available if (m_bluetooth) { m_bluetooth->discover(); } + + // start polling cloud + m_cloudPollTimer.start(); + // If we're logged in, poll right away if (Engine::instance()->awsClient()->isLoggedIn()) { syncCloudDevices(); Engine::instance()->awsClient()->fetchDevices(); } - m_cloudPollTimer.start(); } else { - m_upnp->stopDiscovery(); + if (!m_zeroConf->available()) { + m_upnp->stopDiscovery(); + } + if (m_bluetooth) { m_bluetooth->stopDiscovery(); } + m_cloudPollTimer.stop(); } diff --git a/nymea-app/ui/Nymea.qml b/nymea-app/ui/Nymea.qml index 03d0690d..7a4ca9bb 100644 --- a/nymea-app/ui/Nymea.qml +++ b/nymea-app/ui/Nymea.qml @@ -376,6 +376,7 @@ ApplicationWindow { } KeyboardLoader { + id: keyboardRect anchors { left: parent.left; bottom: parent.bottom; right: parent.right } } } diff --git a/nymea-app/ui/appsettings/CloudLoginPage.qml b/nymea-app/ui/appsettings/CloudLoginPage.qml index 2bb7c431..0e4e167f 100644 --- a/nymea-app/ui/appsettings/CloudLoginPage.qml +++ b/nymea-app/ui/appsettings/CloudLoginPage.qml @@ -154,13 +154,29 @@ Page { Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins text: qsTr("Password") } - TextField { - id: passwordTextField + RowLayout { Layout.leftMargin: app.margins; Layout.rightMargin: app.margins - Layout.fillWidth: true - echoMode: TextInput.Password + 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 @@ -225,81 +241,87 @@ Page { onBackPressed: pageStack.pop() } - ColumnLayout { - anchors { left: parent.left; top: parent.top; right: parent.right } + Flickable { + anchors.fill: parent + contentHeight: signupColumn.height + interactive: contentHeight > height - 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 - } + 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("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: { - Engine.awsClient.signup(usernameTextField.text, passwordTextField.password) + 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 } - } - Connections { - target: Engine.awsClient - onSignupResult: { - switch (error) { - case AWSClient.LoginErrorNoError: - signUpResultLabel.text = "" - pageStack.push(enterCodeComponent) - break; - case AWSClient.LoginErrorInvalidUserOrPass: - signUpResultLabel.text = qsTr("The given username or password are not valid.") - break; - default: - signUpResultLabel.text = qsTr("Uh oh, something went wrong. Please try again.") + 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) } } } - Label { - id: signUpResultLabel - Layout.fillWidth: true - Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins - wrapMode: Text.WordWrap + + 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() + } } } } @@ -335,6 +357,7 @@ Page { Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins text: qsTr("OK") onClicked: { + busyOverlay.shown = true; Engine.awsClient.confirmRegistration(confirmationCodeTextField.text) } } @@ -342,29 +365,28 @@ Page { Connections { target: Engine.awsClient onConfirmationResult: { + busyOverlay.shown = false; + var text switch (error) { case AWSClient.LoginErrorNoError: - confirmResultLabel.text = "" pageStack.pop(root) - break; + return; case AWSClient.LoginErrorUserExists: - confirmResultLabel.text = qsTr("The given user already exists. Did you forget the password?") + text = qsTr("The given user already exists. Did you forget the password?") break; case AWSClient.LoginErrorInvalidCode: - confirmResultLabel.text = qsTr("That wasn't the right code. Please try again.") + text = qsTr("That wasn't the right code. Please try again.") break; case AWSClient.LoginErrorUnknownError: - confirmResultLabel.text = qsTr("Uh oh, something went wrong. Please try again.") + 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; - Label { - id: confirmResultLabel - Layout.fillWidth: true - Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins - wrapMode: Text.WordWrap + } } } } diff --git a/nymea-app/ui/components/AWSPasswordTextField.qml b/nymea-app/ui/components/AWSPasswordTextField.qml index 67101373..2188be07 100644 --- a/nymea-app/ui/components/AWSPasswordTextField.qml +++ b/nymea-app/ui/components/AWSPasswordTextField.qml @@ -16,13 +16,31 @@ ColumnLayout { readonly property bool hasSpecialChar: passwordTextField.text.search(/[\*!"$%&/()=?`'+#'¡^°²³¼\[\]|{}\\@]/) >= 0 readonly property bool confirmationMatches: passwordTextField.text === confirmationPasswordTextField.text - TextField { - id: passwordTextField - Layout.fillWidth: true - echoMode: TextInput.Password - placeholderText: qsTr("Pick a password") + property bool hiddenPassword: true + + RowLayout { + + TextField { + id: passwordTextField + Layout.fillWidth: true + echoMode: root.hiddenPassword ? TextInput.Password : TextInput.Normal + placeholderText: qsTr("Pick a password") + } + ColorIcon { + Layout.preferredHeight: app.iconSize + Layout.preferredWidth: app.iconSize + name: "../images/eye.svg" + color: root.hiddenPassword ? keyColor : app.accentColor + MouseArea { + anchors.fill: parent + onClicked: { + root.hiddenPassword = !root.hiddenPassword + } + } + } } + Label { Layout.fillWidth: true wrapMode: Text.WordWrap @@ -38,13 +56,30 @@ ColumnLayout { font.pixelSize: app.smallFont } - TextField { - id: confirmationPasswordTextField - Layout.fillWidth: true - echoMode: TextInput.Password - placeholderText: qsTr("Confirm password") + RowLayout { + + TextField { + id: confirmationPasswordTextField + Layout.fillWidth: true + echoMode: root.hiddenPassword ? TextInput.Password : TextInput.Normal + placeholderText: qsTr("Confirm password") + } + + ColorIcon { + Layout.preferredHeight: app.iconSize + Layout.preferredWidth: app.iconSize + name: "../images/eye.svg" + color: root.hiddenPassword ? keyColor : app.accentColor + MouseArea { + anchors.fill: parent + onClicked: { + root.hiddenPassword = !root.hiddenPassword + } + } + } } + Label { Layout.fillWidth: true wrapMode: Text.WordWrap