synpad 0.1.0

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

use crate::room_list::room_filter::RoomFilterTabs;
use crate::room_list::room_list_entry::RoomListEntry;
use crate::room_list::room_list_header::RoomListHeader;
use crate::state::app_state::AppState;

/// Room list panel component (left sidebar content).
#[component]
pub fn RoomListPanel() -> Element {
    let state = use_context::<Signal<AppState>>();
    let state_read = state.read();

    let sorted_ids = state_read.sorted_room_ids.clone();
    let rooms = &state_read.rooms;

    // Separate DMs from group rooms when filter is "All" (#49)
    let show_sections = matches!(state_read.room_filter, crate::state::room_state::RoomFilter::All);
    let mut dm_ids = Vec::new();
    let mut group_ids = Vec::new();
    if show_sections {
        for rid in sorted_ids.iter() {
            if let Some(room) = rooms.get(rid) {
                if room.is_direct {
                    dm_ids.push(rid.clone());
                } else {
                    group_ids.push(rid.clone());
                }
            }
        }
    }

    rsx! {
        div {
            class: "room-list-panel",

            RoomListHeader {}
            RoomFilterTabs {}

            div {
                class: "room-list-panel__list",
                if sorted_ids.is_empty() {
                    div {
                        class: "room-list-panel__empty",
                        p { "No rooms yet" }
                        p {
                            class: "room-list-panel__empty-hint",
                            "Join a room or start a conversation"
                        }
                    }
                }

                if show_sections {
                    // Rooms section
                    if !group_ids.is_empty() {
                        div {
                            class: "room-list-panel__section-header",
                            span { "Rooms" }
                            span { class: "room-list-panel__section-count", "{group_ids.len()}" }
                        }
                        for room_id in group_ids.iter() {
                            if let Some(room) = rooms.get(room_id) {
                                RoomListEntry {
                                    key: "{room_id}",
                                    room_id: room_id.to_string(),
                                    display_name: room.display_name.clone(),
                                    avatar_url: room.avatar_url.clone(),
                                    last_event_preview: room.last_event_preview.clone(),
                                    last_event_sender: room.last_event_sender.clone(),
                                    last_activity_ts: room.last_activity_ts,
                                    unread_count: room.unread_count,
                                    highlight_count: room.highlight_count,
                                    is_direct: room.is_direct,
                                    is_selected: state_read.active_room_id.as_ref().map(|id| id.to_string()) == Some(room_id.to_string()),
                                }
                            }
                        }
                    }

                    // DMs section
                    if !dm_ids.is_empty() {
                        div {
                            class: "room-list-panel__section-header",
                            span { "Direct Messages" }
                            span { class: "room-list-panel__section-count", "{dm_ids.len()}" }
                        }
                        for room_id in dm_ids.iter() {
                            if let Some(room) = rooms.get(room_id) {
                                RoomListEntry {
                                    key: "{room_id}",
                                    room_id: room_id.to_string(),
                                    display_name: room.display_name.clone(),
                                    avatar_url: room.avatar_url.clone(),
                                    last_event_preview: room.last_event_preview.clone(),
                                    last_event_sender: room.last_event_sender.clone(),
                                    last_activity_ts: room.last_activity_ts,
                                    unread_count: room.unread_count,
                                    highlight_count: room.highlight_count,
                                    is_direct: room.is_direct,
                                    is_selected: state_read.active_room_id.as_ref().map(|id| id.to_string()) == Some(room_id.to_string()),
                                }
                            }
                        }
                    }
                } else {
                    for room_id in sorted_ids.iter() {
                        if let Some(room) = rooms.get(room_id) {
                            RoomListEntry {
                                key: "{room_id}",
                                room_id: room_id.to_string(),
                                display_name: room.display_name.clone(),
                                avatar_url: room.avatar_url.clone(),
                                last_event_preview: room.last_event_preview.clone(),
                                last_event_sender: room.last_event_sender.clone(),
                                last_activity_ts: room.last_activity_ts,
                                unread_count: room.unread_count,
                                highlight_count: room.highlight_count,
                                is_direct: room.is_direct,
                                is_selected: state_read.active_room_id.as_ref().map(|id| id.to_string()) == Some(room_id.to_string()),
                            }
                        }
                    }
                }
            }
        }
    }
}