synpad 0.1.0

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

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

/// Known integration/widget types.
static INTEGRATIONS: &[(&str, &str, &str)] = &[
    ("jitsi", "Jitsi Meet", "Video conferencing widget"),
    ("etherpad", "Etherpad", "Collaborative text editing"),
    ("youtube", "YouTube", "YouTube video player"),
    ("grafana", "Grafana", "Dashboard monitoring"),
    ("custom", "Custom Widget", "Add a custom widget by URL"),
];

/// Integration manager dialog for adding/managing widgets in a room.
#[component]
pub fn IntegrationManagerDialog(room_id: String, on_close: EventHandler<()>) -> Element {
    let state = use_context::<Signal<AppState>>();
    let mut selected_type = use_signal(|| Option::<String>::None);
    let mut widget_url = use_signal(|| String::new());
    let mut widget_name = use_signal(|| String::new());
    let mut adding = use_signal(|| false);

    let rid = room_id.clone();
    let on_add_widget = move |_| {
        let url = widget_url.read().trim().to_string();
        let name = widget_name.read().trim().to_string();
        let wtype = selected_type.read().clone().unwrap_or_else(|| "custom".to_string());

        if url.is_empty() || name.is_empty() {
            return;
        }

        adding.set(true);
        let rid = rid.clone();
        spawn(async move {
            let client = { state.read().client.clone() };
            if let Some(client) = client {
                if let Ok(room_id) = matrix_sdk::ruma::OwnedRoomId::try_from(rid.as_str()) {
                    if let Some(room) = client.get_room(&room_id) {
                        // In a full implementation, we'd send an im.vector.modular.widgets
                        // state event to add the widget
                        tracing::info!(
                            "Adding widget '{}' ({}) to room {}: {}",
                            name, wtype, room_id, url
                        );

                        // Send a notice about the widget
                        use matrix_sdk::ruma::events::room::message::RoomMessageEventContent;
                        let msg = RoomMessageEventContent::notice_plain(
                            format!("Added widget: {name}")
                        );
                        let _ = room.send(msg).await;
                    }
                }
            }
            adding.set(false);
            widget_url.set(String::new());
            widget_name.set(String::new());
            selected_type.set(None);
        });
    };

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

            div {
                class: "integration-manager",

                // Available integrations
                div {
                    class: "integration-manager__section",
                    h4 { "Available Integrations" }
                    div {
                        class: "integration-manager__list",
                        for (id, name, desc) in INTEGRATIONS.iter() {
                            {
                                let id = id.to_string();
                                let name = name.to_string();
                                let desc = desc.to_string();
                                let is_selected = selected_type.read().as_ref() == Some(&id);
                                rsx! {
                                    button {
                                        class: if is_selected {
                                            "integration-manager__item integration-manager__item--selected"
                                        } else {
                                            "integration-manager__item"
                                        },
                                        onclick: move |_| {
                                            selected_type.set(Some(id.clone()));
                                            if widget_name.read().is_empty() {
                                                widget_name.set(name.clone());
                                            }
                                        },
                                        div {
                                            class: "integration-manager__item-info",
                                            strong { "{name}" }
                                            p { "{desc}" }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                // Add widget form
                if selected_type.read().is_some() {
                    div {
                        class: "integration-manager__form",
                        h4 { "Add Widget" }
                        div {
                            class: "integration-manager__field",
                            label { "Widget name" }
                            input {
                                r#type: "text",
                                class: "settings-input",
                                placeholder: "My Widget",
                                value: "{widget_name}",
                                oninput: move |evt| widget_name.set(evt.value()),
                            }
                        }
                        div {
                            class: "integration-manager__field",
                            label { "Widget URL" }
                            input {
                                r#type: "url",
                                class: "settings-input",
                                placeholder: "https://...",
                                value: "{widget_url}",
                                oninput: move |evt| widget_url.set(evt.value()),
                            }
                        }
                        div {
                            class: "integration-manager__actions",
                            button {
                                class: "btn btn--secondary",
                                onclick: move |_| {
                                    selected_type.set(None);
                                    widget_url.set(String::new());
                                    widget_name.set(String::new());
                                },
                                "Cancel"
                            }
                            button {
                                class: "btn btn--primary",
                                disabled: widget_url.read().is_empty() || widget_name.read().is_empty() || *adding.read(),
                                onclick: on_add_widget,
                                if *adding.read() { "Adding..." } else { "Add Widget" }
                            }
                        }
                    }
                }
            }
        }
    }
}