ImportKeys/ExportKeys separate dialog componants
This commit is contained in:
		
							
								
								
									
										1
									
								
								TODO.md
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								TODO.md
									
									
									
									
									
								
							| @@ -33,6 +33,7 @@ | |||||||
|   - Show error if uploading avatar fails or file is corrupted |   - Show error if uploading avatar fails or file is corrupted | ||||||
|   - Way to open context menus without a right mouse button |   - Way to open context menus without a right mouse button | ||||||
|   - Room header descriptions: styled text |   - Room header descriptions: styled text | ||||||
|  |   - Indeterminate progress bar | ||||||
|  |  | ||||||
|   - Message selection |   - Message selection | ||||||
|     - Copy to X11 selection |     - Copy to X11 selection | ||||||
|   | |||||||
| @@ -324,13 +324,15 @@ class MatrixClient(nio.AsyncClient): | |||||||
|         account     = self.models[Account][self.user_id] |         account     = self.models[Account][self.user_id] | ||||||
|         import_keys = partial(self.olm.import_keys_static, infile, passphrase) |         import_keys = partial(self.olm.import_keys_static, infile, passphrase) | ||||||
|  |  | ||||||
|  |         account.importing_key        = 0 | ||||||
|  |         account.total_keys_to_import = -1  # preparing | ||||||
|  |  | ||||||
|         try: |         try: | ||||||
|             sessions = await loop.run_in_executor(None, import_keys) |             sessions = await loop.run_in_executor(None, import_keys) | ||||||
|         except nio.EncryptionError as err: |         except nio.EncryptionError as err: | ||||||
|             account.import_error = (infile, passphrase, str(err)) |             account.import_error = (infile, passphrase, str(err)) | ||||||
|             return |             return | ||||||
|  |  | ||||||
|         account.importing_key        = 0 |  | ||||||
|         account.total_keys_to_import = len(sessions) |         account.total_keys_to_import = len(sessions) | ||||||
|  |  | ||||||
|         for session in sessions: |         for session in sessions: | ||||||
|   | |||||||
							
								
								
									
										39
									
								
								src/qml/Dialogs/ExportKeys.qml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/qml/Dialogs/ExportKeys.qml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | import QtQuick 2.12 | ||||||
