From e09efaecda3645b52c37ada60e5afc155073e2c2 Mon Sep 17 00:00:00 2001 From: miruka Date: Sat, 27 Apr 2019 18:00:28 -0400 Subject: [PATCH] Refactor LoginPage into separate components --- TODO.md | 3 +- harmonyqml/components/Window.qml | 2 +- harmonyqml/components/base/HButton.qml | 31 +++- harmonyqml/components/base/HInterfaceBox.qml | 57 +++++++ harmonyqml/components/base/HScalingBox.qml | 17 +++ harmonyqml/components/pages/LoginPage.qml | 143 ------------------ .../components/pages/LoginPage/LoginPage.qml | 17 +++ .../components/pages/LoginPage/SignInBox.qml | 75 +++++++++ 8 files changed, 195 insertions(+), 150 deletions(-) create mode 100644 harmonyqml/components/base/HInterfaceBox.qml create mode 100644 harmonyqml/components/base/HScalingBox.qml delete mode 100644 harmonyqml/components/pages/LoginPage.qml create mode 100644 harmonyqml/components/pages/LoginPage/LoginPage.qml create mode 100644 harmonyqml/components/pages/LoginPage/SignInBox.qml diff --git a/TODO.md b/TODO.md index e4b9aa0b..3ebb939c 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,7 @@ - Current focus - - Merge login page + - Remember account dialog - Just import nio? + - Use new H\* components everywhere - TextInput.accepted() for SendBox - Refactoring diff --git a/harmonyqml/components/Window.qml b/harmonyqml/components/Window.qml index 6e084dea..f0f3207a 100644 --- a/harmonyqml/components/Window.qml +++ b/harmonyqml/components/Window.qml @@ -10,7 +10,7 @@ ApplicationWindow { Loader { anchors.fill: parent source: Backend.clientManager.clientCount < 1 ? - "pages/LoginPage.qml" : "pages/MainUI.qml" + "pages/LoginPage/LoginPage.qml" : "pages/MainUI.qml" objectName: "UILoader" } } diff --git a/harmonyqml/components/base/HButton.qml b/harmonyqml/components/base/HButton.qml index 870f4d51..e1823bb2 100644 --- a/harmonyqml/components/base/HButton.qml +++ b/harmonyqml/components/base/HButton.qml @@ -12,6 +12,15 @@ Button { property int contentWidth: 0 + signal canceled + signal clicked + signal doubleClicked + signal entered + signal exited + signal pressAndHold + signal pressed + signal released + function loadingUntilFutureDone(future) { loading = true future.onGotResult.connect(function() { loading = false }) @@ -75,17 +84,29 @@ Button { } MouseArea { - z: 101 anchors.fill: parent hoverEnabled: true - propagateComposedEvents: true - onEntered: overlayOpacity = checked ? 0 : 0.3 - onExited: overlayOpacity = 0 - onPressed: overlayOpacity += 0.3 + onCanceled: button.canceled() + onClicked: button.clicked() + onDoubleClicked: button.doubleClicked() + onEntered: { + overlayOpacity = checked ? 0 : 0.3 + button.entered() + } + onExited: { + overlayOpacity = 0 + button.exited() + } + onPressAndHold: button.pressAndHold() + onPressed: { + overlayOpacity += 0.3 + button.pressed() + } onReleased: { if (checkable) { checked = ! checked } overlayOpacity = checked ? 0 : 0.3 + button.released() } } } diff --git a/harmonyqml/components/base/HInterfaceBox.qml b/harmonyqml/components/base/HInterfaceBox.qml new file mode 100644 index 00000000..a331cf6f --- /dev/null +++ b/harmonyqml/components/base/HInterfaceBox.qml @@ -0,0 +1,57 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.4 + +HScalingBox { + id: interfaceBox + + property alias title: interfaceTitle.text + property alias buttonModel: interfaceButtonsRepeater.model + property var buttonCallbacks: [] + property string enterButtonTarget: "" + + default property alias body: interfaceBody.children + + function clickEnterButtonTarget() { + for (var i = 0; i < buttonModel.length; i++) { + var btn = interfaceButtonsRepeater.itemAt(i) + if (btn.name === enterButtonTarget) { btn.clicked() } + } + } + + ColumnLayout { + anchors.fill: parent + id: mainColumn + + HRowLayout { + Layout.alignment: Qt.AlignHCenter + Layout.margins: interfaceBox.margins + + HLabel { + id: interfaceTitle + font.pixelSize: HStyle.fontSize.big + } + } + + ColumnLayout { id: interfaceBody } + + HRowLayout { + Repeater { + id: interfaceButtonsRepeater + model: [] + + HButton { + property string name: modelData.name + + id: button + text: modelData.text + iconName: modelData.iconName || "" + onClicked: buttonCallbacks[modelData.name](button) + + Layout.fillWidth: true + Layout.preferredHeight: 32 + } + } + } + } +} diff --git a/harmonyqml/components/base/HScalingBox.qml b/harmonyqml/components/base/HScalingBox.qml new file mode 100644 index 00000000..9575c8cc --- /dev/null +++ b/harmonyqml/components/base/HScalingBox.qml @@ -0,0 +1,17 @@ +import QtQuick 2.7 + +Rectangle { + property var container: parent + + property real widthForHeight: 0.75 + property int baseHeight: 300 + property int startScalingUpAboveHeight: 1080 + + readonly property int baseWidth: baseHeight * widthForHeight + readonly property int margins: baseHeight * 0.03 + + color: Qt.hsla(1, 1, 1, 0.3) + height: Math.min(container.height, baseHeight) + width: Math.min(container.width, baseWidth) + scale: Math.max(1, container.height / startScalingUpAboveHeight) +} diff --git a/harmonyqml/components/pages/LoginPage.qml b/harmonyqml/components/pages/LoginPage.qml deleted file mode 100644 index 3b78befd..00000000 --- a/harmonyqml/components/pages/LoginPage.qml +++ /dev/null @@ -1,143 +0,0 @@ -import QtQuick 2.7 -import QtQuick.Controls 2.2 -import QtQuick.Layouts 1.4 -import "../base" as Base - -Image { - id: loginBackground - asynchronous: true - fillMode: Image.PreserveAspectCrop - cache: false - source: "../../images/login_background.jpg" - - function login() { - loginButton.loadingUntilFutureDone(Backend.clientManager.new( - "matrix.org", identifierField.text, passwordField.text - )) - } - - Rectangle { - color: Qt.hsla(1, 1, 1, 0.3) - - id: loginBox - - property real widthForHeight: 0.75 - property int baseHeight: 300 - property int baseWidth: baseHeight * widthForHeight - property int startScalingUpAboveHeight: 1080 - - anchors.centerIn: parent - height: Math.min(parent.height, baseHeight) - width: Math.min(parent.width, baseWidth) - scale: Math.max(1, parent.height / startScalingUpAboveHeight) - - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - - ColumnLayout { - anchors.fill: parent - id: mainColumn - - property int hMargin: loginBox.baseWidth * 0.05 - property int vMargin: hMargin * loginBox.widthForHeight - - Base.HRowLayout { - Layout.alignment: Qt.AlignHCenter - Layout.margins: mainColumn.hMargin - Layout.topMargin: mainColumn.vMargin - Layout.bottomMargin: mainColumn.vMargin - - Base.HLabel { - text: "Sign in" - font.pixelSize: Base.HStyle.fontSize.big - } - } - - Item { Layout.fillHeight: true } - - Base.HRowLayout { - Layout.margins: mainColumn.hMargin - Layout.topMargin: mainColumn.vMargin - Layout.bottomMargin: mainColumn.vMargin - Layout.alignment: Qt.AlignHCenter - spacing: mainColumn.hMargin * 1.25 - - Base.HButton { - id: loginWithUsernameButton - iconName: "username" - circle: true - checked: true - checkable: true - autoExclusive: true - } - Base.HButton { - id: loginWithEmailButton - iconName: "email" - circle: true - checkable: true - autoExclusive: true - } - Base.HButton { - id: loginWithPhoneButton - iconName: "phone" - circle: true - checkable: true - autoExclusive: true - } - } - - Base.HTextField { - id: identifierField - placeholderText: qsTr( - loginWithEmailButton.checked ? "Email" : - loginWithPhoneButton.checked ? "Phone" : - "Username" - ) - onAccepted: login() - Component.onCompleted: forceActiveFocus() - - Layout.fillWidth: true - Layout.margins: mainColumn.hMargin - Layout.topMargin: mainColumn.vMargin - Layout.bottomMargin: mainColumn.vMargin - } - - Base.HTextField { - id: passwordField - placeholderText: qsTr("Password") - echoMode: TextField.Password - onAccepted: login() - - Layout.fillWidth: true - Layout.margins: mainColumn.hMargin - Layout.topMargin: mainColumn.vMargin - Layout.bottomMargin: mainColumn.vMargin - } - - Item { Layout.fillHeight: true } - - Base.HRowLayout { - Base.HButton { - text: qsTr("Register") - Layout.fillWidth: true - Layout.preferredHeight: 32 - } - Base.HButton { - id: loginButton - text: qsTr("Login") - Layout.fillWidth: true - Layout.preferredHeight: 32 - - MouseArea { - anchors.fill: parent - onClicked: login() - } - } - Base.HButton { - text: qsTr("Forgot?") - Layout.fillWidth: true - Layout.preferredHeight: 32 - } - } - } - } -} diff --git a/harmonyqml/components/pages/LoginPage/LoginPage.qml b/harmonyqml/components/pages/LoginPage/LoginPage.qml new file mode 100644 index 00000000..fd6eef3c --- /dev/null +++ b/harmonyqml/components/pages/LoginPage/LoginPage.qml @@ -0,0 +1,17 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.4 +import "../../base" as Base + +Base.HImage { + id: loginPage + fillMode: Image.PreserveAspectCrop + source: "../../../images/login_background.jpg" + + Loader { + anchors.centerIn: parent + Component.onCompleted: setSource( + "SignInBox.qml", { "container": loginPage } + ) + } +} diff --git a/harmonyqml/components/pages/LoginPage/SignInBox.qml b/harmonyqml/components/pages/LoginPage/SignInBox.qml new file mode 100644 index 00000000..878fd40a --- /dev/null +++ b/harmonyqml/components/pages/LoginPage/SignInBox.qml @@ -0,0 +1,75 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.4 +import "../../base" as Base + +Base.HInterfaceBox { + id: signInBox + title: "Sign in" + + property string loginWith: "username" + + enterButtonTarget: "login" + + buttonModel: [ + { name: "register", text: qsTr("Register") }, + { name: "login", text: qsTr("Login") }, + { name: "forgot", text: qsTr("Forgot?") } + ] + + buttonCallbacks: { + "register": function(button) {}, + + "login": function(button) { + button.loadingUntilFutureDone( + Backend.clientManager.new( + "matrix.org", identifierField.text, passwordField.text + ) + ) + }, + + "forgot": function(button) {} + } + + Base.HRowLayout { + spacing: signInBox.margins * 1.25 + Layout.margins: signInBox.margins + Layout.alignment: Qt.AlignHCenter + + Repeater { + model: ["username", "email", "phone"] + + Base.HButton { + iconName: modelData + circle: true + checked: loginWith == modelData + autoExclusive: true + onClicked: loginWith = modelData + } + } + } + + Base.HTextField { + id: identifierField + placeholderText: qsTr( + loginWith === "email" ? "Email" : + loginWith === "phone" ? "Phone" : + "Username" + ) + onAccepted: signInBox.clickEnterButtonTarget() + Component.onCompleted: forceActiveFocus() + + Layout.fillWidth: true + Layout.margins: signInBox.margins + } + + Base.HTextField { + id: passwordField + placeholderText: qsTr("Password") + echoMode: TextField.Password + onAccepted: signInBox.clickEnterButtonTarget() + + Layout.fillWidth: true + Layout.margins: signInBox.margins + } +}