From 7235611d5437fcb7f5425e9390c7039c35dc202d Mon Sep 17 00:00:00 2001 From: miruka Date: Sat, 7 Dec 2019 09:38:36 -0400 Subject: [PATCH] Refactor SignIn, adjustments to HCheckBox & HBox --- src/icons/thin/sign-in.svg | 3 + src/qml/Base/HBox.qml | 24 +-- src/qml/Base/HCheckBox.qml | 4 +- src/qml/Pages/AccountSettings/ImportError.qml | 3 - .../AccountSettings/ImportExportKeys.qml | 3 - src/qml/Pages/AddAccount/AddAccount.qml | 15 ++ src/qml/Pages/AddAccount/SignIn.qml | 185 +++++++++++++++++ src/qml/Pages/AddChat/AddChat.qml | 1 - src/qml/Pages/AddChat/CreateRoom.qml | 8 +- src/qml/Pages/AddChat/EncryptCheckBox.qml | 1 - src/qml/Pages/AddChat/FindSomeone.qml | 10 +- src/qml/Pages/AddChat/JoinRoom.qml | 8 +- src/qml/Pages/SignIn.qml | 188 ------------------ src/qml/Popups/LogoutPopup.qml | 2 +- src/qml/SidePane/SidePaneToolBar.qml | 2 +- src/qml/UI.qml | 2 +- src/themes/Default.qpl | 1 + 17 files changed, 233 insertions(+), 227 deletions(-) create mode 100644 src/icons/thin/sign-in.svg create mode 100644 src/qml/Pages/AddAccount/AddAccount.qml create mode 100644 src/qml/Pages/AddAccount/SignIn.qml delete mode 100644 src/qml/Pages/SignIn.qml diff --git a/src/icons/thin/sign-in.svg b/src/icons/thin/sign-in.svg new file mode 100644 index 00000000..ee16f93e --- /dev/null +++ b/src/icons/thin/sign-in.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/qml/Base/HBox.qml b/src/qml/Base/HBox.qml index 84a86ead..c1212c11 100644 --- a/src/qml/Base/HBox.qml +++ b/src/qml/Base/HBox.qml @@ -15,14 +15,6 @@ Rectangle { property real multiplyWidth: 1.0 - property real multiplyHorizontalSpacing: 1.5 - property real multiplyVerticalSpacing: 1.5 - - property int horizontalSpacing: - Math.min(theme.spacing * width / 400, theme.spacing) * - multiplyHorizontalSpacing - - property int verticalSpacing: theme.spacing * multiplyVerticalSpacing property alias title: interfaceTitle.text property alias buttonModel: buttonRepeater.model @@ -51,7 +43,7 @@ Rectangle { HColumnLayout { id: mainColumn width: parent.width - spacing: interfaceBox.verticalSpacing + spacing: theme.spacing HLabel { id: interfaceTitle @@ -62,21 +54,21 @@ Rectangle { Layout.preferredWidth: parent.width Layout.fillWidth: true - Layout.topMargin: interfaceBox.verticalSpacing - Layout.leftMargin: interfaceBox.horizontalSpacing - Layout.rightMargin: interfaceBox.horizontalSpacing + Layout.topMargin: theme.spacing + Layout.leftMargin: theme.spacing + Layout.rightMargin: theme.spacing } HColumnLayout { id: interfaceBody - spacing: interfaceBox.verticalSpacing + spacing: theme.spacing Layout.preferredWidth: parent.width Layout.fillWidth: true Layout.topMargin: - interfaceTitle.visible ? 0 : interfaceBox.verticalSpacing - Layout.leftMargin: interfaceBox.horizontalSpacing - Layout.rightMargin: interfaceBox.horizontalSpacing + interfaceTitle.visible ? 0 : theme.spacing + Layout.leftMargin: theme.spacing + Layout.rightMargin: theme.spacing } HGridLayout { diff --git a/src/qml/Base/HCheckBox.qml b/src/qml/Base/HCheckBox.qml index eff569f6..4b0f24a6 100644 --- a/src/qml/Base/HCheckBox.qml +++ b/src/qml/Base/HCheckBox.qml @@ -21,8 +21,8 @@ CheckBox { indicator: Rectangle { - implicitWidth: implicitHeight - implicitHeight: mainText.font.pixelSize * 1.5 + implicitWidth: theme.controls.checkBox.boxSize + implicitHeight: implicitWidth x: box.leftPadding y: box.topPadding + box.availableHeight / 2 - height / 2 radius: theme.radius / 1.5 diff --git a/src/qml/Pages/AccountSettings/ImportError.qml b/src/qml/Pages/AccountSettings/ImportError.qml index 72a2ff30..0ff4c683 100644 --- a/src/qml/Pages/AccountSettings/ImportError.qml +++ b/src/qml/Pages/AccountSettings/ImportError.qml @@ -5,9 +5,6 @@ import "../../Base" import "../../utils.js" as Utils HBox { - horizontalSpacing: currentSpacing - verticalSpacing: currentSpacing - buttonModel: [ { name: "retry", text: qsTr("Retry"), iconName: "retry" }, { name: "cancel", text: qsTr("Cancel"), iconName: "cancel" }, diff --git a/src/qml/Pages/AccountSettings/ImportExportKeys.qml b/src/qml/Pages/AccountSettings/ImportExportKeys.qml index f4cab581..7905a073 100644 --- a/src/qml/Pages/AccountSettings/ImportExportKeys.qml +++ b/src/qml/Pages/AccountSettings/ImportExportKeys.qml @@ -4,9 +4,6 @@ import "../../Base" import "../../utils.js" as Utils HBox { - horizontalSpacing: currentSpacing - verticalSpacing: currentSpacing - buttonModel: [ { name: "export", text: qsTr("Export"), iconName: "export-keys"}, { name: "import", text: qsTr("Import"), iconName: "import-keys"}, diff --git a/src/qml/Pages/AddAccount/AddAccount.qml b/src/qml/Pages/AddAccount/AddAccount.qml new file mode 100644 index 00000000..54ae1c54 --- /dev/null +++ b/src/qml/Pages/AddAccount/AddAccount.qml @@ -0,0 +1,15 @@ +import QtQuick 2.12 +import QtQuick.Layouts 1.12 +import "../../Base" + +HPage { + HTabbedBoxes { + tabModel: [ + qsTr("Sign in"), qsTr("Register"), qsTr("Recovery"), + ] + + SignIn { Component.onCompleted: forceActiveFocus() } + Item {} // TODO + Item {} // TODO + } +} diff --git a/src/qml/Pages/AddAccount/SignIn.qml b/src/qml/Pages/AddAccount/SignIn.qml new file mode 100644 index 00000000..f8297eb6 --- /dev/null +++ b/src/qml/Pages/AddAccount/SignIn.qml @@ -0,0 +1,185 @@ +import QtQuick 2.12 +import QtQuick.Layouts 1.12 +import "../../Base" + +HBox { + id: signInBox + clickButtonOnEnter: "apply" + + onFocusChanged: idField.forceActiveFocus() + + buttonModel: [ + { + name: "apply", + text: qsTr("Sign in"), + enabled: canSignIn, + iconName: "sign-in", + disableWhileLoading: false + }, + { name: "cancel", text: qsTr("Cancel"), iconName: "cancel"}, + ] + + buttonCallbacks: ({ + apply: button => { + button.loading = true + errorMessage.text = "" + + let args = [ + idField.text, passwordField.text, + undefined, serverField.text, + ] + + signInTimeout.restart() + + py.callCoro("login_client", args, userId => { + signInTimeout.stop() + errorMessage.text = "" + button.loading = false + + py.callCoro( + rememberAccount.checked ? + "saved_accounts.add": "saved_accounts.delete", + + [userId] + ) + + pageLoader.showPage( + "AccountSettings/AccountSettings", {userId} + ) + + }, type => { + if (type === "CancelledError") return + + signInTimeout.stop() + let txt = qsTr("Invalid request or login type") + + if (type === "MatrixForbidden") + txt = qsTr("Invalid username or password") + + if (type === "MatrixUserDeactivated") + txt = qsTr("This account was deactivated") + + errorMessage.text = txt + button.loading = false + }) + }, + + cancel: button => {} + }) + + + property string signInWith: "username" + readonly property bool canSignIn: + serverField.text && idField.text && passwordField.text && + ! serverField.error + + + Timer { + id: signInTimeout + interval: 30 * 1000 + onTriggered: { + errorMessage.text = + serverField.knownServerChosen ? + + qsTr("This server seems unavailable. Verify your inter" + + "net connection or try again in a few minutes.") : + + qsTr("This server seems unavailable. Verify the " + + "entered URL, your internet connection or try " + + "again in a few minutes.") + } + } + + HRowLayout { + spacing: theme.spacing * 1.25 + Layout.alignment: Qt.AlignHCenter + Layout.topMargin: spacing / 2 + Layout.bottomMargin: Layout.topMargin + + Repeater { + model: ["username", "email", "phone"] + + HButton { + icon.name: modelData + circle: true + checked: signInWith == modelData + enabled: modelData == "username" + autoExclusive: true + onClicked: signInWith = modelData + } + } + } + + HTextField { + id: serverField + placeholderText: qsTr("Homeserver URL") + text: "https://matrix.org" + error: ! /.+:\/\/.+/.test(cleanText) + + Layout.fillWidth: true + + + readonly property string cleanText: text.toLowerCase().trim() + + // 2019-11-11 https://www.hello-matrix.net/public_servers.php + readonly property var knownServers: [ + "https://matrix.org", + "https://chat.weho.st", + "https://tchncs.de", + "https://chat.privacytools.io", + "https://hackerspaces.be", + "https://matrix.allmende.io", + "https://feneas.org", + "https://junta.pl", + "https://perthchat.org", + "https://matrix.tedomum.net", + "https://converser.eu", + "https://ru-matrix.org", + "https://matrix.sibnsk.net", + "https://alternanet.fr", + ] + + readonly property bool knownServerChosen: + knownServers.includes(cleanText) + } + + HTextField { + id: idField + placeholderText: qsTr( + signInWith === "email" ? "Email" : + signInWith === "phone" ? "Phone" : + "Username" + ) + + Layout.fillWidth: true + } + + HTextField { + id: passwordField + placeholderText: qsTr("Password") + echoMode: HTextField.Password + + Layout.fillWidth: true + } + + HCheckBox { + id: rememberAccount + text: qsTr("Remember my account") + checked: true + + Layout.alignment: Qt.AlignHCenter + } + + HLabel { + id: errorMessage + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignHCenter + color: theme.colors.errorText + + visible: Layout.maximumHeight > 0 + Layout.maximumHeight: text ? implicitHeight : 0 + Behavior on Layout.maximumHeight { HNumberAnimation {} } + + Layout.fillWidth: true + } +} diff --git a/src/qml/Pages/AddChat/AddChat.qml b/src/qml/Pages/AddChat/AddChat.qml index 187ab72f..d932aa7f 100644 --- a/src/qml/Pages/AddChat/AddChat.qml +++ b/src/qml/Pages/AddChat/AddChat.qml @@ -1,5 +1,4 @@ import QtQuick 2.12 -import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 import "../../Base" import "../../utils.js" as Utils diff --git a/src/qml/Pages/AddChat/CreateRoom.qml b/src/qml/Pages/AddChat/CreateRoom.qml index e2141a6f..ab4b4f0d 100644 --- a/src/qml/Pages/AddChat/CreateRoom.qml +++ b/src/qml/Pages/AddChat/CreateRoom.qml @@ -89,15 +89,14 @@ HBox { id: publicCheckBox text: qsTr("Make this room public") subtitle.text: qsTr("Anyone will be able to join without invitation.") - spacing: addChatBox.horizontalSpacing - Layout.maximumWidth: parent.width + Layout.fillWidth: true } EncryptCheckBox { id: encryptCheckBox - Layout.maximumWidth: parent.width + Layout.fillWidth: true } HCheckBox { @@ -105,9 +104,8 @@ HBox { text: qsTr("Reject users from other matrix servers") subtitle.text: qsTr("Cannot be changed later!") subtitle.color: theme.colors.middleBackground - spacing: addChatBox.horizontalSpacing - Layout.maximumWidth: parent.width + Layout.fillWidth: true } HLabel { diff --git a/src/qml/Pages/AddChat/EncryptCheckBox.qml b/src/qml/Pages/AddChat/EncryptCheckBox.qml index 083eedac..ccb07015 100644 --- a/src/qml/Pages/AddChat/EncryptCheckBox.qml +++ b/src/qml/Pages/AddChat/EncryptCheckBox.qml @@ -10,5 +10,4 @@ HCheckBox { qsTr("Cannot be disabled later!") + "" subtitle.textFormat: Text.StyledText - spacing: addChatBox.horizontalSpacing } diff --git a/src/qml/Pages/AddChat/FindSomeone.qml b/src/qml/Pages/AddChat/FindSomeone.qml index 469ed38e..27f1c622 100644 --- a/src/qml/Pages/AddChat/FindSomeone.qml +++ b/src/qml/Pages/AddChat/FindSomeone.qml @@ -10,8 +10,12 @@ HBox { onFocusChanged: userField.forceActiveFocus() buttonModel: [ - { name: "apply", text: qsTr("Start chat"), - iconName: "start-direct-chat", enabled: Boolean(userField.text) }, + { + name: "apply", + text: qsTr("Start chat"), + iconName: "start-direct-chat", + enabled: Boolean(userField.text) + }, { name: "cancel", text: qsTr("Cancel"), iconName: "cancel" }, ] @@ -74,7 +78,7 @@ HBox { EncryptCheckBox { id: encryptCheckBox - Layout.maximumWidth: parent.width + Layout.fillWidth: true } HLabel { diff --git a/src/qml/Pages/AddChat/JoinRoom.qml b/src/qml/Pages/AddChat/JoinRoom.qml index 3ee1a045..46a71a90 100644 --- a/src/qml/Pages/AddChat/JoinRoom.qml +++ b/src/qml/Pages/AddChat/JoinRoom.qml @@ -10,8 +10,12 @@ HBox { onFocusChanged: roomField.forceActiveFocus() buttonModel: [ - { name: "apply", text: qsTr("Join"), iconName: "join", - enabled: Boolean(roomField.text), }, + { + name: "apply", + text: qsTr("Join"), + iconName: "join", + enabled: Boolean(roomField.text), + }, { name: "cancel", text: qsTr("Cancel"), iconName: "cancel" }, ] diff --git a/src/qml/Pages/SignIn.qml b/src/qml/Pages/SignIn.qml deleted file mode 100644 index 343500b1..00000000 --- a/src/qml/Pages/SignIn.qml +++ /dev/null @@ -1,188 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Layouts 1.12 -import "../Base" - -HPage { - property string loginWith: "username" - readonly property bool canLogin: - serverField.text && idField.text && passwordField.text && - ! serverField.error - - onFocusChanged: idField.forceActiveFocus() - - HBox { - id: signInBox - Layout.alignment: Qt.AlignCenter - - title: qsTr("Sign in") - clickButtonOnEnter: "login" - - buttonModel: [ - { name: "register", text: qsTr("Register"), enabled: false }, - { name: "login", text: qsTr("Login"), enabled: canLogin, - disableWhileLoading: false }, - { name: "forgot", text: qsTr("Forgot?"), enabled: false }, - ] - - buttonCallbacks: ({ - register: button => {}, - - login: button => { - button.loading = true - errorMessage.text = "" - - let args = [ - idField.text, passwordField.text, - undefined, serverField.text, - ] - - loginTimeout.restart() - - py.callCoro("login_client", args, userId => { - loginTimeout.stop() - errorMessage.text = "" - button.loading = false - - py.callCoro( - rememberAccount.checked ? - "saved_accounts.add": "saved_accounts.delete", - - [userId] - ) - - pageLoader.showPage( - "AccountSettings/AccountSettings", {userId} - ) - - }, type => { - if (type === "CancelledError") return - - loginTimeout.stop() - let txt = qsTr("Invalid request or login type") - - if (type === "MatrixForbidden") - txt = qsTr("Invalid username or password") - - if (type === "MatrixUserDeactivated") - txt = qsTr("This account was deactivated") - - errorMessage.text = txt - button.loading = false - }) - }, - - forgot: button => {} - }) - - Timer { - id: loginTimeout - interval: 30 * 1000 - onTriggered: { - errorMessage.text = - serverField.knownServerChosen ? - - qsTr("This server seems unavailable. Verify your inter" + - "net connection or try again in a few minutes.") : - - qsTr("This server seems unavailable. Verify the " + - "entered URL, your internet connection or try " + - "again in a few minutes.") - } - } - - HRowLayout { - spacing: signInBox.horizontalSpacing * 1.25 - Layout.alignment: Qt.AlignHCenter - Layout.topMargin: signInBox.verticalSpacing / 2 - Layout.bottomMargin: Layout.topMargin - - Repeater { - model: ["username", "email", "phone"] - - HButton { - icon.name: modelData - circle: true - checked: loginWith == modelData - enabled: modelData == "username" - autoExclusive: true - onClicked: loginWith = modelData - } - } - } - - HTextField { - id: serverField - placeholderText: qsTr("Homeserver URL") - text: "https://matrix.org" - error: ! /.+:\/\/.+/.test(cleanText) - - Layout.fillWidth: true - - - readonly property string cleanText: text.toLowerCase().trim() - - // 2019-11-11 https://www.hello-matrix.net/public_servers.php - readonly property var knownServers: [ - "https://matrix.org", - "https://chat.weho.st", - "https://tchncs.de", - "https://chat.privacytools.io", - "https://hackerspaces.be", - "https://matrix.allmende.io", - "https://feneas.org", - "https://junta.pl", - "https://perthchat.org", - "https://matrix.tedomum.net", - "https://converser.eu", - "https://ru-matrix.org", - "https://matrix.sibnsk.net", - "https://alternanet.fr", - ] - - readonly property bool knownServerChosen: - knownServers.includes(cleanText) - } - - HTextField { - id: idField - placeholderText: qsTr( - loginWith === "email" ? "Email" : - loginWith === "phone" ? "Phone" : - "Username" - ) - - Layout.fillWidth: true - } - - HTextField { - id: passwordField - placeholderText: qsTr("Password") - echoMode: HTextField.Password - - Layout.fillWidth: true - } - - HCheckBox { - id: rememberAccount - text: qsTr("Automatically sign in") - checked: true - spacing: signInBox.horizontalSpacing - - Layout.maximumWidth: parent.width - Layout.alignment: Qt.AlignHCenter - } - - HLabel { - id: errorMessage - wrapMode: Text.Wrap - horizontalAlignment: Text.AlignHCenter - color: theme.colors.errorText - - visible: Layout.maximumHeight > 0 - Layout.maximumHeight: text ? implicitHeight : 0 - Behavior on Layout.maximumHeight { HNumberAnimation {} } - - Layout.fillWidth: true - } - } -} diff --git a/src/qml/Popups/LogoutPopup.qml b/src/qml/Popups/LogoutPopup.qml index e37113e9..1e4863f2 100644 --- a/src/qml/Popups/LogoutPopup.qml +++ b/src/qml/Popups/LogoutPopup.qml @@ -44,7 +44,7 @@ BoxPopup { popup.ok() if ((modelSources["Account"] || []).length < 2) { - pageLoader.showPage("SignIn") + pageLoader.showPage("AddAccount/AddAccount") } else if (window.uiState.pageProperties.userId == userId) { pageLoader.showPage("Default") } diff --git a/src/qml/SidePane/SidePaneToolBar.qml b/src/qml/SidePane/SidePaneToolBar.qml index a6eb9319..214591fa 100644 --- a/src/qml/SidePane/SidePaneToolBar.qml +++ b/src/qml/SidePane/SidePaneToolBar.qml @@ -18,7 +18,7 @@ HRowLayout { icon.name: "add-account" toolTip.text: qsTr("Add another account") backgroundColor: theme.sidePane.settingsButton.background - onClicked: pageLoader.showPage("SignIn") + onClicked: pageLoader.showPage("AddAccount/AddAccount") Layout.fillHeight: true } diff --git a/src/qml/UI.qml b/src/qml/UI.qml index 197ff6fd..61e60324 100644 --- a/src/qml/UI.qml +++ b/src/qml/UI.qml @@ -90,7 +90,7 @@ Item { Component.onCompleted: { if (! py.startupAnyAccountsSaved) { - pageLoader.showPage("SignIn") + pageLoader.showPage("AddAccount/AddAccount") return } diff --git a/src/themes/Default.qpl b/src/themes/Default.qpl index 04b5cb85..02c49ce6 100644 --- a/src/themes/Default.qpl +++ b/src/themes/Default.qpl @@ -145,6 +145,7 @@ controls: checkBox: color checkIconColorize: colors.accentBackground color boxBackground: controls.button.background + int boxSize: 24 * uiScale color boxBorder: hsluv(0, 0, 50, 0.3) color boxHoveredBorder: colors.accentBackground