UI/UX to ask for the accounts password on start up
With this change Keysmith now prompts the user to either: - setup a new password - supply an existing password (if detected) Additionally the organisation/structure of the QML is cleaned up a bit. All QML pages are dedicated QML files and a few signals are introduced to provide slightly better encapsulation/decouple interdependencies.master
parent
f16eba4505
commit
d048adf921
|
@ -31,11 +31,12 @@ target_link_libraries(keysmith
|
||||||
|
|
||||||
if(ANDROID)
|
if(ANDROID)
|
||||||
kirigami_package_breeze_icons(ICONS
|
kirigami_package_breeze_icons(ICONS
|
||||||
go-next
|
answer-correct
|
||||||
edit-delete
|
edit-delete
|
||||||
edit-undo
|
edit-undo
|
||||||
|
go-next
|
||||||
list-add
|
list-add
|
||||||
answer-correct
|
unlock
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
* SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.1
|
||||||
|
import QtQuick.Layouts 1.2
|
||||||
|
import QtQuick.Controls 2.0 as Controls
|
||||||
|
import org.kde.kirigami 2.8 as Kirigami
|
||||||
|
|
||||||
|
import Keysmith.Application 1.0
|
||||||
|
import Keysmith.Models 1.0 as Models
|
||||||
|
|
||||||
|
Kirigami.Page {
|
||||||
|
id: root
|
||||||
|
title: i18nc("@title:window", "Password")
|
||||||
|
|
||||||
|
property bool bannerTextError : false
|
||||||
|
property string bannerText : i18n("Get started by choosing a password to protect your accounts")
|
||||||
|
property string failedToApplyNewPassword : i18n("Failed to set up your password")
|
||||||
|
property Models.PasswordRequestModel passwordRequest: Keysmith.passwordRequest()
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors {
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
Controls.Label {
|
||||||
|
text: bannerText
|
||||||
|
color: bannerTextError ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.textColor
|
||||||
|
}
|
||||||
|
Kirigami.FormLayout {
|
||||||
|
Kirigami.PasswordField {
|
||||||
|
id: newPassword
|
||||||
|
text: ""
|
||||||
|
Kirigami.FormData.label: i18nc("@label:textbox", "New password:")
|
||||||
|
inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhNoPredictiveText | Qt.ImhSensitiveData | Qt.ImhHiddenText
|
||||||
|
}
|
||||||
|
Kirigami.PasswordField {
|
||||||
|
id: newPasswordCopy
|
||||||
|
text: ""
|
||||||
|
Kirigami.FormData.label: i18nc("@label:textbox", "Verify password:")
|
||||||
|
inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhNoPredictiveText | Qt.ImhSensitiveData | Qt.ImhHiddenText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.main : Kirigami.Action {
|
||||||
|
text: i18n("Apply")
|
||||||
|
iconName: "answer-correct"
|
||||||
|
enabled: newPassword.text === newPasswordCopy.text && newPassword.text && newPassword.text.length > 0
|
||||||
|
onTriggered: {
|
||||||
|
// TODO convert to C++ helper, have proper logging?
|
||||||
|
if (passwordRequest) {
|
||||||
|
if (!passwordRequest.provideBothPasswords(newPassword.text, newPasswordCopy.text)) {
|
||||||
|
bannerText = failedToApplyNewPassword;
|
||||||
|
bannerTextError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO warn if not
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
* SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.1
|
||||||
|
import QtQuick.Layouts 1.2
|
||||||
|
import QtQuick.Controls 2.0 as Controls
|
||||||
|
import org.kde.kirigami 2.8 as Kirigami
|
||||||
|
|
||||||
|
import Keysmith.Application 1.0
|
||||||
|
import Keysmith.Models 1.0 as Models
|
||||||
|
|
||||||
|
Kirigami.Page {
|
||||||
|
id: root
|
||||||
|
title: i18nc("@title:window", "Password")
|
||||||
|
|
||||||
|
property bool bannerTextError : false
|
||||||
|
property string bannerText : i18n("Please provide the password to unlock your accounts")
|
||||||
|
property string failedToApplyPassword : i18n("Failed to unlock your accounts")
|
||||||
|
property Models.PasswordRequestModel passwordRequest: Keysmith.passwordRequest()
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors {
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
Controls.Label {
|
||||||
|
text: bannerText
|
||||||
|
color: bannerTextError ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.textColor
|
||||||
|
}
|
||||||
|
Kirigami.FormLayout {
|
||||||
|
Kirigami.PasswordField {
|
||||||
|
id: existingPassword
|
||||||
|
text: ""
|
||||||
|
Kirigami.FormData.label: i18nc("@label:textbox", "Password:")
|
||||||
|
inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhNoPredictiveText | Qt.ImhSensitiveData | Qt.ImhHiddenText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.main : Kirigami.Action {
|
||||||
|
text: i18n("Unlock")
|
||||||
|
iconName: "unlock"
|
||||||
|
enabled: existingPassword.text && existingPassword.text.length > 0
|
||||||
|
onTriggered: {
|
||||||
|
// TODO convert to C++ helper, have proper logging?
|
||||||
|
if (passwordRequest) {
|
||||||
|
if (!passwordRequest.providePassword(existingPassword.text)) {
|
||||||
|
bannerText = failedToApplyPassword;
|
||||||
|
bannerTextError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO warn if not
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,10 +15,23 @@ import org.kde.kirigami 2.4 as Kirigami
|
||||||
Kirigami.ApplicationWindow {
|
Kirigami.ApplicationWindow {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
pageStack.initialPage: accountsOverviewPage
|
|
||||||
|
|
||||||
property bool addActionEnabled: true
|
property bool addActionEnabled: true
|
||||||
property Models.AccountListModel accounts: Keysmith.accountListModel()
|
property Models.AccountListModel accounts: Keysmith.accountListModel()
|
||||||
|
property Models.PasswordRequestModel passwordRequest: Keysmith.passwordRequest()
|
||||||
|
|
||||||
|
pageStack.initialPage: passwordRequest.previouslyDefined ? unlockAccountsPage : setupPasswordPage
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: setupPasswordPage
|
||||||
|
SetupPassword {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: unlockAccountsPage
|
||||||
|
UnlockAccounts {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: accountsOverviewPage
|
id: accountsOverviewPage
|
||||||
|
@ -42,4 +55,17 @@ Kirigami.ApplicationWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO maybe have a onPasswordProvided handler to push a "progress" page to provide visual feedback for devices where key derivation is slow?
|
||||||
|
Connections {
|
||||||
|
target: passwordRequest
|
||||||
|
onDerivedKey : {
|
||||||
|
// TODO convert to C++ helper, have proper logging?
|
||||||
|
if (passwordRequest.keyAvailable) {
|
||||||
|
pageStack.pop();
|
||||||
|
pageStack.push(accountsOverviewPage);
|
||||||
|
}
|
||||||
|
// TODO warn if not
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,5 +10,7 @@
|
||||||
<file alias="AccountEntryView.qml">contents/ui/AccountEntryView.qml</file>
|
<file alias="AccountEntryView.qml">contents/ui/AccountEntryView.qml</file>
|
||||||
<file alias="AccountsOverview.qml">contents/ui/AccountsOverview.qml</file>
|
<file alias="AccountsOverview.qml">contents/ui/AccountsOverview.qml</file>
|
||||||
<file alias="AddAccount.qml">contents/ui/AddAccount.qml</file>
|
<file alias="AddAccount.qml">contents/ui/AddAccount.qml</file>
|
||||||
|
<file alias="UnlockAccounts.qml">contents/ui/UnlockAccounts.qml</file>
|
||||||
|
<file alias="SetupPassword.qml">contents/ui/SetupPassword.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
Loading…
Reference in New Issue