use dioxus::prelude::*; use dioxus_free_icons::icons::io_icons::IoChevronDown; use dioxus_free_icons::Icon; use fermi::prelude::*; use matrix_sdk::{ruma::OwnedRoomId, RoomState}; use tracing::{debug, warn}; use crate::base::{ByIdRooms, Room, CHATS_WIN_INTERFACE, ROOMS}; use crate::components::chats_window::interface::Interface as ChatsWindowInterface; turf::style_sheet!("src/components/contacts_window/contacts_section.scss"); fn ContactsArrow(cx: Scope) -> Element { cx.render(rsx! { style { STYLE_SHEET }, Icon { icon: IoChevronDown, }, }) } static NO_NAME_REPR: &str = "No name"; static NO_SUBJECT_REPR: &str = "No subject"; pub(super) fn filter_people_conversations(rooms_atom: UseAtomRef) -> Vec> { let rooms = rooms_atom.read(); let mut filtered_rooms = Vec::>::with_capacity(rooms.len()); for room in rooms.values() { let is_direct = room.borrow().is_direct.unwrap(); if !is_direct { filtered_rooms.push(room.to_owned()); } } filtered_rooms } pub(super) fn filter_room_conversations(rooms_atom: UseAtomRef) -> Vec> { let rooms = rooms_atom.read(); let mut filtered_rooms = Vec::>::with_capacity(rooms.len()); for room in rooms.values() { let is_direct = room.borrow().is_direct.unwrap(); if is_direct { filtered_rooms.push(room.to_owned()); } } filtered_rooms } // TODO: Handle errors fn on_clicked_room( room_id: &OwnedRoomId, chats_window_interface: &UseAtomRef, ) { let _ = chats_window_interface.read().toggle_room(room_id.clone()); } #[component] pub fn ContactsSection<'a>( cx: Scope, name: &'a str, filter: &'a dyn Fn(UseAtomRef) -> Vec>, ) -> Element { debug!("ContactsSection rendering"); let rooms_atom_ref = use_atom_ref(cx, &ROOMS); let chats_window_interface_ref = use_atom_ref(cx, &CHATS_WIN_INTERFACE); let contacts = filter(rooms_atom_ref.clone()); let contacts_len = contacts.len(); let show = use_state(cx, || false); let classes = [ ClassName::SECTION, if **show { ClassName::ACTIVE } else { "" }, ] .join(" "); let rendered_contacts = contacts.into_iter().map(|room_ref| { let room = room_ref.borrow(); let room_topic = room .topic .as_ref() .unwrap_or(&RefCell::new(NO_SUBJECT_REPR.to_string())) .borrow() .to_owned(); let room_name = room.name().unwrap_or(NO_NAME_REPR.to_string()); let room_id = room.id(); let is_invited = room.matrix_room.state() == RoomState::Invited; let formatted = format!( "{room_name} - {}", if is_invited { "Invited - ".to_string() } else { "".to_string() } ); rsx!(li { onclick: move |_| on_clicked_room(&room_id, chats_window_interface_ref), img { src: "./images/status_online.png", }, p { formatted, }, p { style: "color: darkgrey;", room_topic, }, }) }); cx.render(rsx! { style { STYLE_SHEET }, div { class: "{classes}", p { class: ClassName::HEADER, onclick: move |_| show.set(!show), ContactsArrow {}, format!("{name} ({contacts_len})"), }, ul { rendered_contacts.into_iter(), }, }, }) }