status-desktop/ui/onboarding/Login.qml

273 lines
8.3 KiB
QML

import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import QtQuick.Dialogs 1.3
import QtGraphicalEffects 1.13
import "../shared"
import "../shared/status"
import utils 1.0
import "./Login"
Item {
property var onGenKeyClicked: function () {}
property var onExistingKeyClicked: function () {}
property bool loading: false
id: loginView
anchors.fill: parent
function setCurrentFlow(isLogin) {
loginModel.isCurrentFlow = isLogin;
onboardingModel.isCurrentFlow = !isLogin;
}
function doLogin(password) {
if (loading || password.length === 0)
return
setCurrentFlow(true);
loading = true
loginModel.login(password)
applicationWindow.checkForStoringPassToKeychain(loginModel.currentAccount.username, password, false)
txtPassword.textField.clear()
}
function resetLogin() {
if(accountSettings.storeToKeychain === Constants.storeToKeychainValueStore)
{
connection.enabled = true
txtPassword.visible = false
loginModel.tryToObtainPassword()
}
else
{
txtPassword.visible = true
txtPassword.forceActiveFocus(Qt.MouseFocusReason)
}
}
Component.onCompleted: {
resetLogin()
}
Connections{
id: connection
target: loginModel
onObtainingPasswordError: {
enabled = false
obtainingPasswordErrorNotification.confirmationText = errorDescription
obtainingPasswordErrorNotification.open()
}
onObtainingPasswordSuccess: {
enabled = false
doLogin(password)
}
}
ConfirmationDialog {
id: obtainingPasswordErrorNotification
height: 270
confirmButtonLabel: qsTr("Ok")
onConfirmButtonClicked: {
close()
}
onClosed: {
txtPassword.visible = true
}
}
Item {
id: element
width: 360
height: 200
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
StatusImageIdenticon {
id: userImage
anchors.horizontalCenter: parent.horizontalCenter
source: loginModel.currentAccount.thumbnailImage
}
StyledText {
id: usernameText
text: loginModel.currentAccount.username
font.weight: Font.Bold
font.pixelSize: 17
anchors.top: userImage.bottom
anchors.topMargin: 4
anchors.horizontalCenter: parent.horizontalCenter
}
ConfirmAddExistingKeyModal {
id: confirmAddExstingKeyModal
onOpenModalClick: function () {
setCurrentFlow(false);
onExistingKeyClicked()
}
}
SelectAnotherAccountModal {
id: selectAnotherAccountModal
onAccountSelect: function (index) {
loginModel.setCurrentAccount(index)
resetLogin()
}
onOpenModalClick: function () {
setCurrentFlow(true);
onExistingKeyClicked()
}
}
Rectangle {
property bool isHovered: false
id: changeAccountBtn
width: 24
height: 24
anchors.left: usernameText.right
anchors.leftMargin: 4
anchors.verticalCenter: usernameText.verticalCenter
color: isHovered ? Style.current.backgroundHover : Style.current.transparent
radius: 4
SVGImage {
id: caretImg
width: 10
height: 6
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
source: Style.svg("caret")
fillMode: Image.PreserveAspectFit
}
ColorOverlay {
anchors.fill: caretImg
source: caretImg
color: Style.current.secondaryText
}
MouseArea {
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onEntered: {
changeAccountBtn.isHovered = true
}
onExited: {
changeAccountBtn.isHovered = false
}
onClicked: {
if (loginModel.rowCount() > 1) {
selectAnotherAccountModal.open()
} else {
confirmAddExstingKeyModal.open()
}
}
}
}
Input {
id: txtPassword
anchors.top: changeAccountBtn.bottom
anchors.topMargin: Style.current.padding * 2
enabled: !loading
placeholderText: loading ?
//% "Connecting..."
qsTrId("connecting") :
//% "Enter password"
qsTrId("enter-password")
textField.echoMode: TextInput.Password
textField.focus: true
Keys.onReturnPressed: {
doLogin(textField.text)
}
onTextEdited: {
errMsg.visible = false
loading = false
}
}
StatusRoundButton {
id: submitBtn
size: "medium"
type: "secondary"
icon.name: "arrow-right"
icon.width: 18
icon.height: 14
opacity: (loading || txtPassword.text.length > 0) ? 1 : 0
anchors.left: txtPassword.visible? txtPassword.right : changeAccountBtn.right
anchors.leftMargin: (loading || txtPassword.text.length > 0) ? Style.current.padding : Style.current.smallPadding
anchors.verticalCenter: txtPassword.visible? txtPassword.verticalCenter : changeAccountBtn.verticalCenter
state: loading ? "pending" : "default"
onClicked: {
doLogin(txtPassword.textField.text)
}
// https://www.figma.com/file/BTS422M9AkvWjfRrXED3WC/%F0%9F%91%8B-Onboarding%E2%8E%9CDesktop?node-id=6%3A0
Behavior on opacity {
OpacityAnimator {
from: 0.5
duration: 200
}
}
Behavior on anchors.leftMargin {
NumberAnimation {
duration: 200
}
}
}
Connections {
target: loginModel
ignoreUnknownSignals: true
onLoginResponseChanged: {
if (error) {
// SQLITE_NOTADB: "file is not a database"
if (error === "file is not a database") {
errMsg.text = errMsg.incorrectPasswordMsg
} else {
//% "Login failed: %1"
errMsg.text = qsTrId("login-failed---1").arg(error.toUpperCase())
}
errMsg.visible = true
loading = false
txtPassword.textField.forceActiveFocus()
}
}
}
StatusButton {
id: generateKeysLinkText
//% "Generate new keys"
text: qsTrId("generate-new-keys")
anchors.top: txtPassword.visible? txtPassword.bottom : changeAccountBtn.bottom
anchors.topMargin: 16
anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: 13
type: "secondary"
onClicked: {
setCurrentFlow(false);
onGenKeyClicked()
}
}
StyledText {
id: errMsg
//% "Login failed. Please re-enter your password and try again."
readonly property string incorrectPasswordMsg: qsTrId("login-failed--please-re-enter-your-password-and-try-again-")
anchors.top: generateKeysLinkText.bottom
anchors.topMargin: Style.current.smallPadding
anchors.horizontalCenter: parent.horizontalCenter
visible: false
text: incorrectPasswordMsg
font.pixelSize: 13
color: Style.current.danger
}
}
}