diff --git a/resources/qml/MatrixTextField.qml b/resources/qml/MatrixTextField.qml
index 655d53f1..05f2c82f 100644
--- a/resources/qml/MatrixTextField.qml
+++ b/resources/qml/MatrixTextField.qml
@@ -21,6 +21,14 @@ ColumnLayout {
property alias echoMode: input.echoMode
property alias selectByMouse: input.selectByMouse
+ Timer {
+ id: timer
+ interval: 350
+ onTriggered: editingFinished()
+ }
+
+ onTextChanged: timer.restart()
+
signal textEdited
signal accepted
signal editingFinished
diff --git a/resources/qml/QuickSwitcher.qml b/resources/qml/QuickSwitcher.qml
index 6d217c72..8747c47d 100644
--- a/resources/qml/QuickSwitcher.qml
+++ b/resources/qml/QuickSwitcher.qml
@@ -58,7 +58,7 @@ Popup {
id: completerPopup
x: roomTextInput.x
- y: roomTextInput.y + roomTextInput.height
+ y: roomTextInput.y + quickSwitcher.textHeight
visible: roomTextInput.length > 0
width: parent.width
completerName: "room"
diff --git a/resources/qml/Root.qml b/resources/qml/Root.qml
index f3976cc0..1969c613 100644
--- a/resources/qml/Root.qml
+++ b/resources/qml/Root.qml
@@ -395,6 +395,13 @@ Pane {
}
}
+ Component {
+ id: registerPage
+
+ RegistrationPage {
+ }
+ }
+
Connections {
function onSwitchToChatPage() {
mainWindow.replace(null, chatPage);
diff --git a/resources/qml/pages/LoginPage.qml b/resources/qml/pages/LoginPage.qml
index 0beb2bdc..4d3a52b3 100644
--- a/resources/qml/pages/LoginPage.qml
+++ b/resources/qml/pages/LoginPage.qml
@@ -1,3 +1,7 @@
+// SPDX-FileCopyrightText: 2022 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.2
@@ -9,7 +13,7 @@ import "../"
Item {
id: loginPage
- property int maxExpansion: 800
+ property int maxExpansion: 400
property string error: login.error
diff --git a/resources/qml/pages/RegistrationPage.qml b/resources/qml/pages/RegistrationPage.qml
new file mode 100644
index 00000000..44836ccb
--- /dev/null
+++ b/resources/qml/pages/RegistrationPage.qml
@@ -0,0 +1,215 @@
+// SPDX-FileCopyrightText: 2022 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.2
+import QtQuick.Window 2.15
+import im.nheko 1.0
+import "../components/"
+import "../ui/"
+import "../"
+
+Item {
+ id: registrationPage
+ property int maxExpansion: 400
+
+ property string error: regis.error
+
+ Registration {
+ id: regis
+ }
+
+ ScrollView {
+ id: scroll
+
+ clip: false
+ palette: Nheko.colors
+ ScrollBar.horizontal.visible: false
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ height: Math.min(registrationPage.height, col.implicitHeight)
+ anchors.margins: Nheko.paddingLarge
+
+ contentWidth: availableWidth
+
+ ColumnLayout {
+ id: col
+
+ spacing: Nheko.paddingMedium
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: Math.min(registrationPage.maxExpansion, scroll.width- Nheko.paddingLarge*2)
+
+ Image {
+ Layout.alignment: Qt.AlignHCenter
+ source: "qrc:/logos/login.png"
+ height: 128
+ width: 128
+ }
+
+ RowLayout {
+ spacing: Nheko.paddingLarge
+
+ Layout.fillWidth: true
+ MatrixTextField {
+ id: hsLabel
+ label: qsTr("Homeserver")
+ placeholderText: qsTr("your.server")
+ onEditingFinished: regis.setServer(text)
+
+ ToolTip.text: qsTr("A server that allows registration. Since matrix is decentralized, you need to first find a server you can register on or host your own.")
+ }
+
+
+ Spinner {
+ height: hsLabel.height/2
+ Layout.alignment: Qt.AlignBottom
+
+ visible: running
+ running: regis.lookingUpHs
+ foreground: Nheko.colors.mid
+ }
+ }
+
+ MatrixText {
+ textFormat: Text.PlainText
+ color: Nheko.theme.error
+ text: regis.hsError
+ visible: text
+ }
+
+ RowLayout {
+ spacing: Nheko.paddingLarge
+
+ visible: regis.supported
+
+ Layout.fillWidth: true
+ MatrixTextField {
+ id: usernameLabel
+ Layout.fillWidth: true
+ label: qsTr("Username")
+ ToolTip.text: qsTr("The username must not be empty, and must contain only the characters a-z, 0-9, ., _, =, -, and /.")
+ onEditingFinished: regis.checkUsername(text)
+ }
+ Spinner {
+ height: usernameLabel.height/2
+ Layout.alignment: Qt.AlignBottom
+
+ visible: running
+ running: regis.lookingUpUsername
+ foreground: Nheko.colors.mid
+ }
+
+ Image {
+ width: usernameLabel.height/2
+ height: width
+ Layout.preferredHeight: usernameLabel.height/2
+ Layout.preferredWidth: usernameLabel.height/2
+ Layout.alignment: Qt.AlignBottom
+ source: regis.usernameAvailable ? ("image://colorimage/:/icons/icons/ui/checkmark.svg?green") : ("image://colorimage/:/icons/icons/ui/dismiss.svg?"+Nheko.theme.error)
+ visible: regis.usernameAvailable || regis.usernameUnavailable
+ ToolTip.visible: ma.hovered
+ ToolTip.text: qsTr("Back")
+ sourceSize.height: height * Screen.devicePixelRatio
+ sourceSize.width: width * Screen.devicePixelRatio
+ HoverHandler {
+ id: ma
+ }
+ }
+ }
+
+ MatrixText {
+ textFormat: Text.PlainText
+ color: Nheko.theme.error
+ text: regis.usernameError
+ visible: text
+ }
+
+
+ MatrixTextField {
+ visible: regis.supported
+ id: passwordLabel
+ Layout.fillWidth: true
+ label: qsTr("Password")
+ echoMode: TextInput.Password
+ ToolTip.text: qsTr("Please choose a secure password. The exact requirements for password strength may depend on your server.")
+ }
+
+ MatrixTextField {
+ visible: regis.supported
+ id: passwordConfirmationLabel
+ Layout.fillWidth: true
+ label: qsTr("Password confirmation")
+ echoMode: TextInput.Password
+ }
+
+ MatrixText {
+ visible: regis.supported
+ textFormat: Text.PlainText
+ color: Nheko.theme.error
+ text: passwordLabel.text != passwordConfirmationLabel.text ? qsTr("Your passwords do not match!") : ""
+ }
+
+ MatrixTextField {
+ visible: regis.supported
+ id: deviceNameLabel
+ Layout.fillWidth: true
+ label: qsTr("Device name")
+ placeholderText: regis.initialDeviceName()
+ ToolTip.text: qsTr("A name for this device, which will be shown to others, when verifying your devices. If none is provided a default is used.")
+ }
+
+ Item {
+ height: Nheko.avatarSize
+ Layout.fillWidth: true
+
+ Spinner {
+ height: parent.height
+ anchors.centerIn: parent
+
+ visible: running
+ running: regis.registering
+ foreground: Nheko.colors.mid
+ }
+ }
+
+ MatrixText {
+ textFormat: Text.PlainText
+ color: Nheko.theme.error
+ text: registrationPage.error
+ visible: text
+ }
+
+ FlatButton {
+ id: regisBtn
+ visible: regis.supported
+ enabled: usernameLabel.text && passwordLabel.text && passwordLabel.text == passwordConfirmationLabel.text
+ Layout.alignment: Qt.AlignHCenter
+ text: qsTr("REGISTER")
+ function register() {
+ regis.startRegistration(usernameLabel.text, passwordLabel.text, deviceNameLabel.text)
+ }
+ onClicked: regisBtn.register()
+ Keys.onEnterPressed: regisBtn.register()
+ Keys.onReturnPressed: regisBtn.register()
+ Keys.enabled: regisBtn.enabled && regis.supported
+ }
+ }
+ }
+
+ ImageButton {
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.margins: Nheko.paddingMedium
+ width: Nheko.avatarSize
+ height: Nheko.avatarSize
+ image: ":/icons/icons/ui/angle-arrow-left.svg"
+ ToolTip.visible: hovered
+ ToolTip.text: qsTr("Back")
+ onClicked: mainWindow.pop()
+ }
+}
+
diff --git a/resources/qml/pages/WelcomePage.qml b/resources/qml/pages/WelcomePage.qml
index 43050d8e..627d8b1c 100644
--- a/resources/qml/pages/WelcomePage.qml
+++ b/resources/qml/pages/WelcomePage.qml
@@ -48,6 +48,7 @@ ColumnLayout {
Layout.alignment: Qt.AlignHCenter
text: qsTr("REGISTER")
onClicked: {
+ mainWindow.push(registerPage);
}
}
FlatButton {
|