You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
464 lines
15 KiB
464 lines
15 KiB
// Copyright (c) 2021 Proton Technologies AG |
|
// |
|
// This file is part of ProtonMail Bridge. |
|
// |
|
// ProtonMail Bridge is free software: you can redistribute it and/or modify |
|
// it under the terms of the GNU General Public License as published by |
|
// the Free Software Foundation, either version 3 of the License, or |
|
// (at your option) any later version. |
|
// |
|
// ProtonMail Bridge is distributed in the hope that it will be useful, |
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
// GNU General Public License for more details. |
|
// |
|
// You should have received a copy of the GNU General Public License |
|
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>. |
|
|
|
// Dialog with adding new user |
|
|
|
import QtQuick 2.8 |
|
import ProtonUI 1.0 |
|
|
|
|
|
Dialog { |
|
id: root |
|
|
|
title : "" |
|
|
|
signal createAccount() |
|
|
|
property alias inputPassword : inputPassword |
|
property alias input2FAuth : input2FAuth |
|
property alias inputPasswMailbox : inputPasswMailbox |
|
// |
|
property alias username : inputUsername.text |
|
property alias usernameElided : usernameMetrics.elidedText |
|
|
|
isDialogBusy : currentIndex==waitingAuthIndex || currentIndex==addingAccIndex |
|
|
|
property bool isFirstAccount: false |
|
|
|
property color buttonOpaqueMain : "white" |
|
|
|
|
|
property int origin: 0 |
|
property int nameAndPasswordIndex : 0 |
|
property int waitingAuthIndex : 2 |
|
property int twoFAIndex : 1 |
|
property int mailboxIndex : 3 |
|
property int addingAccIndex : 4 |
|
property int newAccountIndex : 5 |
|
|
|
|
|
signal cancel() |
|
signal okay() |
|
|
|
TextMetrics { |
|
id: usernameMetrics |
|
font: dialogWaitingAuthText.font |
|
elideWidth : Style.dialog.widthInput |
|
elide : Qt.ElideMiddle |
|
text : root.username |
|
} |
|
|
|
Column { // 0 |
|
id: dialogNameAndPassword |
|
property int heightInputs : inputUsername.height + buttonRow.height + middleSep.height + inputPassword.height + middleSepPassw.height |
|
|
|
Rectangle { |
|
id: topSep |
|
color : "transparent" |
|
width : Style.main.dummy |
|
height : root.height/2 - (dialogNameAndPassword.heightInputs)/2 |
|
} |
|
|
|
InputField { |
|
id: inputUsername |
|
iconText : Style.fa.user_circle |
|
label : qsTr("Username", "enter username to add account") |
|
onAccepted : inputPassword.focusInput = true |
|
} |
|
|
|
Rectangle { id: middleSepPassw; color : "transparent"; width : Style.main.dummy; height : Style.dialog.heightSeparator} |
|
|
|
InputField { |
|
id: inputPassword |
|
label : qsTr("Password", "password entry field") |
|
iconText : Style.fa.lock |
|
isPassword : true |
|
onAccepted : root.okay() |
|
} |
|
|
|
Rectangle { id: middleSep; color : "transparent"; width : Style.main.dummy; height : 2*Style.dialog.heightSeparator } |
|
|
|
Row { |
|
id: buttonRow |
|
anchors.horizontalCenter: parent.horizontalCenter |
|
spacing: Style.dialog.fontSize |
|
ButtonRounded { |
|
id:buttonCancel |
|
fa_icon : Style.fa.times |
|
text : qsTr("Cancel", "dismisses current action") |
|
color_main : Style.dialog.text |
|
onClicked : root.cancel() |
|
} |
|
ButtonRounded { |
|
id: buttonNext |
|
fa_icon : Style.fa.check |
|
text : qsTr("Next", "navigate to next page in add account flow") |
|
color_main : buttonOpaqueMain |
|
color_minor : Style.dialog.textBlue |
|
isOpaque : true |
|
onClicked : root.okay() |
|
} |
|
} |
|
|
|
Rectangle { |
|
color : "transparent" |
|
width : Style.main.dummy |
|
height : root.height - (topSep.height + dialogNameAndPassword.heightInputs + Style.main.bottomMargin + signUpForAccount.height) |
|
} |
|
|
|
ClickIconText { |
|
id: signUpForAccount |
|
anchors.horizontalCenter: parent.horizontalCenter |
|
fontSize : Style.dialog.fontSize |
|
iconSize : Style.dialog.fontSize |
|
iconText : "+" |
|
text : qsTr ("Sign Up for an Account", "takes user to web page where they can create a ProtonMail account") |
|
textBold : true |
|
textUnderline : true |
|
textColor : Style.dialog.text |
|
onClicked : root.createAccount() |
|
} |
|
} |
|
|
|
Column { // 1 |
|
id: dialog2FA |
|
property int heightInputs : buttonRowPassw.height + middleSep2FA.height + input2FAuth.height |
|
|
|
Rectangle { |
|
color : "transparent" |
|
width : Style.main.dummy |
|
height : (root.height - dialog2FA.heightInputs)/2 |
|
} |
|
|
|
InputField { |
|
id: input2FAuth |
|
label : qsTr("Two Factor Code", "two factor code entry field") |
|
iconText : Style.fa.lock |
|
onAccepted : root.okay() |
|
} |
|
|
|
Rectangle { id: middleSep2FA; color : "transparent"; width : Style.main.dummy; height : 2*Style.dialog.heightSeparator } |
|
|
|
Row { |
|
id: buttonRowPassw |
|
anchors.horizontalCenter: parent.horizontalCenter |
|
spacing: Style.dialog.fontSize |
|
ButtonRounded { |
|
id: buttonBack |
|
fa_icon: Style.fa.times |
|
text: qsTr("Back", "navigate back in add account flow") |
|
color_main: Style.dialog.text |
|
onClicked : root.cancel() |
|
} |
|
ButtonRounded { |
|
id: buttonNextTwo |
|
fa_icon: Style.fa.check |
|
text: qsTr("Next", "navigate to next page in add account flow") |
|
color_main: buttonOpaqueMain |
|
color_minor: Style.dialog.textBlue |
|
isOpaque: true |
|
onClicked : root.okay() |
|
} |
|
} |
|
} |
|
|
|
Column { // 2 |
|
id: dialogWaitingAuth |
|
Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height-dialogWaitingAuthText.height) /2 } |
|
Text { |
|
id: dialogWaitingAuthText |
|
anchors.horizontalCenter: parent.horizontalCenter |
|
color: Style.dialog.text |
|
font.pointSize: Style.dialog.fontSize * Style.pt |
|
text : qsTr("Logging in") +"\n" + root.usernameElided |
|
horizontalAlignment: Text.AlignHCenter |
|
} |
|
} |
|
|
|
Column { // 3 |
|
id: dialogMailboxPassword |
|
property int heightInputs : buttonRowMailbox.height + inputPasswMailbox.height + middleSepMailbox.height |
|
|
|
Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height - dialogMailboxPassword.heightInputs)/2} |
|
|
|
InputField { |
|
id: inputPasswMailbox |
|
label : qsTr("Mailbox password for %1", "mailbox password entry field").arg(root.usernameElided) |
|
iconText : Style.fa.lock |
|
isPassword : true |
|
onAccepted : root.okay() |
|
} |
|
|
|
Rectangle { id: middleSepMailbox; color : "transparent"; width : Style.main.dummy; height : 2*Style.dialog.heightSeparator } |
|
|
|
Row { |
|
id: buttonRowMailbox |
|
anchors.horizontalCenter: parent.horizontalCenter |
|
spacing: Style.dialog.fontSize |
|
ButtonRounded { |
|
id: buttonBackBack |
|
fa_icon: Style.fa.times |
|
text: qsTr("Back", "navigate back in add account flow") |
|
color_main: Style.dialog.text |
|
onClicked : root.cancel() |
|
} |
|
ButtonRounded { |
|
id: buttonLogin |
|
fa_icon: Style.fa.check |
|
text: qsTr("Next", "navigate to next page in add account flow") |
|
color_main: buttonOpaqueMain |
|
color_minor: Style.dialog.textBlue |
|
isOpaque: true |
|
onClicked : root.okay() |
|
} |
|
} |
|
} |
|
|
|
Column { // 4 |
|
id: dialogWaitingAccount |
|
|
|
Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height - dialogWaitingAccountText.height )/2 } |
|
|
|
Text { |
|
id: dialogWaitingAccountText |
|
anchors.horizontalCenter: parent.horizontalCenter |
|
color: Style.dialog.text |
|
font { |
|
bold : true |
|
pointSize: Style.dialog.fontSize * Style.pt |
|
} |
|
text : qsTr("Adding account, please wait ...", "displayed after user has logged in, before new account is displayed") |
|
wrapMode: Text.Wrap |
|
} |
|
} |
|
|
|
Column { // 5 |
|
id: dialogFirstUserAdded |
|
|
|
Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height - dialogWaitingAccountText.height - okButton.height*2 )/2 } |
|
|
|
Text { |
|
id: textFirstUser |
|
anchors.horizontalCenter: parent.horizontalCenter |
|
color: Style.dialog.text |
|
font { |
|
bold : false |
|
pointSize: Style.dialog.fontSize * Style.pt |
|
} |
|
width: 2*root.width/3 |
|
horizontalAlignment: Text.AlignHCenter |
|
textFormat: Text.RichText |
|
text: "<html><style>a { font-weight: bold; text-decoration: none; color: white;}</style>"+ |
|
qsTr("Now you need to configure your client(s) to use the Bridge. Instructions for configuring your client can be found at", "") + |
|
"<br/><a href=\"https://protonmail.com/bridge/clients\">https://protonmail.com/bridge/clients</a>.<html>" |
|
wrapMode: Text.Wrap |
|
onLinkActivated: { |
|
Qt.openUrlExternally(link) |
|
} |
|
MouseArea { |
|
anchors.fill: parent |
|
cursorShape: parent.hoveredLink=="" ? Qt.PointingHandCursor : Qt.WaitCursor |
|
acceptedButtons: Qt.NoButton |
|
} |
|
} |
|
|
|
Rectangle { color : "transparent"; width : Style.main.dummy; height : okButton.height} |
|
|
|
ButtonRounded{ |
|
id: okButton |
|
anchors.horizontalCenter: parent.horizontalCenter |
|
color_main: buttonOpaqueMain |
|
color_minor: Style.main.textBlue |
|
isOpaque: true |
|
text: qsTr("Okay", "confirms and dismisses a notification") |
|
onClicked: root.hide() |
|
} |
|
} |
|
|
|
function clear_user() { |
|
inputUsername.text = "" |
|
inputUsername.rightIcon = "" |
|
} |
|
|
|
function clear_passwd() { |
|
inputPassword.text = "" |
|
inputPassword.rightIcon = "" |
|
inputPassword.hidePasswordText() |
|
} |
|
|
|
|
|
function clear_2fa() { |
|
input2FAuth.text = "" |
|
input2FAuth.rightIcon = "" |
|
} |
|
|
|
function clear_passwd_mailbox() { |
|
inputPasswMailbox.text = "" |
|
inputPasswMailbox.rightIcon = "" |
|
inputPasswMailbox.hidePasswordText() |
|
} |
|
|
|
onCancel : { |
|
root.warning.visible=false |
|
if (currentIndex==0) { |
|
root.hide() |
|
} else { |
|
clear_passwd() |
|
clear_passwd_mailbox() |
|
currentIndex=0 |
|
} |
|
} |
|
|
|
|
|
function check_inputs() { |
|
var isOK = true |
|
switch (currentIndex) { |
|
case nameAndPasswordIndex : |
|
isOK &= inputUsername.checkNonEmpty() |
|
isOK &= inputPassword.checkNonEmpty() |
|
break |
|
case twoFAIndex : |
|
isOK &= input2FAuth.checkNonEmpty() |
|
break |
|
case mailboxIndex : |
|
isOK &= inputPasswMailbox.checkNonEmpty() |
|
break |
|
} |
|
if (isOK) { |
|
warning.visible = false |
|
warning.text= "" |
|
} else { |
|
setWarning(qsTr("Field required", "a field that must be filled in to submit form"),0) |
|
} |
|
return isOK |
|
} |
|
|
|
function setWarning(msg, changeIndex) { |
|
// show message |
|
root.warning.text = msg |
|
root.warning.visible = true |
|
} |
|
|
|
|
|
onOkay : { |
|
var isOK = check_inputs() |
|
if (isOK) { |
|
root.origin = root.currentIndex |
|
switch (root.currentIndex) { |
|
case nameAndPasswordIndex: |
|
case twoFAIndex: |
|
root.currentIndex = waitingAuthIndex |
|
break; |
|
case mailboxIndex: |
|
root.currentIndex = addingAccIndex |
|
} |
|
timer.start() |
|
} |
|
} |
|
|
|
onShow: { |
|
root.title = qsTr ("Log in to your ProtonMail account", "displayed on screen when user enters username to begin adding account") |
|
root.warning.visible = false |
|
inputUsername.forceFocus() |
|
root.isFirstAccount = go.isFirstStart && accountsModel.count==0 |
|
} |
|
|
|
function startAgain() { |
|
clear_passwd() |
|
clear_2fa() |
|
clear_passwd_mailbox() |
|
root.currentIndex = nameAndPasswordIndex |
|
root.inputPassword.focusInput = true |
|
} |
|
|
|
function finishLogin(){ |
|
root.currentIndex = addingAccIndex |
|
var auth = go.addAccount(inputPasswMailbox.text) |
|
if (auth<0) { |
|
startAgain() |
|
return |
|
} |
|
} |
|
|
|
Connections { |
|
target: timer |
|
|
|
onTriggered : { |
|
timer.repeat = false |
|
switch (root.origin) { |
|
case nameAndPasswordIndex: |
|
var auth = go.login(inputUsername.text, inputPassword.text) |
|
if (auth < 0) { |
|
startAgain() |
|
break |
|
} |
|
if (auth == 1) { |
|
root.currentIndex = twoFAIndex |
|
root.input2FAuth.focusInput = true |
|
break |
|
} |
|
if (auth == 2) { |
|
root.currentIndex = mailboxIndex |
|
root.inputPasswMailbox.focusInput = true |
|
break |
|
} |
|
root.inputPasswMailbox.text = inputPassword.text |
|
root.finishLogin() |
|
break; |
|
case twoFAIndex: |
|
var auth = go.auth2FA(input2FAuth.text) |
|
if (auth < 0) { |
|
startAgain() |
|
break |
|
} |
|
if (auth == 1) { |
|
root.currentIndex = mailboxIndex |
|
root.inputPasswMailbox.focusInput = true |
|
break |
|
} |
|
root.inputPasswMailbox.text = inputPassword.text |
|
root.finishLogin() |
|
break; |
|
case mailboxIndex: |
|
root.finishLogin() |
|
break; |
|
} |
|
} |
|
} |
|
|
|
onHide: { |
|
// because hide slot is conneceted to processFinished it will update |
|
// the list evertyime `go` obejcet is finished |
|
clear_passwd() |
|
clear_passwd_mailbox() |
|
clear_2fa() |
|
clear_user() |
|
go.loadAccounts() |
|
if (root.isFirstAccount && accountsModel.count==1) { |
|
root.isFirstAccount=false |
|
root.currentIndex=5 |
|
root.show() |
|
root.title=qsTr("Success, Account Added!", "shown after successful account addition") |
|
} |
|
} |
|
|
|
Keys.onPressed: { |
|
if (event.key == Qt.Key_Enter) { |
|
root.okay() |
|
} |
|
} |
|
}
|
|
|