Port login to FormCard
This commit is contained in:
@@ -87,7 +87,11 @@ void Login::init()
|
||||
Q_EMIT isLoggingInChanged();
|
||||
});
|
||||
connect(m_connection, &Connection::loginError, this, [this](QString error, const QString &) {
|
||||
Q_EMIT errorOccured(i18n("Login Failed: %1", error));
|
||||
if (error == QStringLiteral("Invalid username or password")) {
|
||||
setInvalidPassword(true);
|
||||
} else {
|
||||
Q_EMIT errorOccured(i18n("Login Failed: %1", error));
|
||||
}
|
||||
m_isLoggingIn = false;
|
||||
Q_EMIT isLoggingInChanged();
|
||||
});
|
||||
@@ -133,6 +137,7 @@ QString Login::password() const
|
||||
|
||||
void Login::setPassword(const QString &password)
|
||||
{
|
||||
setInvalidPassword(false);
|
||||
m_password = password;
|
||||
Q_EMIT passwordChanged();
|
||||
}
|
||||
@@ -199,4 +204,15 @@ bool Login::isLoggedIn() const
|
||||
return m_isLoggedIn;
|
||||
}
|
||||
|
||||
void Login::setInvalidPassword(bool invalid)
|
||||
{
|
||||
m_invalidPassword = invalid;
|
||||
Q_EMIT isInvalidPasswordChanged();
|
||||
}
|
||||
|
||||
bool Login::isInvalidPassword() const
|
||||
{
|
||||
return m_invalidPassword;
|
||||
}
|
||||
|
||||
#include "moc_login.cpp"
|
||||
|
||||
10
src/login.h
10
src/login.h
@@ -73,6 +73,11 @@ class Login : public QObject
|
||||
*/
|
||||
Q_PROPERTY(bool isLoggedIn READ isLoggedIn NOTIFY isLoggedInChanged)
|
||||
|
||||
/**
|
||||
* @brief Whether the password (or the username) is invalid.
|
||||
*/
|
||||
Q_PROPERTY(bool isInvalidPassword READ isInvalidPassword NOTIFY isInvalidPasswordChanged)
|
||||
|
||||
public:
|
||||
explicit Login(QObject *parent = nullptr);
|
||||
|
||||
@@ -100,6 +105,9 @@ public:
|
||||
|
||||
bool isLoggedIn() const;
|
||||
|
||||
bool isInvalidPassword() const;
|
||||
void setInvalidPassword(bool invalid);
|
||||
|
||||
Q_INVOKABLE void login();
|
||||
Q_INVOKABLE void loginWithSso();
|
||||
|
||||
@@ -116,6 +124,7 @@ Q_SIGNALS:
|
||||
void testingChanged();
|
||||
void isLoggingInChanged();
|
||||
void isLoggedInChanged();
|
||||
void isInvalidPasswordChanged();
|
||||
|
||||
private:
|
||||
void setHomeserverReachable(bool reachable);
|
||||
@@ -131,4 +140,5 @@ private:
|
||||
bool m_testing = false;
|
||||
bool m_isLoggingIn = false;
|
||||
bool m_isLoggedIn = false;
|
||||
bool m_invalidPassword = false;
|
||||
};
|
||||
|
||||
@@ -6,16 +6,19 @@ import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard 1.0 as FormCard
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
Kirigami.LoadingPlaceholder {
|
||||
property var showContinueButton: false
|
||||
property var showBackButton: false
|
||||
|
||||
QQC2.Label {
|
||||
LoginStep {
|
||||
id: root
|
||||
FormCard.FormTextDelegate {
|
||||
text: i18n("Please wait. This might take a little while.")
|
||||
}
|
||||
FormCard.AbstractFormDelegate {
|
||||
contentItem: QQC2.BusyIndicator {}
|
||||
background: null
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Controller
|
||||
|
||||
@@ -7,43 +7,34 @@ import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.15 as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard 1.0 as FormCard
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
LoginStep {
|
||||
id: login
|
||||
id: root
|
||||
|
||||
showContinueButton: true
|
||||
showBackButton: false
|
||||
|
||||
title: i18nc("@title", "Login")
|
||||
message: i18n("Enter your Matrix ID")
|
||||
onActiveFocusChanged: if (activeFocus) matrixIdField.forceActiveFocus()
|
||||
|
||||
Component.onCompleted: {
|
||||
LoginHelper.matrixId = ""
|
||||
}
|
||||
|
||||
Kirigami.FormLayout {
|
||||
QQC2.TextField {
|
||||
id: matrixIdField
|
||||
Kirigami.FormData.label: i18n("Matrix ID:")
|
||||
placeholderText: "@user:matrix.org"
|
||||
Accessible.name: i18n("Matrix ID")
|
||||
onTextChanged: {
|
||||
LoginHelper.matrixId = text
|
||||
}
|
||||
FormCard.FormTextFieldDelegate {
|
||||
id: matrixIdField
|
||||
label: i18n("Matrix ID:")
|
||||
placeholderText: "@user:example.org"
|
||||
Accessible.name: i18n("Matrix ID")
|
||||
onTextChanged: {
|
||||
LoginHelper.matrixId = text
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
matrixIdField.forceActiveFocus()
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
login.action.trigger()
|
||||
}
|
||||
Keys.onReturnPressed: {
|
||||
root.action.trigger()
|
||||
}
|
||||
}
|
||||
|
||||
action: Kirigami.Action {
|
||||
nextAction: Kirigami.Action {
|
||||
text: LoginHelper.isLoggedIn ? i18n("Already logged in") : (LoginHelper.testing && matrixIdField.acceptableInput) ? i18n("Loading…") : i18nc("@action:button", "Continue")
|
||||
onTriggered: {
|
||||
if (LoginHelper.supportsSso && LoginHelper.supportsPassword) {
|
||||
@@ -56,4 +47,10 @@ LoginStep {
|
||||
}
|
||||
enabled: LoginHelper.homeserverReachable
|
||||
}
|
||||
// TODO: enable once we have registration
|
||||
// previousAction: Kirigami.Action {
|
||||
// onTriggered: {
|
||||
// root.processed("qrc:/Login.qml")
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -4,28 +4,26 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.15 as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard 1.0 as FormCard
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
LoginStep {
|
||||
id: loginMethod
|
||||
id: root
|
||||
|
||||
title: i18n("Login Methods")
|
||||
onActiveFocusChanged: if (activeFocus) loginPasswordButton.forceActiveFocus()
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
QQC2.Button {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: i18n("Login with password")
|
||||
Layout.preferredWidth: Kirigami.Units.gridUnit * 12
|
||||
FormCard.FormButtonDelegate {
|
||||
id: loginPasswordButton
|
||||
text: i18nc("@action:button", "Login with password")
|
||||
onClicked: processed("qrc:/Password.qml")
|
||||
}
|
||||
|
||||
QQC2.Button {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: i18n("Login with single sign-on")
|
||||
Layout.preferredWidth: Kirigami.Units.gridUnit * 12
|
||||
FormCard.FormButtonDelegate {
|
||||
id: loginSsoButton
|
||||
text: i18nc("@action:button", "Login with single sign-on")
|
||||
onClicked: processed("qrc:/Sso.qml")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,25 +6,22 @@ import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.15 as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard 1.0 as FormCard
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
LoginStep {
|
||||
id: loginRegister
|
||||
id: root
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
|
||||
QQC2.Button {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: i18n("Login")
|
||||
Layout.preferredWidth: Kirigami.Units.gridUnit * 12
|
||||
onClicked: processed("qrc:/Login.qml")
|
||||
FormCard.FormButtonDelegate {
|
||||
text: i18nc("@action:button", "Login")
|
||||
onClicked: root.processed("qrc:/Login.qml")
|
||||
}
|
||||
|
||||
QQC2.Button {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: i18n("Register")
|
||||
Layout.preferredWidth: Kirigami.Units.gridUnit * 12
|
||||
onClicked: processed("qrc:/Homeserver.qml")
|
||||
FormCard.FormButtonDelegate {
|
||||
text: i18nc("@action:button", "Register")
|
||||
onClicked: root.processed("qrc:/Homeserver.qml")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,21 +7,25 @@ import QtQuick.Layouts 1.14
|
||||
|
||||
/// Step for the login/registration flow
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
property string title: i18n("Welcome")
|
||||
property string message: i18n("Welcome")
|
||||
property bool showContinueButton: false
|
||||
property bool showBackButton: false
|
||||
property bool acceptable: false
|
||||
property string previousUrl: ""
|
||||
/// Set to true if the login step does not have any controls. This will ensure that the focus remains on the "continue" button
|
||||
property bool noControls: false
|
||||
|
||||
/// Process this module, this is called by the continue button.
|
||||
/// Should call \sa processed when it finish successfully.
|
||||
property QQC2.Action action: null
|
||||
property QQC2.Action nextAction: null
|
||||
|
||||
/// Go to the previous module. This is called by the "go back" button.
|
||||
/// If no "go back" button should be shown, this should be null.
|
||||
property QQC2.Action previousAction: null
|
||||
|
||||
/// Called when switching to the next step.
|
||||
signal processed(url nextUrl)
|
||||
|
||||
/// Show a message in a banner at the top of the page.
|
||||
signal showMessage(string message)
|
||||
|
||||
signal clearError()
|
||||
|
||||
}
|
||||
|
||||
@@ -6,25 +6,12 @@ import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.15 as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard 1.0 as FormCard
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
LoginStep {
|
||||
id: password
|
||||
|
||||
title: i18nc("@title", "Password")
|
||||
message: i18n("Enter your password")
|
||||
showContinueButton: true
|
||||
showBackButton: true
|
||||
previousUrl: LoginHelper.isLoggingIn ? "" : LoginHelper.supportsSso ? "qrc:/LoginMethod.qml" : "qrc:/Login.qml"
|
||||
|
||||
action: Kirigami.Action {
|
||||
text: i18nc("@action:button", "Login")
|
||||
enabled: passwordField.text.length > 0 && !LoginHelper.isLoggingIn
|
||||
onTriggered: {
|
||||
LoginHelper.login();
|
||||
}
|
||||
}
|
||||
id: root
|
||||
|
||||
Connections {
|
||||
target: LoginHelper
|
||||
@@ -33,20 +20,32 @@ LoginStep {
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.FormLayout {
|
||||
Kirigami.PasswordField {
|
||||
id: passwordField
|
||||
onTextChanged: LoginHelper.password = text
|
||||
enabled: !LoginHelper.isLoggingIn
|
||||
Accessible.name: i18n("Password")
|
||||
onActiveFocusChanged: if(activeFocus) passwordField.forceActiveFocus()
|
||||
|
||||
Component.onCompleted: {
|
||||
passwordField.forceActiveFocus()
|
||||
}
|
||||
FormCard.FormTextFieldDelegate {
|
||||
id: passwordField
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
password.action.trigger()
|
||||
}
|
||||
label: i18n("Password:")
|
||||
onTextChanged: LoginHelper.password = text
|
||||
enabled: !LoginHelper.isLoggingIn
|
||||
echoMode: TextInput.Password
|
||||
Accessible.name: i18n("Password")
|
||||
statusMessage: LoginHelper.isInvalidPassword ? i18n("Invalid username or password") : ""
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
root.action.trigger()
|
||||
}
|
||||
}
|
||||
|
||||
nextAction: Kirigami.Action {
|
||||
text: i18nc("@action:button", "Login")
|
||||
enabled: passwordField.text.length > 0 && !LoginHelper.isLoggingIn
|
||||
onTriggered: {
|
||||
root.clearError()
|
||||
LoginHelper.login();
|
||||
}
|
||||
}
|
||||
previousAction: Kirigami.Action {
|
||||
onTriggered: processed("qrc:/Login.qml")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,47 +6,38 @@ import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.12 as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard 1.0 as FormCard
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
LoginStep {
|
||||
id: root
|
||||
|
||||
title: i18nc("@title", "Login")
|
||||
message: i18n("Login with single sign-on")
|
||||
noControls: true
|
||||
|
||||
Kirigami.FormLayout {
|
||||
Connections {
|
||||
target: LoginHelper
|
||||
function onSsoUrlChanged() {
|
||||
UrlHelper.openUrl(LoginHelper.ssoUrl)
|
||||
root.showMessage(i18n("Complete the authentication steps in your browser"))
|
||||
loginButton.enabled = true
|
||||
loginButton.text = i18n("Login")
|
||||
}
|
||||
function onConnected() {
|
||||
processed("qrc:/Loading.qml")
|
||||
}
|
||||
Component.onCompleted: LoginHelper.loginWithSso()
|
||||
|
||||
Connections {
|
||||
target: LoginHelper
|
||||
function onSsoUrlChanged() {
|
||||
UrlHelper.openUrl(LoginHelper.ssoUrl)
|
||||
}
|
||||
RowLayout {
|
||||
QQC2.Button {
|
||||
text: i18nc("@action:button", "Back")
|
||||
|
||||
onClicked: {
|
||||
module.source = "qrc:/Login.qml"
|
||||
}
|
||||
}
|
||||
QQC2.Button {
|
||||
id: loginButton
|
||||
text: i18n("Login")
|
||||
onClicked: {
|
||||
LoginHelper.loginWithSso()
|
||||
loginButton.enabled = false
|
||||
loginButton.text = i18n("Loading…")
|
||||
}
|
||||
Component.onCompleted: forceActiveFocus()
|
||||
Keys.onReturnPressed: clicked()
|
||||
}
|
||||
function onConnected() {
|
||||
processed("qrc:/Loading.qml")
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormTextDelegate {
|
||||
text: i18n("Continue the login process in your browser.")
|
||||
}
|
||||
|
||||
previousAction: Kirigami.Action {
|
||||
onTriggered: processed("qrc:/Login.qml")
|
||||
}
|
||||
|
||||
nextAction: Kirigami.Action {
|
||||
text: i18nc("@action:button", "Re-open SSO URL")
|
||||
onTriggered: UrlHelper.openUrl(LoginHelper.ssoUrl)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,15 +6,16 @@ import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.15 as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard 1.0 as FormCard
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
Kirigami.ScrollablePage {
|
||||
id: welcomePage
|
||||
FormCard.FormCardPage {
|
||||
id: root
|
||||
|
||||
property alias currentStep: module.item
|
||||
|
||||
title: module.item.title ?? i18n("Welcome")
|
||||
title: i18n("Welcome")
|
||||
|
||||
header: QQC2.Control {
|
||||
contentItem: Kirigami.InlineMessage {
|
||||
@@ -25,79 +26,90 @@ Kirigami.ScrollablePage {
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: LoginHelper.init()
|
||||
FormCard.FormCard {
|
||||
id: contentCard
|
||||
|
||||
Connections {
|
||||
target: LoginHelper
|
||||
function onErrorOccured(message) {
|
||||
headerMessage.text = message;
|
||||
headerMessage.visible = true;
|
||||
headerMessage.type = Kirigami.MessageType.Error;
|
||||
FormCard.AbstractFormDelegate {
|
||||
contentItem: Kirigami.Icon {
|
||||
source: "org.kde.neochat"
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 16
|
||||
}
|
||||
background: Item {}
|
||||
onActiveFocusChanged: if (activeFocus) module.item.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Controller
|
||||
function onInitiated() {
|
||||
pageStack.layers.pop();
|
||||
FormCard.FormTextDelegate {
|
||||
id: welcomeMessage
|
||||
text: AccountRegistry.accountCount > 0 ? i18n("Log in to a different account.") : i18n("Welcome to NeoChat! Continue by logging in.")
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Kirigami.Icon {
|
||||
source: "org.kde.neochat"
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 16
|
||||
}
|
||||
QQC2.Label {
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 25
|
||||
text: module.item.message ?? module.item.title ?? i18n("Welcome to Matrix")
|
||||
FormCard.FormDelegateSeparator {
|
||||
above: welcomeMessage
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: module
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
source: "qrc:/Login.qml"
|
||||
onSourceChanged: {
|
||||
headerMessage.visible = false
|
||||
headerMessage.text = ""
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
QQC2.Button {
|
||||
text: i18nc("@action:button", "Back")
|
||||
Connections {
|
||||
target: currentStep
|
||||
|
||||
enabled: welcomePage.currentStep.previousUrl !== ""
|
||||
visible: welcomePage.currentStep.showBackButton
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
onClicked: {
|
||||
module.source = welcomePage.currentStep.previousUrl
|
||||
function onProcessed(nextUrl) {
|
||||
module.source = nextUrl;
|
||||
headerMessage.text = "";
|
||||
headerMessage.visible = false;
|
||||
if (!module.item.noControls) {
|
||||
module.item.forceActiveFocus()
|
||||
} else {
|
||||
continueButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
function onShowMessage(message) {
|
||||
headerMessage.text = message;
|
||||
headerMessage.visible = true;
|
||||
headerMessage.type = Kirigami.MessageType.Information;
|
||||
}
|
||||
function onClearError() {
|
||||
headerMessage.text = "";
|
||||
headerMessage.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.Button {
|
||||
id: continueButton
|
||||
enabled: welcomePage.currentStep.acceptable
|
||||
visible: welcomePage.currentStep.showContinueButton
|
||||
action: welcomePage.currentStep.action
|
||||
Connections {
|
||||
target: LoginHelper
|
||||
function onErrorOccured(message) {
|
||||
headerMessage.text = message;
|
||||
headerMessage.visible = message.length > 0;
|
||||
headerMessage.type = Kirigami.MessageType.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: currentStep
|
||||
FormCard.FormDelegateSeparator {
|
||||
below: continueButton
|
||||
}
|
||||
|
||||
function onProcessed(nextUrl) {
|
||||
module.source = nextUrl;
|
||||
}
|
||||
function onShowMessage(message) {
|
||||
headerMessage.text = message;
|
||||
headerMessage.visible = true;
|
||||
headerMessage.type = Kirigami.MessageType.Information;
|
||||
}
|
||||
FormCard.FormButtonDelegate {
|
||||
id: continueButton
|
||||
text: root.currentStep.nextAction ? root.currentStep.nextAction.text : i18nc("@action:button", "Continue")
|
||||
visible: root.currentStep.nextAction
|
||||
onClicked: root.currentStep.nextAction.trigger()
|
||||
icon.name: "arrow-right"
|
||||
enabled: root.currentStep.nextAction ? root.currentStep.nextAction.enabled : false
|
||||
}
|
||||
|
||||
FormCard.FormButtonDelegate {
|
||||
text: i18nc("@action:button", "Go back")
|
||||
visible: root.currentStep.previousAction
|
||||
onClicked: root.currentStep.previousAction.trigger()
|
||||
icon.name: "arrow-left"
|
||||
enabled: root.currentStep.previousAction ? root.currentStep.previousAction.enabled : false
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
LoginHelper.init()
|
||||
module.item.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user