synpad 0.1.0

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

use crate::components::avatar::Avatar;
use crate::components::badge::UnreadBadge;
use crate::state::app_state::AppState;
use crate::utils::time_format::format_room_list_time;
use matrix_sdk::ruma::OwnedRoomId;

/// A single room entry in the room list.
#[component]
pub fn RoomListEntry(
    room_id: String,
    display_name: String,
    avatar_url: Option<String>,
    last_event_preview: Option<String>,
    last_event_sender: Option<String>,
    last_activity_ts: Option<u64>,
    unread_count: u64,
    highlight_count: u64,
    is_direct: bool,
    is_selected: bool,
) -> Element {
    let mut state = use_context::<Signal<AppState>>();
    let room_id_clone = room_id.clone();

    let on_click = move |_| {
        if let Ok(parsed) = OwnedRoomId::try_from(room_id_clone.as_str()) {
            state.write().active_room_id = Some(parsed);
        }
    };

    let class = if is_selected {
        "room-list-entry room-list-entry--selected"
    } else if unread_count > 0 {
        "room-list-entry room-list-entry--unread"
    } else {
        "room-list-entry"
    };

    let preview_text = last_event_preview
        .unwrap_or_default();

    let time_text = last_activity_ts
        .map(format_room_list_time)
        .unwrap_or_default();

    rsx! {
        div {
            class: "{class}",
            onclick: on_click,

            // Avatar with presence indicator (#47)
            div {
                class: "room-list-entry__avatar-wrapper",
                Avatar {
                    name: display_name.clone(),
                    url: avatar_url,
                    size: 40,
                }
                if is_direct {
                    span { class: "room-list-entry__presence-dot room-list-entry__presence-dot--online" }
                }
            }

            // Room info
            div {
                class: "room-list-entry__info",
                div {
                    class: "room-list-entry__top-row",
                    span {
                        class: "room-list-entry__name",
                        "{display_name}"
                    }
                    if !time_text.is_empty() {
                        span {
                            class: "room-list-entry__time",
                            "{time_text}"
                        }
                    }
                }
                div {
                    class: "room-list-entry__bottom-row",
                    span {
                        class: "room-list-entry__preview",
                        "{preview_text}"
                    }
                    if unread_count > 0 {
                        UnreadBadge {
                            count: unread_count,
                            highlight: highlight_count > 0,
                        }
                    }
                }
            }
        }
    }
}