synpad 0.1.0

A full-featured Matrix chat client built with Dioxus
use crate::state::room_state::TimelineContent;
use crate::utils::html_render::strip_html;

/// Generate a short preview text for a timeline event, suitable for the room list.
pub fn event_preview_text(content: &TimelineContent, sender_name: &str) -> String {
    match content {
        TimelineContent::Text { body, .. } => {
            let clean = strip_html(body);
            let truncated = truncate_text(&clean, 100);
            format!("{sender_name}: {truncated}")
        }
        TimelineContent::Image { .. } => {
            format!("{sender_name}: sent an image")
        }
        TimelineContent::File { .. } => {
            format!("{sender_name}: sent a file")
        }
        TimelineContent::Audio { .. } => {
            format!("{sender_name}: sent an audio message")
        }
        TimelineContent::Video { .. } => {
            format!("{sender_name}: sent a video")
        }
        TimelineContent::Emote { body, .. } => {
            let clean = strip_html(body);
            format!("* {sender_name} {}", truncate_text(&clean, 100))
        }
        TimelineContent::Notice { body, .. } => {
            let clean = strip_html(body);
            truncate_text(&clean, 100).to_string()
        }
        TimelineContent::StateEvent { description } => {
            description.clone()
        }
        TimelineContent::Redacted { .. } => {
            "Message deleted".to_string()
        }
        TimelineContent::EncryptionError { .. } => {
            "Unable to decrypt message".to_string()
        }
        TimelineContent::Sticker { .. } => {
            format!("{sender_name}: sent a sticker")
        }
        TimelineContent::Poll { question, .. } => {
            format!("{sender_name}: created a poll: {}", truncate_text(question, 80))
        }
        TimelineContent::Location { .. } => {
            format!("{sender_name}: shared a location")
        }
        TimelineContent::VoiceMessage { .. } => {
            format!("{sender_name}: sent a voice message")
        }
    }
}

/// Truncate text to a maximum length, adding "..." if truncated.
fn truncate_text(text: &str, max_len: usize) -> &str {
    if text.len() <= max_len {
        text
    } else {
        // Find a safe truncation point (don't break UTF-8)
        let mut end = max_len;
        while !text.is_char_boundary(end) && end > 0 {
            end -= 1;
        }
        &text[..end]
    }
}