|  | import Qt.labs.platform 1.1 | ||||||
|  | import "../Popups" | ||||||
|  |  | ||||||
|  | HFileDialogOpener { | ||||||
|  |     fill: false | ||||||
|  |     dialog.title: qsTr("Save decryption keys file as...") | ||||||
|  |     dialog.fileMode: FileDialog.SaveFile | ||||||
|  |     onFileChanged: { | ||||||
|  |         exportPasswordPopup.file = file | ||||||
|  |         exportPasswordPopup.open() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     property string userId: "" | ||||||
|  |     property bool exporting: false | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     function exportKeys(file, passphrase) { | ||||||
|  |         exporting = true | ||||||
|  |  | ||||||
|  |         let path = file.toString().replace(/^file:\/\//, "") | ||||||
|  |  | ||||||
|  |         py.callClientCoro(userId, "export_keys", [path, passphrase], () => { | ||||||
|  |             exporting = false | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     PasswordPopup { | ||||||
|  |         id: exportPasswordPopup | ||||||
|  |         details.text: qsTr("Please enter a passphrase to protect this file:") | ||||||
|  |         okText: qsTr("Export") | ||||||
|  |  | ||||||
|  |         onAcceptedPasswordChanged: exportKeys(file, acceptedPassword) | ||||||
|  |  | ||||||
|  |         property url file: "" | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										42
									
								
								src/qml/Dialogs/ImportKeys.qml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/qml/Dialogs/ImportKeys.qml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | |||||||
|  | import QtQuick 2.12 | ||||||
|  | import Qt.labs.platform 1.1 | ||||||
|  | import "../Popups" | ||||||
|  |  | ||||||
|  | HFileDialogOpener { | ||||||
|  |     fill: false | ||||||
|  |     dialog.title: qsTr("Select a decryption keys file to import") | ||||||
|  |     onFileChanged: { | ||||||
|  |         importPasswordPopup.file = file | ||||||
|  |         importPasswordPopup.open() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     property string userId: "" | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     function importKeys(file, passphrase) { | ||||||
|  |         let path = file.toString().replace(/^file:\/\//, "") | ||||||
|  |         py.callClientCoro(userId, "import_keys", [path, passphrase]) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     PasswordPopup { | ||||||
|  |         id: importPasswordPopup | ||||||
|  |         details.text: qsTr( | ||||||
|  |             "Please enter the passphrase that was used to protect this file:" | ||||||
|  |         ) | ||||||
|  |         okText: qsTr("Import") | ||||||
|  |  | ||||||
|  |         onAcceptedPasswordChanged: importKeys(file, acceptedPassword) | ||||||
|  |  | ||||||
|  |         property url file: "" | ||||||
|  |  | ||||||
|  |         function verifyPassword(pass, callback) { | ||||||
|  |             py.callCoro( | ||||||
|  |                 "check_exported_keys_passphrase", | ||||||
|  |                 [file.toString().replace(/^file:\/\//, ""), pass], | ||||||
|  |                 callback | ||||||
|  |             ) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -4,46 +4,13 @@ import "../../Base" | |||||||
| HLoader { | HLoader { | ||||||
|     id: encryptionUI |     id: encryptionUI | ||||||
|     source: |     source: | ||||||
|         accountInfo.import_error[0] ? "ImportError.qml" : |         accountInfo.import_error[0]      ? "ImportError.qml" : | ||||||
|         importing || accountInfo.total_keys_to_import ? "ImportingKeys.qml" : |         accountInfo.total_keys_to_import ? "ImportingKeys.qml" : | ||||||
|         "ImportExportKeys.qml" |         "ImportExportKeys.qml" | ||||||
|  |  | ||||||
|     onSourceChanged: animation.running = true |     onSourceChanged: animation.running = true | ||||||
|  |  | ||||||
|  |  | ||||||
|     property bool importing: false |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     function exportKeys(file, passphrase, button=null) { |  | ||||||
|         if (button) button.loading = true |  | ||||||
|  |  | ||||||
|         let path = file.toString().replace(/^file:\/\//, "") |  | ||||||
|  |  | ||||||
|         py.callClientCoro( |  | ||||||
|             editAccount.userId, "export_keys", [path, passphrase], () => { |  | ||||||
|                 // null: user is on another page |  | ||||||
|                 if (encryptionUI !== null && button) button.loading = false |  | ||||||
|             } |  | ||||||
|         ) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     function importKeys(file, passphrase, button=null) { |  | ||||||
|         if (button) button.loading = true |  | ||||||
|         encryptionUI.importing = true |  | ||||||
|  |  | ||||||
|         let path = file.toString().replace(/^file:\/\//, "") |  | ||||||
|  |  | ||||||
|         py.callClientCoro( |  | ||||||
|             editAccount.userId, "import_keys", [path, passphrase], () => { |  | ||||||
|                 if (encryptionUI !== null) { |  | ||||||
|                     encryptionUI.importing = false |  | ||||||
|                     if (button) button.loading = false |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         ) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     SequentialAnimation { |     SequentialAnimation { | ||||||
|         id: animation |         id: animation | ||||||
|         HNumberAnimation { |         HNumberAnimation { | ||||||
|   | |||||||
| @@ -1,14 +1,9 @@ | |||||||
| import QtQuick 2.12 | import QtQuick 2.12 | ||||||
| import QtQuick.Controls 2.12 |  | ||||||
| import QtQuick.Layouts 1.12 | import QtQuick.Layouts 1.12 | ||||||
| import Qt.labs.platform 1.1 |  | ||||||
| import "../../Base" | import "../../Base" | ||||||
| import "../../Popups" |  | ||||||
| import "../../utils.js" as Utils | import "../../utils.js" as Utils | ||||||
|  |  | ||||||
| HBox { | HBox { | ||||||
|     property var exportButton: null |  | ||||||
|  |  | ||||||
|     horizontalSpacing: currentSpacing |     horizontalSpacing: currentSpacing | ||||||
|     verticalSpacing: currentSpacing |     verticalSpacing: currentSpacing | ||||||
|  |  | ||||||
| @@ -19,10 +14,24 @@ HBox { | |||||||
|  |  | ||||||
|     buttonCallbacks: ({ |     buttonCallbacks: ({ | ||||||
|         export: button => { |         export: button => { | ||||||
|             exportButton = button |             Utils.makeObject( | ||||||
|             exportFileDialog.dialog.open() |                 "Dialogs/ExportKeys.qml", | ||||||
|  |                 editAccount, | ||||||
|  |                 { userId: editAccount.userId }, | ||||||
|  |                 obj => { | ||||||
|  |                     button.loading = Qt.binding(() => obj.exporting) | ||||||
|  |                     obj.dialog.open() | ||||||
|  |                 } | ||||||
|  |             ) | ||||||
|  |         }, | ||||||
|  |         import: button => { | ||||||
|  |             Utils.makeObject( | ||||||
|  |                 "Dialogs/ImportKeys.qml", | ||||||
|  |                 editAccount, | ||||||
|  |                 { userId: editAccount.userId }, | ||||||
|  |                 obj => { obj.dialog.open() } | ||||||
|  |             ) | ||||||
|         }, |         }, | ||||||
|         import: button => { importFileDialog.dialog.open() }, |  | ||||||
|     }) |     }) | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -38,57 +47,4 @@ HBox { | |||||||
|  |  | ||||||
|         Layout.fillWidth: true |         Layout.fillWidth: true | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     HFileDialogOpener { |  | ||||||
|         id: exportFileDialog |  | ||||||
|         fill: false |  | ||||||
|         dialog.title: qsTr("Save decryption keys file as...") |  | ||||||
|         dialog.fileMode: FileDialog.SaveFile |  | ||||||
|         onFileChanged: { |  | ||||||
|             exportPasswordPopup.file = file |  | ||||||
|             exportPasswordPopup.open() |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     HFileDialogOpener { |  | ||||||
|         id: importFileDialog |  | ||||||
|         fill: false |  | ||||||
|         dialog.title: qsTr("Select a decryption keys file to import") |  | ||||||
|         onFileChanged: { |  | ||||||
|             importPasswordPopup.file = file |  | ||||||
|             importPasswordPopup.open() |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     PasswordPopup { |  | ||||||
|         property url file: "" |  | ||||||
|  |  | ||||||
|         id: exportPasswordPopup |  | ||||||
|         details.text: qsTr("Please enter a passphrase to protect this file:") |  | ||||||
|         okText: qsTr("Export") |  | ||||||
|  |  | ||||||
|         onAcceptedPasswordChanged: |  | ||||||
|             encryptionUI.exportKeys(file, acceptedPassword, exportButton) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     PasswordPopup { |  | ||||||
|         property url file: "" |  | ||||||
|  |  | ||||||
|         function verifyPassword(pass, callback) { |  | ||||||
|             py.callCoro( |  | ||||||
|                 "check_exported_keys_passphrase", |  | ||||||
|                 [file.toString().replace(/^file:\/\//, ""), pass], |  | ||||||
|                 callback |  | ||||||
|             ) |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         id: importPasswordPopup |  | ||||||
|         details.text: qsTr( |  | ||||||
|             "Please enter the passphrase that was used to protect this file:" |  | ||||||
|         ) |  | ||||||
|         okText: qsTr("Import") |  | ||||||
|  |  | ||||||
|         onAcceptedPasswordChanged: |  | ||||||
|             encryptionUI.importKeys(file, acceptedPassword) |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -34,7 +34,9 @@ HColumnLayout { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         HLabel { |         HLabel { | ||||||
|             text: qsTr("%1/%2") |             text: progressBar.indeterminate ? | ||||||
|  |                   qsTr("Preparing...") : | ||||||
|  |                   qsTr("%1/%2") | ||||||
|                   .arg(Math.ceil(progressBar.value)).arg(progressBar.to) |                   .arg(Math.ceil(progressBar.value)).arg(progressBar.to) | ||||||
|  |  | ||||||
|             Layout.margins: currentSpacing |             Layout.margins: currentSpacing | ||||||
| @@ -46,6 +48,7 @@ HColumnLayout { | |||||||
|         from: 0 |         from: 0 | ||||||
|         value: progress |         value: progress | ||||||
|         to: accountInfo.total_keys_to_import |         to: accountInfo.total_keys_to_import | ||||||
|  |         indeterminate: accountInfo.total_keys_to_import < 0 | ||||||
|  |  | ||||||
|         Behavior on value { HNumberAnimation { factor: 5 } } |         Behavior on value { HNumberAnimation { factor: 5 } } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ import QtQuick 2.12 | |||||||
| import QtQuick.Controls 2.12 | import QtQuick.Controls 2.12 | ||||||
| import QtQuick.Layouts 1.12 | import QtQuick.Layouts 1.12 | ||||||
| import "../../Base" | import "../../Base" | ||||||
|  | import "../../Dialogs" | ||||||
| import "../../utils.js" as Utils | import "../../utils.js" as Utils | ||||||
|  |  | ||||||
| HGridLayout { | HGridLayout { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	