status-desktop/ui/app/AppLayouts/Onboarding/views/LoginView.qml

300 lines
8.9 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 StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1 as StatusQControls
import StatusQ.Popups 0.1
import shared.panels 1.0
import shared.popups 1.0
import shared.status 1.0
import shared.controls 1.0
import shared.controls.chat 1.0
import "../panels"
import "../popups"
import "../stores"
import utils 1.0
Item {
property bool loading: false
signal addNewUserClicked()
signal addExistingKeyClicked()
id: loginView
anchors.fill: parent
function doLogin(password) {
if (loading || password.length === 0)
return
loading = true
LoginStore.login(password)
txtPassword.textField.clear()
}
function resetLogin() {
if(localAccountSettings.storeToKeychainValue === Constants.storeToKeychainValueStore)
{
connection.enabled = true
}
else
{
txtPassword.visible = true
txtPassword.forceActiveFocus(Qt.MouseFocusReason)
}
}
Component.onCompleted: {
resetLogin()
}
Connections{
id: connection
target: LoginStore.loginModuleInst
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: childrenRect.height
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
Image {
id: statusIcon
width: 140
height: 140
fillMode: Image.PreserveAspectFit
source: Style.png("status-logo")
anchors.horizontalCenter: parent.horizontalCenter
}
StatusBaseText {
id: welcomeBackText
text: qsTr("Welcome back")
font.weight: Font.Bold
font.pixelSize: 17
anchors.top: statusIcon.bottom
anchors.topMargin: 10
anchors.horizontalCenter: parent.horizontalCenter
color: Theme.palette.directColor1
}
ConfirmAddExistingKeyModal {
id: confirmAddExstingKeyModal
onOpenModalClicked: {
addExistingKeyClicked()
}
}
SelectAnotherAccountModal {
id: selectAnotherAccountModal
onAccountSelected: {
LoginStore.setCurrentAccount(index)
resetLogin()
}
onOpenModalClicked: {
addExistingKeyClicked()
}
}
Item {
id: userInfo
height: userImage.height
anchors.top: welcomeBackText.bottom
anchors.topMargin: 64
width: 318
anchors.horizontalCenter: parent.horizontalCenter
UserImage {
id: userImage
image: LoginStore.currentAccount.thumbnailImage
name: LoginStore.currentAccount.username
colorId: LoginStore.currentAccount.colorId
colorHash: LoginStore.currentAccount.colorHash
anchors.left: parent.left
}
StatusBaseText {
id: usernameText
text: LoginStore.currentAccount.username
font.pixelSize: 17
anchors.left: userImage.right
anchors.leftMargin: 16
anchors.verticalCenter: userImage.verticalCenter
color: Theme.palette.directColor1
}
StatusQControls.StatusFlatRoundButton {
icon.name: "chevron-down"
type: StatusQControls.StatusFlatRoundButton.Type.Tertiary
width: 24
height: 24
id: changeAccountBtn
anchors.verticalCenter: usernameText.verticalCenter
anchors.right: parent.right
onClicked: {
if (accountsPopup.opened) {
accountsPopup.close()
} else {
accountsPopup.popup(width-userInfo.width-16, userInfo.height+4)
}
}
StatusPopupMenu {
id: accountsPopup
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
width: 346
dim: false
Repeater {
id: accounts
model: LoginStore.loginModuleInst.accountsModel
delegate: AccountMenuItemPanel {
label: model.username
image: model.thumbnailImage
colorId: model.colorId
colorHash: model.colorHash
onClicked: {
LoginStore.setCurrentAccount(index)
resetLogin()
accountsPopup.close()
}
}
}
AccountMenuItemPanel {
label: qsTr("Add new user")
onClicked: {
accountsPopup.close()
addNewUserClicked();
}
}
AccountMenuItemPanel {
label: qsTr("Add existing Status user")
iconSettings.name: "wallet"
onClicked: {
accountsPopup.close()
addExistingKeyClicked();
}
}
}
}
}
Input {
id: txtPassword
anchors.top: userInfo.bottom
anchors.topMargin: Style.current.padding * 2
anchors.left: undefined
anchors.right: undefined
anchors.horizontalCenter: parent.horizontalCenter
width: 318
enabled: !loading
placeholderText: loading ?
qsTr("Connecting...") :
qsTr("Password")
textField.echoMode: TextInput.Password
Keys.onReturnPressed: {
doLogin(textField.text)
}
onTextEdited: {
errMsg.visible = false
loading = false
}
}
StatusQControls.StatusRoundButton {
id: submitBtn
width: 40
height: 40
type: StatusQControls.StatusRoundButton.Type.Secondary
icon.name: "arrow-right"
opacity: (loading || txtPassword.text.length > 0) ? 1 : 0
anchors.left: txtPassword.right
anchors.leftMargin: (loading || txtPassword.text.length > 0) ? Style.current.padding : Style.current.smallPadding
anchors.verticalCenter: txtPassword.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: LoginStore.loginModuleInst
onAccountLoginError: {
if (error) {
// SQLITE_NOTADB: "file is not a database"
if (error === "file is not a database") {
errMsg.text = errMsg.incorrectPasswordMsg
} else {
errMsg.text = qsTr("Login failed: %1").arg(error.toUpperCase())
}
errMsg.visible = true
loading = false
txtPassword.textField.forceActiveFocus()
}
}
}
StyledText {
id: errMsg
readonly property string incorrectPasswordMsg: qsTr("Password incorrect")
anchors.top: txtPassword.bottom
anchors.topMargin: Style.current.padding
anchors.horizontalCenter: parent.horizontalCenter
visible: false
text: incorrectPasswordMsg
font.pixelSize: 13
color: Style.current.danger
}
}
}