synpad 0.1.0

A full-featured Matrix chat client built with Dioxus
use dioxus::prelude::*;
use matrix_sdk::ruma::{OwnedEventId, OwnedRoomId};

use crate::components::modal::Modal;
use crate::state::app_state::AppState;

/// Dialog for reporting a message to the homeserver.
#[component]
pub fn ReportDialog(
    room_id: String,
    event_id: String,
    on_close: EventHandler<()>,
) -> Element {
    let state = use_context::<Signal<AppState>>();
    let mut reason = use_signal(|| String::new());
    let mut is_reporting = use_signal(|| false);
    let mut report_status = use_signal(|| Option::<Result<(), String>>::None);

    rsx! {
        Modal {
            title: "Report Content".to_string(),
            on_close: move |_| on_close.call(()),

            div {
                class: "report-dialog",

                p {
                    class: "report-dialog__info",
                    "Report this message to your homeserver administrator. The message content and sender information will be included."
                }

                if let Some(ref result) = *report_status.read() {
                    match result {
                        Ok(()) => rsx! {
                            div {
                                class: "report-dialog__success",
                                "Report submitted successfully. Thank you."
                            }
                        },
                        Err(e) => rsx! {
                            div {
                                class: "report-dialog__error",
                                "{e}"
                            }
                        },
                    }
                }

                div {
                    class: "report-dialog__field",
                    label { "Reason (optional)" }
                    textarea {
                        class: "report-dialog__reason",
                        placeholder: "Why are you reporting this content?",
                        value: "{reason}",
                        oninput: move |evt| reason.set(evt.value()),
                        rows: "4",
                    }
                }

                div {
                    class: "report-dialog__actions",
                    button {
                        class: "btn btn--secondary",
                        onclick: move |_| on_close.call(()),
                        "Cancel"
                    }
                    button {
                        class: "btn btn--danger",
                        disabled: *is_reporting.read(),
                        onclick: move |_| {
                            let rid = room_id.clone();
                            let eid = event_id.clone();
                            let r = reason.read().clone();
                            is_reporting.set(true);
                            spawn(async move {
                                let client = { state.read().client.clone() };
                                if let Some(client) = client {
                                    if let (Ok(room_id), Ok(event_id)) = (
                                        OwnedRoomId::try_from(rid.as_str()),
                                        OwnedEventId::try_from(eid.as_str()),
                                    ) {
                                        if let Some(_room) = client.get_room(&room_id) {
                                            use matrix_sdk::ruma::api::client::room::report_content::v3::Request;
                                            use matrix_sdk::ruma::int;
                                            let reason_opt = if r.is_empty() { None } else { Some(r) };
                                            let request = Request::new(room_id, event_id, Some(int!(-100)), reason_opt);
                                            match client.send(request).await {
                                                Ok(_) => {
                                                    report_status.set(Some(Ok(())));
                                                }
                                                Err(e) => {
                                                    report_status.set(Some(Err(format!("Report failed: {e}"))));
                                                }
                                            }
                                        }
                                    }
                                }
                                is_reporting.set(false);
                            });
                        },
                        if *is_reporting.read() { "Reporting..." } else { "Report" }
                    }
                }
            }
        }
    }
}