Refactor LoginPage into separate components
This commit is contained in:
parent
102baccbe5
commit
e09efaecda
3
TODO.md
3
TODO.md
|
@ -1,6 +1,7 @@
|
||||||
- Current focus
|
- Current focus
|
||||||
- Merge login page
|
- Remember account dialog
|
||||||
- Just import nio?
|
- Just import nio?
|
||||||
|
- Use new H\* components everywhere
|
||||||
- TextInput.accepted() for SendBox
|
- TextInput.accepted() for SendBox
|
||||||
|
|
||||||
- Refactoring
|
- Refactoring
|
||||||
|
|
|
@ -10,7 +10,7 @@ ApplicationWindow {
|
||||||
Loader {
|
Loader {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
source: Backend.clientManager.clientCount < 1 ?
|
source: Backend.clientManager.clientCount < 1 ?
|
||||||
"pages/LoginPage.qml" : "pages/MainUI.qml"
|
"pages/LoginPage/LoginPage.qml" : "pages/MainUI.qml"
|
||||||
objectName: "UILoader"
|
objectName: "UILoader"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,15 @@ Button {
|
||||||
|
|
||||||
property int contentWidth: 0
|
property int contentWidth: 0
|
||||||
|
|
||||||
|
signal canceled
|
||||||
|
signal clicked
|
||||||
|
signal doubleClicked
|
||||||
|
signal entered
|
||||||
|
signal exited
|
||||||
|
signal pressAndHold
|
||||||
|
signal pressed
|
||||||
|
signal released
|
||||||
|
|
||||||
function loadingUntilFutureDone(future) {
|
function loadingUntilFutureDone(future) {
|
||||||
loading = true
|
loading = true
|
||||||
future.onGotResult.connect(function() { loading = false })
|
future.onGotResult.connect(function() { loading = false })
|
||||||
|
@ -75,17 +84,29 @@ Button {
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
z: 101
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
propagateComposedEvents: true
|
|
||||||
|
|
||||||
onEntered: overlayOpacity = checked ? 0 : 0.3
|
onCanceled: button.canceled()
|
||||||
onExited: overlayOpacity = 0
|
onClicked: button.clicked()
|
||||||
onPressed: overlayOpacity += 0.3
|
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: {
|
onReleased: {
|
||||||
if (checkable) { checked = ! checked }
|
if (checkable) { checked = ! checked }
|
||||||
overlayOpacity = checked ? 0 : 0.3
|
overlayOpacity = checked ? 0 : 0.3
|
||||||
|
button.released()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
57
harmonyqml/components/base/HInterfaceBox.qml
Normal file
57
harmonyqml/components/base/HInterfaceBox.qml
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
harmonyqml/components/base/HScalingBox.qml
Normal file
17
harmonyqml/components/base/HScalingBox.qml
Normal file
|
@ -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)
|
||||||
|
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
17
harmonyqml/components/pages/LoginPage/LoginPage.qml
Normal file
17
harmonyqml/components/pages/LoginPage/LoginPage.qml
Normal file
|
@ -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 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
75
harmonyqml/components/pages/LoginPage/SignInBox.qml
Normal file
75
harmonyqml/components/pages/LoginPage/SignInBox.qml
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user