diff --git a/TODO.md b/TODO.md
index fb0b586f..90657970 100644
--- a/TODO.md
+++ b/TODO.md
@@ -16,6 +16,9 @@
- When qml syntax highlighting supports string interpolation, use them
- Fixes
+ - Run import in thread ? Does it blocks the async loop?
+ - Handle import errors
+ - Update the room subtitle when a message is decrypted/edited
- Don't linkify images for outgoing html
- state: If last page is a room and the account for it is no longer present,
load Default.qml instead
@@ -29,6 +32,13 @@
- [hr not working](https://bugreports.qt.io/browse/QTBUG-74342)
- UI
+ - Popup:
+ - label size
+ - Accept/cancel buttons
+ - Transitions
+
+ - When starting a long task, e.g. importing keys, quitting the page,
+ and coming back, show the buttons as still loading until operation is done
- Make invite/left banners look better in column mode
- Messages editing
- Code highlighting
diff --git a/src/icons/dark-filled/export-keys.svg b/src/icons/dark-filled/export-keys.svg
new file mode 100644
index 00000000..9b9b732c
--- /dev/null
+++ b/src/icons/dark-filled/export-keys.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/dark-filled/import-keys.svg b/src/icons/dark-filled/import-keys.svg
new file mode 100644
index 00000000..51e5123b
--- /dev/null
+++ b/src/icons/dark-filled/import-keys.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/light-thin/export-keys.svg b/src/icons/light-thin/export-keys.svg
new file mode 100644
index 00000000..55b716a5
--- /dev/null
+++ b/src/icons/light-thin/export-keys.svg
@@ -0,0 +1,32 @@
+
+
diff --git a/src/icons/light-thin/import-keys.svg b/src/icons/light-thin/import-keys.svg
new file mode 100644
index 00000000..b33a28ef
--- /dev/null
+++ b/src/icons/light-thin/import-keys.svg
@@ -0,0 +1,32 @@
+
+
diff --git a/src/qml/Base/HFileDialogOpener.qml b/src/qml/Base/HFileDialogOpener.qml
index 9bfac066..bdd0c983 100644
--- a/src/qml/Base/HFileDialogOpener.qml
+++ b/src/qml/Base/HFileDialogOpener.qml
@@ -13,7 +13,7 @@ Item {
property string file: ""
enum FileType { All, Images }
- property int fileType: FileType.All
+ property int fileType: HFileDialogOpener.FileType.All
TapHandler { onTapped: fileDialog.open() }
diff --git a/src/qml/Base/HPasswordPopup.qml b/src/qml/Base/HPasswordPopup.qml
new file mode 100644
index 00000000..806e8f9a
--- /dev/null
+++ b/src/qml/Base/HPasswordPopup.qml
@@ -0,0 +1,55 @@
+// Copyright 2019 miruka
+// This file is part of harmonyqml, licensed under LGPLv3.
+
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+import "../SidePane"
+
+Popup {
+ id: popup
+ width: window.width
+ anchors.centerIn: Overlay.overlay
+ modal: true
+
+ onOpened: passwordField.forceActiveFocus()
+
+ property alias label: popupLabel
+ property alias field: passwordField
+ property string password: ""
+
+ background: HRectangle {
+ color: theme.controls.popup.background
+ }
+
+ HColumnLayout {
+ width: parent.width
+ spacing: theme.spacing
+
+ HLabel {
+ id: popupLabel
+ wrapMode: Text.Wrap
+
+ Layout.alignment: Qt.AlignCenter
+ Layout.minimumWidth: theme.minimumSupportedWidth
+ Layout.maximumWidth:
+ Math.min(480, window.width - theme.spacing * 2)
+ }
+
+ HTextField {
+ id: passwordField
+ echoMode: TextInput.Password
+ focus: true
+ onAccepted: {
+ popup.password = text
+ popup.close()
+ }
+
+ Layout.alignment: Qt.AlignCenter
+ Layout.fillWidth: true
+
+ Layout.preferredWidth: popupLabel.width
+ Layout.maximumWidth: popupLabel.width
+ }
+ }
+}
diff --git a/src/qml/Pages/EditAccount/ClientSettings.qml b/src/qml/Pages/EditAccount/ClientSettings.qml
deleted file mode 100644
index 742ae0ab..00000000
--- a/src/qml/Pages/EditAccount/ClientSettings.qml
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2019 miruka
-// This file is part of harmonyqml, licensed under LGPLv3.
-
-import QtQuick 2.12
-import QtQuick.Controls 2.12
-import QtQuick.Layouts 1.12
-import "../../Base"
-import "../../utils.js" as Utils
-
-HLabel {
- text: "Client - TODO"
-}
diff --git a/src/qml/Pages/EditAccount/Devices.qml b/src/qml/Pages/EditAccount/Devices.qml
deleted file mode 100644
index 1e8cb0a6..00000000
--- a/src/qml/Pages/EditAccount/Devices.qml
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2019 miruka
-// This file is part of harmonyqml, licensed under LGPLv3.
-
-import QtQuick 2.12
-import QtQuick.Controls 2.12
-import QtQuick.Layouts 1.12
-import "../../Base"
-import "../../utils.js" as Utils
-
-HLabel {
- text: "Devices - TODO"
-}
diff --git a/src/qml/Pages/EditAccount/EditAccount.qml b/src/qml/Pages/EditAccount/EditAccount.qml
index 3d2478d0..94fa7fd7 100644
--- a/src/qml/Pages/EditAccount/EditAccount.qml
+++ b/src/qml/Pages/EditAccount/EditAccount.qml
@@ -24,21 +24,32 @@ HPage {
Utils.coloredNameHtml(headerName, userId)
)
- HRectangle {
- color: ready ? theme.controls.box.background : "transparent"
- Behavior on color { HColorAnimation {} }
+ HSpacer {}
- Layout.alignment: Qt.AlignCenter
+ Repeater {
+ model: ["Profile.qml", "Encryption.qml"]
- Layout.maximumWidth: Math.min(parent.width, 640)
- Layout.preferredWidth:
- pageStack.isWide ? parent.width : avatarPreferredSize
+ HRectangle {
+ color: ready ? theme.controls.box.background : "transparent"
+ Behavior on color { HColorAnimation {} }
- Layout.preferredHeight: childrenRect.height
+ Layout.alignment: Qt.AlignCenter
- Loader {
- width: parent.width
- source: ready ? "Profile.qml" : "../../Base/HBusyIndicator.qml"
+ Layout.maximumWidth: Math.min(parent.width, 640)
+ Layout.preferredWidth:
+ pageStack.isWide ? parent.width : avatarPreferredSize
+
+ Layout.preferredHeight: childrenRect.height
+
+ Loader {
+ width: parent.width
+ source: ready ?
+ modelData :
+ (modelData == "Profile.qml" ?
+ "../../Base/HBusyIndicator.qml" : "")
+ }
}
}
+
+ HSpacer {}
}
diff --git a/src/qml/Pages/EditAccount/Encryption.qml b/src/qml/Pages/EditAccount/Encryption.qml
new file mode 100644
index 00000000..02c1ada8
--- /dev/null
+++ b/src/qml/Pages/EditAccount/Encryption.qml
@@ -0,0 +1,79 @@
+// Copyright 2019 miruka
+// This file is part of harmonyqml, licensed under LGPLv3.
+
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+import "../../Base"
+import "../../utils.js" as Utils
+
+HColumnLayout {
+ function importKeys(file, passphrase) {
+ importButton.loading = true
+
+ let path = Qt.resolvedUrl(file).replace(/^file:\/\//, "")
+
+ py.callClientCoro(
+ editAccount.userId, "import_keys", [path, passphrase], () => {
+ importButton.loading = false
+ }
+ )
+ }
+
+ HLabel {
+ wrapMode: Text.Wrap
+ text: qsTr(
+ "The decryption keys for the messages you received in " +
+ "encrypted rooms can be exported to a file.%1" +
+ "You will then be able to import this file in another " +
+ "Matrix client."
+ ).arg(pageStack.isWide ? "\n" :"\n\n")
+
+ Layout.fillWidth: true
+ Layout.margins: currentSpacing
+ }
+
+ HRowLayout {
+ HUIButton {
+ id: exportButton
+ iconName: "export-keys"
+ text: qsTr("Export")
+ enabled: false
+
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignBottom
+ }
+
+ HUIButton {
+ id: importButton
+ iconName: "import-keys"
+ text: qsTr("Import")
+
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignBottom
+
+ HFileDialogOpener {
+ id: fileDialog
+ dialog.title: qsTr("Select a decryption key file to import")
+ onFileChanged: {
+ importPasswordPopup.file = file
+ importPasswordPopup.open()
+ }
+ }
+ }
+ }
+
+ HPasswordPopup {
+ property url file: ""
+
+ id: importPasswordPopup
+ label.text: qsTr(
+ "Please enter the passphrase that was used to protect this " +
+ "file.\n\n" +
+ "The import can take a few minutes. " +
+ "You can leave the account settings page while it is running. " +
+ "Messages may not be sent or received until the operation is done."
+ )
+ onPasswordChanged: importKeys(file, password)
+ }
+}
diff --git a/src/themes/Default.qpl b/src/themes/Default.qpl
index c2e86d92..64d81caf 100644
--- a/src/themes/Default.qpl
+++ b/src/themes/Default.qpl
@@ -72,6 +72,9 @@ controls:
color background: colors.strongBackground
int radius: theme.radius
+ popup:
+ color background: colors.strongBackground
+
header:
color background: colors.strongBackground