diff --git a/data/resources/resources.gresource.xml b/data/resources/resources.gresource.xml
index 77945325..1c935894 100644
--- a/data/resources/resources.gresource.xml
+++ b/data/resources/resources.gresource.xml
@@ -26,6 +26,8 @@
ui/account-settings-deactivate-account-subpage.ui
ui/account-settings-device-row.ui
ui/account-settings-devices-page.ui
+ ui/account-settings-import-export-keys-subpage.ui
+ ui/account-settings-security-page.ui
ui/account-settings-user-page.ui
ui/account-settings.ui
ui/attachment-dialog.ui
diff --git a/data/resources/ui/account-settings-change-password-subpage.ui b/data/resources/ui/account-settings-change-password-subpage.ui
index 38d25f27..bba7b230 100644
--- a/data/resources/ui/account-settings-change-password-subpage.ui
+++ b/data/resources/ui/account-settings-change-password-subpage.ui
@@ -61,7 +61,7 @@
- Fractal’s support for encryption is unstable so you might lose access to your encrypted message history. It is recommended to backup your encryption keys from another Matrix client before proceeding.
+ Fractal’s support for encryption is unstable so you might lose access to your encrypted message history. It is recommended to backup your encryption keys before proceeding.
True
word-char
0.0
diff --git a/data/resources/ui/account-settings-import-export-keys-subpage.ui b/data/resources/ui/account-settings-import-export-keys-subpage.ui
new file mode 100644
index 00000000..a2fc3057
--- /dev/null
+++ b/data/resources/ui/account-settings-import-export-keys-subpage.ui
@@ -0,0 +1,108 @@
+
+
+
+ vertical
+
+
+
+
+
+
+
+
diff --git a/data/resources/ui/account-settings-security-page.ui b/data/resources/ui/account-settings-security-page.ui
new file mode 100644
index 00000000..4b8852f9
--- /dev/null
+++ b/data/resources/ui/account-settings-security-page.ui
@@ -0,0 +1,30 @@
+
+
+
+ channel-secure-symbolic
+ Security
+ security
+
+
+ Room Encryption Keys
+
+
+ Export Room Encryption Keys
+ true
+
+
+
+
+
+ Import Room Encryption Keys
+ true
+
+
+
+
+
+
+
+
+
+
diff --git a/data/resources/ui/account-settings.ui b/data/resources/ui/account-settings.ui
index c9ca479f..3140cc89 100644
--- a/data/resources/ui/account-settings.ui
+++ b/data/resources/ui/account-settings.ui
@@ -18,5 +18,10 @@
+
+
+
+
+
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 41468cb5..12ef1700 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -9,7 +9,9 @@ data/resources/ui/account-settings-change-password-subpage.ui
data/resources/ui/account-settings-deactivate-account-subpage.ui
data/resources/ui/account-settings-device-row.ui
data/resources/ui/account-settings-devices-page.ui
+data/resources/ui/account-settings-import-export-keys-subpage.ui
data/resources/ui/account-settings-user-page.ui
+data/resources/ui/account-settings-security-page.ui
data/resources/ui/account-settings.ui
data/resources/ui/attachment-dialog.ui
data/resources/ui/components-auth-dialog.ui
@@ -51,6 +53,7 @@ src/login/mod.rs
src/secret.rs
src/session/account_settings/devices_page/device_list.rs
src/session/account_settings/devices_page/device_row.rs
+src/session/account_settings/security_page/import_export_keys_subpage.rs
src/session/account_settings/user_page/change_password_subpage.rs
src/session/account_settings/user_page/deactivate_account_subpage.rs
src/session/account_settings/user_page/mod.rs
diff --git a/src/session/account_settings/devices_page/device_row.rs b/src/session/account_settings/devices_page/device_row.rs
index 6d657b33..bd8fa655 100644
--- a/src/session/account_settings/devices_page/device_row.rs
+++ b/src/session/account_settings/devices_page/device_row.rs
@@ -225,7 +225,7 @@ impl DeviceRow {
self.imp().delete_logout_button.set_loading(true);
let window: Option = self.root().and_then(|root| root.downcast().ok());
- let dialog = gtk::MessageDialog::new(window.as_ref(), gtk::DialogFlags::MODAL, gtk::MessageType::Info, gtk::ButtonsType::OkCancel, &gettext("Fractal’s support for encryption is unstable so you might lose access to your encrypted message history. It is recommended to backup your encryption keys from another Matrix client before proceeding."));
+ let dialog = gtk::MessageDialog::new(window.as_ref(), gtk::DialogFlags::MODAL, gtk::MessageType::Info, gtk::ButtonsType::OkCancel, &gettext("Fractal doesn't support online backup of room encryption keys so you might lose access to your encrypted message history. It is recommended to backup your encryption keys before proceeding."));
dialog.show();
dialog.connect_response(
clone!(@weak self as obj, @weak dialog => move |_, response| {
diff --git a/src/session/account_settings/mod.rs b/src/session/account_settings/mod.rs
index b50a0266..7d97a911 100644
--- a/src/session/account_settings/mod.rs
+++ b/src/session/account_settings/mod.rs
@@ -6,8 +6,10 @@ use gtk::{
};
mod devices_page;
+mod security_page;
mod user_page;
use devices_page::DevicesPage;
+use security_page::SecurityPage;
use user_page::UserPage;
use super::Session;
@@ -35,6 +37,7 @@ mod imp {
fn class_init(klass: &mut Self::Class) {
DevicesPage::static_type();
UserPage::static_type();
+ SecurityPage::static_type();
Self::bind_template(klass);
klass.install_action("account-settings.close", None, |obj, _, _| {
diff --git a/src/session/account_settings/security_page/import_export_keys_subpage.rs b/src/session/account_settings/security_page/import_export_keys_subpage.rs
new file mode 100644
index 00000000..175a2fac
--- /dev/null
+++ b/src/session/account_settings/security_page/import_export_keys_subpage.rs
@@ -0,0 +1,451 @@
+use adw::{prelude::*, subclass::prelude::*};
+use gettextrs::gettext;
+use gtk::{
+ gio,
+ glib::{self, clone},
+ CompositeTemplate,
+};
+use log::error;
+use matrix_sdk::encryption::{KeyExportError, RoomKeyImportError};
+
+use crate::{
+ components::{PasswordEntryRow, SpinnerButton},
+ i18n::ngettext_f,
+ session::Session,
+ spawn, spawn_tokio, toast,
+};
+
+#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy, glib::Enum)]
+#[repr(u32)]
+#[enum_type(name = "KeysSubpageMode")]
+pub enum KeysSubpageMode {
+ Export = 0,
+ Import = 1,
+}
+
+impl Default for KeysSubpageMode {
+ fn default() -> Self {
+ Self::Export
+ }
+}
+
+mod imp {
+ use std::cell::{Cell, RefCell};
+
+ use glib::{subclass::InitializingObject, WeakRef};
+ use once_cell::unsync::OnceCell;
+
+ use super::*;
+
+ #[derive(Debug, Default, CompositeTemplate)]
+ #[template(resource = "/org/gnome/Fractal/account-settings-import-export-keys-subpage.ui")]
+ pub struct ImportExportKeysSubpage {
+ pub session: OnceCell>,
+ #[template_child]
+ pub title: TemplateChild,
+ #[template_child]
+ pub description: TemplateChild,
+ #[template_child]
+ pub instructions: TemplateChild,
+ #[template_child]
+ pub passphrase: TemplateChild,
+ #[template_child]
+ pub confirm_passphrase: TemplateChild,
+ #[template_child]
+ pub file_row: TemplateChild,
+ #[template_child]
+ pub file_button: TemplateChild,
+ #[template_child]
+ pub proceed_button: TemplateChild,
+ pub file_path: RefCell