183 lines
6.6 KiB
QML
183 lines
6.6 KiB
QML
/*
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
* SPDX-FileCopyrightText: 2020-2021 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
|
* SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
|
|
*/
|
|
|
|
import QtQuick 2.1
|
|
import QtQuick.Layouts 1.2
|
|
import org.kde.kirigami 2.15 as Kirigami
|
|
|
|
import Keysmith.Application 1.0 as Application
|
|
import Keysmith.Models 1.0 as Models
|
|
|
|
Kirigami.ScrollablePage {
|
|
id: root
|
|
/*
|
|
* Explicitly opt-out of scroll-to-refresh/drag-to-refresh behaviour
|
|
* Underlying model implementations don't offer the hooks for that.
|
|
*/
|
|
supportsRefreshing: false
|
|
title: i18nc("@title:window", "Accounts")
|
|
|
|
property Application.AccountsOverviewViewModel vm
|
|
|
|
property string accountErrorMessage: i18nc("generic error shown when adding or updating an account failed", "Failed to update accounts")
|
|
property string loadingErrorMessage: i18nc("error message shown when loading accounts from storage failed", "Some accounts failed to load.")
|
|
property string errorMessage: loadingErrorMessage
|
|
|
|
header: ColumnLayout {
|
|
id: column
|
|
Layout.margins: 0
|
|
spacing: 0
|
|
Kirigami.InlineMessage {
|
|
id: message
|
|
visible: vm.accounts.error // FIXME : should be managed via vm
|
|
type: Kirigami.MessageType.Error
|
|
text: root.errorMessage // FIXME : should be managed via vm
|
|
Layout.fillWidth: true
|
|
Layout.margins: Kirigami.Units.smallSpacing
|
|
/*
|
|
* There is supposed to be a more Kirigami-way to allow the user to dismiss the error message: showCloseButton
|
|
* Unfortunately:
|
|
*
|
|
* - Kirigami doesn't really offer a direct API for detecting when the close button is clicked.
|
|
* Observing the close button's effect via the visible property works just as well, but it is a bit of a hack.
|
|
* - It results in a rather unattractive vertical sizing problem: the close button is rather big for inline text
|
|
* This makes the internal horizontal spacing look completely out of proportion with the vertical spacing.
|
|
* - The actual click/tap target is only a small fraction of the entire message (banner).
|
|
* In this case, making the entire message click/tap target would be much better.
|
|
*
|
|
* Solution: add a MouseArea for dismissing the message via click/tap.
|
|
*/
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
onClicked: {
|
|
// FIXME : should be managed via vm
|
|
vm.accounts.error = false;
|
|
}
|
|
}
|
|
}
|
|
Kirigami.Separator {
|
|
Layout.fillWidth: true
|
|
visible: vm.accounts.error // FIXME : should be managed via vm
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: hotpDelegate
|
|
HOTPAccountEntryView {
|
|
account: value
|
|
onActionTriggered: {
|
|
// FIXME : should be managed via vm
|
|
vm.accounts.error = false;
|
|
root.errorMessage = root.accountErrorMessage;
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: totpDelegate
|
|
TOTPAccountEntryView {
|
|
account: value
|
|
onActionTriggered: {
|
|
// FIXME : should be managed via vm
|
|
vm.accounts.error = false;
|
|
root.errorMessage = root.accountErrorMessage;
|
|
}
|
|
}
|
|
}
|
|
|
|
ListView {
|
|
id: mainList
|
|
model: Models.SortedAccountListModel {
|
|
sourceModel: vm.accounts
|
|
}
|
|
|
|
Kirigami.PlaceholderMessage {
|
|
anchors.centerIn: parent
|
|
width: parent.width - (Kirigami.Units.largeSpacing * 4)
|
|
visible: vm.accounts.loaded && mainList.count == 0
|
|
text: i18n("No accounts added")
|
|
icon.name: "unlock"
|
|
|
|
helpfulAction: Kirigami.Action {
|
|
iconName: "list-add"
|
|
text: i18nc("@action:button add new account, shown instead of overview list when no accounts have been added yet", "Add account")
|
|
onTriggered: {
|
|
// FIXME : should be managed via vm
|
|
vm.accounts.error = false;
|
|
root.errorMessage = root.accountErrorMessage;
|
|
vm.addNewAccount();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Use a Loader to get a switch-like statement to select an
|
|
* appropriate delegate based on properties of the account model.
|
|
*/
|
|
delegate: Loader {
|
|
/*
|
|
* Fix up width manually.
|
|
* It doesn't seem to be propagated correctly by itself otherwise.
|
|
*/
|
|
width: mainList.width
|
|
|
|
/*
|
|
* The `model` and related properties from the ListView delegate
|
|
* context will not survive into the actual delegate components.
|
|
* However Loader will also inject properties in *its* context
|
|
* which will be observed by those delegate components.
|
|
*
|
|
* Fill the Loader's context with properties from the model passed
|
|
* by ListView, to make these values propagate into delegates.
|
|
*
|
|
* See also: https://doc.qt.io/qt-5/qml-qtquick-loader.html#using-a-loader-within-a-view-delegate
|
|
*/
|
|
property Models.Account value: model.account
|
|
property int index: model.index
|
|
|
|
sourceComponent: {
|
|
/*
|
|
* Guard against a broken account model.
|
|
* Will simply render nothing at all in that case.
|
|
*/
|
|
if (!value) {
|
|
// TODO warn about this
|
|
return null;
|
|
}
|
|
if (value.isHotp) {
|
|
return hotpDelegate;
|
|
}
|
|
if (value.isTotp) {
|
|
return totpDelegate;
|
|
}
|
|
|
|
// TODO warn about this
|
|
return null;
|
|
}
|
|
}
|
|
section {
|
|
property: "account.issuer"
|
|
delegate: Kirigami.ListSectionHeader {
|
|
text: section
|
|
}
|
|
}
|
|
}
|
|
|
|
actions.main: Kirigami.Action {
|
|
id: addAction
|
|
text: i18nc("@action:button add new account, shown in toolbar", "Add")
|
|
iconName: "list-add"
|
|
enabled: vm.actionsEnabled
|
|
visible: vm.actionsEnabled
|
|
onTriggered: {
|
|
// FIXME : should be managed via vm
|
|
vm.accounts.error = false;
|
|
root.errorMessage = root.accountErrorMessage;
|
|
vm.addNewAccount();
|
|
}
|
|
}
|
|
}
|