synpad 0.1.0

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

/// Maximum character length before a reply is considered "long" and becomes collapsible.
const REPLY_TRUNCATE_THRESHOLD: usize = 200;

/// Reply preview shown above a message that is a reply.
/// Long replies (over 200 chars) are automatically truncated with a "Show more" toggle.
#[component]
pub fn ReplyPreviewComponent(sender_name: String, body: String) -> Element {
    let mut expanded = use_signal(|| false);
    let is_long = body.len() > REPLY_TRUNCATE_THRESHOLD;
    let is_expanded = expanded();

    let display_body = if is_long && !is_expanded {
        let truncated: String = body.chars().take(REPLY_TRUNCATE_THRESHOLD).collect();
        let mut result = truncated;
        result.push_str("...");
        result
    } else {
        body.clone()
    };

    let body_class = if is_long && !is_expanded {
        "reply-preview__body reply-preview__body--truncated"
    } else {
        "reply-preview__body reply-preview__body--expanded"
    };

    let toggle_label = if is_expanded {
        "Show less"
    } else {
        "Show more"
    };

    rsx! {
        div {
            class: "reply-preview",
            div { class: "reply-preview__bar" }
            div {
                class: "reply-preview__content",
                span {
                    class: "reply-preview__sender",
                    "{sender_name}"
                }
                span {
                    class: "{body_class}",
                    "{display_body}"
                }
                if is_long {
                    button {
                        class: "reply-preview__toggle",
                        onclick: move |evt| {
                            evt.stop_propagation();
                            let current = expanded();
                            expanded.set(!current);
                        },
                        "{toggle_label}"
                    }
                }
            }
        }
    }
}