Refactor SignIn, adjustments to HCheckBox & HBox
This commit is contained in:
parent
150744ab8a
commit
7235611d54
3
src/icons/thin/sign-in.svg
Normal file
3
src/icons/thin/sign-in.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m16 2c3.309 0 6 2.691 6 6s-2.691 6-6 6-6-2.691-6-6 2.691-6 6-6zm0-2c-4.418 0-8 3.582-8 8s3.582 8 8 8 8-3.582 8-8-3.582-8-8-8zm-5.405 16.4-1.472 1.6h-3.123v2h-2v2h-2v-2.179l5.903-5.976c-.404-.559-.754-1.158-1.038-1.795l-6.865 6.95v5h6v-2h2v-2h2l2.451-2.663c-.655-.249-1.276-.562-1.856-.937zm7.405-11.4c.551 0 1 .449 1 1s-.449 1-1 1-1-.449-1-1 .449-1 1-1zm0-1c-1.104 0-2 .896-2 2s.896 2 2 2 2-.896 2-2-.896-2-2-2z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 519 B |
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" },
|
||||
|
|
|
@ -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"},
|
||||
|
|
15
src/qml/Pages/AddAccount/AddAccount.qml
Normal file
15
src/qml/Pages/AddAccount/AddAccount.qml
Normal file
|
@ -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
|
||||
}
|
||||
}
|
185
src/qml/Pages/AddAccount/SignIn.qml
Normal file
185
src/qml/Pages/AddAccount/SignIn.qml
Normal file
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -10,5 +10,4 @@ HCheckBox {
|
|||
qsTr("Cannot be disabled later!") +
|
||||
"</font>"
|
||||
subtitle.textFormat: Text.StyledText
|
||||
spacing: addChatBox.horizontalSpacing
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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" },
|
||||
]
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ Item {
|
|||
|
||||
Component.onCompleted: {
|
||||
if (! py.startupAnyAccountsSaved) {
|
||||
pageLoader.showPage("SignIn")
|
||||
pageLoader.showPage("AddAccount/AddAccount")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user