synpad 0.1.0

A full-featured Matrix chat client built with Dioxus
use dioxus::prelude::*;

use crate::encryption::key_export::KeyExportDialog;
use crate::encryption::qr_verification::QrVerificationDialog;
use crate::settings::account_deactivation::AccountDeactivationDialog;
use crate::state::app_state::AppState;

/// Security settings panel (E2E encryption, devices).
#[component]
pub fn SecuritySettings() -> Element {
    let state = use_context::<Signal<AppState>>();
    let mut show_key_export = use_signal(|| false);
    let mut show_qr_verification = use_signal(|| false);
    let mut show_deactivate = use_signal(|| false);
    let mut cross_signing_status = use_signal(|| "Checking...".to_string());
    let mut key_backup_status = use_signal(|| "Checking...".to_string());
    let mut identity_trusted = use_signal(|| false);
    let mut backup_active = use_signal(|| false);
    let mut is_bootstrapping = use_signal(|| false);
    let mut is_enabling_backup = use_signal(|| false);
    let mut action_error = use_signal(|| Option::<String>::None);
    let mut loaded = use_signal(|| false);

    // Load encryption status from SDK
    if !*loaded.read() {
        loaded.set(true);
        spawn(async move {
            let client = { state.read().client.clone() };
            if let Some(client) = client {
                let encryption = client.encryption();

                // Check cross-signing status
                match encryption.cross_signing_status().await {
                    Some(status) => {
                        let has_master = status.has_master;
                        let has_self_signing = status.has_self_signing;
                        let has_user_signing = status.has_user_signing;
                        if has_master && has_self_signing && has_user_signing {
                            cross_signing_status.set("Active - all keys present".to_string());
                            identity_trusted.set(true);
                        } else {
                            let mut missing = vec![];
                            if !has_master { missing.push("master"); }
                            if !has_self_signing { missing.push("self-signing"); }
                            if !has_user_signing { missing.push("user-signing"); }
                            cross_signing_status.set(format!("Partially set up (missing: {})", missing.join(", ")));
                        }
                    }
                    None => {
                        cross_signing_status.set("Not set up".to_string());
                    }
                }

                // Check key backup status
                match encryption.backups().state() {
                    matrix_sdk::encryption::backups::BackupState::Unknown => {
                        key_backup_status.set("Unknown".to_string());
                    }
                    matrix_sdk::encryption::backups::BackupState::Enabled => {
                        key_backup_status.set("Active".to_string());
                        backup_active.set(true);
                    }
                    matrix_sdk::encryption::backups::BackupState::Creating => {
                        key_backup_status.set("Creating...".to_string());
                    }
                    matrix_sdk::encryption::backups::BackupState::Resuming => {
                        key_backup_status.set("Resuming...".to_string());
                    }
                    matrix_sdk::encryption::backups::BackupState::Disabling => {
                        key_backup_status.set("Disabling...".to_string());
                    }
                    matrix_sdk::encryption::backups::BackupState::Downloading => {
                        key_backup_status.set("Downloading keys...".to_string());
                    }
                    _ => {
                        key_backup_status.set("Not set up".to_string());
                    }
                }
            }
        });
    }

    rsx! {
        div {
            class: "security-settings",

            h3 { "Security" }

            // Encryption status
            div {
                class: "settings-section",
                h4 { "End-to-End Encryption" }
                div {
                    class: "security-status",
                    span { class: "security-status__icon", "🔒" }
                    div {
                        class: "security-status__info",
                        span { class: "security-status__label", "Encryption enabled" }
                        span {
                            class: "security-status__description",
                            "Messages in encrypted rooms are secured with end-to-end encryption."
                        }
                    }
                }
            }

            // Error display
            if let Some(ref err) = *action_error.read() {
                div {
                    class: "settings-section",
                    style: "padding: 8px 12px; background: var(--error-bg, #3a1a1a); color: var(--error-text, #f44336); border-radius: 6px;",
                    "{err}"
                }
            }

            // Cross-signing
            div {
                class: "settings-section",
                h4 { "Cross-Signing" }
                div {
                    class: "security-status",
                    span {
                        class: if *identity_trusted.read() { "security-status__icon security-status__icon--ok" } else { "security-status__icon" },
                        if *identity_trusted.read() { "" } else { "⚠️" }
                    }
                    div {
                        class: "security-status__info",
                        span { class: "security-status__label", "Status: {cross_signing_status}" }
                        span {
                            class: "security-status__description",
                            "Cross-signing allows you to verify your identity across all your devices."
                        }
                    }
                }
                if !*identity_trusted.read() {
                    button {
                        class: "settings-section__action-btn",
                        style: "margin-top: 8px; padding: 8px 16px; border: none; border-radius: 6px; background: var(--accent-color, #4a9eff); color: white; cursor: pointer;",
                        disabled: *is_bootstrapping.read(),
                        onclick: move |_| {
                            is_bootstrapping.set(true);
                            action_error.set(None);
                            spawn(async move {
                                let client = { state.read().client.clone() };
                                if let Some(client) = client {
                                    match client.encryption().bootstrap_cross_signing(None).await {
                                        Ok(_) => {
                                            tracing::info!("Cross-signing bootstrapped successfully");
                                            cross_signing_status.set("Active - all keys present".to_string());
                                            identity_trusted.set(true);
                                        }
                                        Err(e) => {
                                            tracing::error!("Failed to bootstrap cross-signing: {e}");
                                            action_error.set(Some(format!("Failed to set up cross-signing: {e}")));
                                        }
                                    }
                                }
                                is_bootstrapping.set(false);
                            });
                        },
                        if *is_bootstrapping.read() { "Setting up..." } else { "Set Up Cross-Signing" }
                    }
                }
                button {
                    class: "settings-section__action-btn",
                    style: "margin-top: 8px; padding: 8px 16px; border: none; border-radius: 6px; background: var(--accent-color, #4a9eff); color: white; cursor: pointer;",
                    onclick: move |_| show_qr_verification.set(true),
                    "Verify This Device with QR"
                }
            }

            if *show_qr_verification.read() {
                QrVerificationDialog {
                    on_close: move |_| show_qr_verification.set(false),
                }
            }

            // Key Export/Import
            div {
                class: "settings-section",
                h4 { "Cryptographic Key Export / Import" }
                p {
                    class: "security-status__description",
                    "Export your end-to-end encryption keys for backup or import keys from another client."
                }
                button {
                    class: "settings-section__action-btn",
                    style: "margin-top: 8px; padding: 8px 16px; border: none; border-radius: 6px; background: var(--accent-color, #4a9eff); color: white; cursor: pointer;",
                    onclick: move |_| show_key_export.set(true),
                    "Export / Import Keys"
                }
            }

            // Key export dialog
            if *show_key_export.read() {
                KeyExportDialog {
                    on_close: move |_| show_key_export.set(false),
                }
            }

            // Key backup
            div {
                class: "settings-section",
                h4 { "Key Backup" }
                div {
                    class: "security-status",
                    span { class: "security-status__icon", "🔑" }
                    div {
                        class: "security-status__info",
                        span { class: "security-status__label", "Status: {key_backup_status}" }
                        span {
                            class: "security-status__description",
                            "Back up your encryption keys so you can restore them if you lose access to your devices."
                        }
                    }
                }
                if !*backup_active.read() {
                    button {
                        class: "settings-section__action-btn",
                        style: "margin-top: 8px; padding: 8px 16px; border: none; border-radius: 6px; background: var(--accent-color, #4a9eff); color: white; cursor: pointer;",
                        disabled: *is_enabling_backup.read(),
                        onclick: move |_| {
                            is_enabling_backup.set(true);
                            action_error.set(None);
                            spawn(async move {
                                let client = { state.read().client.clone() };
                                if let Some(client) = client {
                                    match client.encryption().backups().create().await {
                                        Ok(_) => {
                                            tracing::info!("Key backup enabled");
                                            key_backup_status.set("Active".to_string());
                                            backup_active.set(true);
                                        }
                                        Err(e) => {
                                            tracing::error!("Failed to enable key backup: {e}");
                                            action_error.set(Some(format!("Failed to enable backup: {e}")));
                                        }
                                    }
                                }
                                is_enabling_backup.set(false);
                            });
                        },
                        if *is_enabling_backup.read() { "Enabling..." } else { "Enable Key Backup" }
                    }
                }
            }

            // Account deactivation (danger zone)
            div {
                class: "settings-section settings-section--danger",
                h4 { "Danger Zone" }
                p {
                    class: "security-status__description",
                    "Deactivating your account is permanent and cannot be undone."
                }
                button {
                    class: "btn btn--danger",
                    onclick: move |_| show_deactivate.set(true),
                    "Deactivate Account"
                }
            }

            // Account deactivation dialog
            if *show_deactivate.read() {
                AccountDeactivationDialog {
                    on_close: move |_| show_deactivate.set(false),
                }
            }
        }
    }
}