🚧 Add an interface to the ChatsWindows to drive its behavior
For now, only the ChatsWindow tabs are toggled on clicks on room names (from ContactsSection).
This commit is contained in:
32
src/components/chats_window/interface.rs
Normal file
32
src/components/chats_window/interface.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
use dioxus::prelude::*;
|
||||
use matrix_sdk::ruma::OwnedRoomId;
|
||||
use tokio::sync::broadcast::error::SendError;
|
||||
use tokio::sync::broadcast::{channel, Receiver, Sender};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Tasks {
|
||||
ToggleRoom(OwnedRoomId),
|
||||
}
|
||||
|
||||
pub struct Interface {
|
||||
sender: Sender<Tasks>,
|
||||
receiver: RefCell<Receiver<Tasks>>,
|
||||
}
|
||||
|
||||
impl Interface {
|
||||
pub fn new() -> Self {
|
||||
let (sender, receiver) = channel::<Tasks>(32);
|
||||
Self {
|
||||
sender,
|
||||
receiver: RefCell::new(receiver),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn receiver(&self) -> &RefCell<Receiver<Tasks>> {
|
||||
&self.receiver
|
||||
}
|
||||
|
||||
pub fn toggle_room(&self, room_id: OwnedRoomId) -> Result<usize, SendError<Tasks>> {
|
||||
self.sender.send(Tasks::ToggleRoom(room_id))
|
||||
}
|
||||
}
|
@@ -1,56 +1,115 @@
|
||||
pub mod interface;
|
||||
|
||||
mod edit_section;
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use fermi::*;
|
||||
use tracing::debug;
|
||||
use matrix_sdk::ruma::OwnedRoomId;
|
||||
use tokio::sync::broadcast::Receiver;
|
||||
use tracing::{debug, error};
|
||||
|
||||
use crate::base::{sync_rooms, ROOMS};
|
||||
use crate::base::{sync_rooms, Room, ROOMS};
|
||||
use crate::components::avatar_selector::AvatarSelector;
|
||||
use crate::components::icons::DownArrowIcon;
|
||||
use crate::matrix_interface::requester::Receivers;
|
||||
|
||||
use edit_section::EditSection;
|
||||
use interface::{Interface, Tasks};
|
||||
|
||||
turf::style_sheet!("src/components/chats_window/chats_window.scss");
|
||||
|
||||
pub struct ChatsWindowProps {
|
||||
pub receivers: Receivers,
|
||||
pub interface: UseAtomRef<Interface>,
|
||||
}
|
||||
|
||||
fn render_rooms_tabs<'a>(
|
||||
rooms_atom_ref: &'a UseAtomRef<HashMap<OwnedRoomId, RefCell<Room>>>,
|
||||
displayed_room_ids_ref: &'a UseRef<HashSet<OwnedRoomId>>,
|
||||
) -> Vec<LazyNodes<'a, 'a>> {
|
||||
let rooms_ref = rooms_atom_ref.read();
|
||||
let displayed_room_ids = displayed_room_ids_ref.read();
|
||||
rooms_ref
|
||||
.values()
|
||||
.filter(|room| displayed_room_ids.contains(&room.borrow().id()))
|
||||
.map(|room| -> LazyNodes {
|
||||
let room = room.borrow();
|
||||
let room_name = room.name().unwrap_or(room.id().to_string());
|
||||
rsx!(
|
||||
div {
|
||||
class: ClassName::TAB,
|
||||
|
||||
button {
|
||||
img {
|
||||
src: "./images/status_online.png",
|
||||
},
|
||||
|
||||
"{room_name}",
|
||||
},
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
async fn handle_controls<'a>(
|
||||
receiver_ref: &'a RefCell<Receiver<Tasks>>,
|
||||
displayed_room_ids_ref: &'a UseRef<HashSet<OwnedRoomId>>,
|
||||
) {
|
||||
loop {
|
||||
let result = receiver_ref.borrow_mut().recv().await;
|
||||
match result {
|
||||
Ok(task) => match task {
|
||||
Tasks::ToggleRoom(room_id) => {
|
||||
error!("ON TOGGLE ROOM {}", room_id);
|
||||
let mut displayed_room_ids = displayed_room_ids_ref.write();
|
||||
match displayed_room_ids.take(&room_id) {
|
||||
Some(_) => {
|
||||
error!("Toggle {} already dispayed... close it", room_id);
|
||||
}
|
||||
None => {
|
||||
displayed_room_ids.insert(room_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
Tasks::Test(msg) => error!("TEST {}", msg),
|
||||
},
|
||||
Err(err) => error!("{}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ChatsWindow(cx: Scope<ChatsWindowProps>) -> Element {
|
||||
debug!("ChatsWindow rendering");
|
||||
|
||||
let receivers = &cx.props.receivers;
|
||||
|
||||
use_init_atom_root(cx);
|
||||
|
||||
let receivers = &cx.props.receivers;
|
||||
let interface_ref = &cx.props.interface;
|
||||
|
||||
let rooms_ref = use_atom_ref(cx, &ROOMS);
|
||||
|
||||
let displayed_room_ids = use_ref(cx, HashSet::<OwnedRoomId>::new);
|
||||
|
||||
let sync_rooms_coro = use_coroutine(cx, |rx| {
|
||||
to_owned![receivers];
|
||||
|
||||
sync_rooms(rx, receivers, rooms_ref.clone())
|
||||
});
|
||||
sync_rooms_coro.send(true);
|
||||
|
||||
let rooms = rooms_ref.read();
|
||||
let rendered_room_tabs = rooms.values().map(|room| {
|
||||
let room = room.borrow();
|
||||
let room_name = room.name().unwrap_or(room.id().to_string());
|
||||
rsx!(
|
||||
div {
|
||||
class: ClassName::TAB,
|
||||
|
||||
button {
|
||||
img {
|
||||
src: "./images/status_online.png",
|
||||
},
|
||||
|
||||
"{room_name}",
|
||||
},
|
||||
},
|
||||
)
|
||||
let _: &Coroutine<()> = use_coroutine(cx, |_: UnboundedReceiver<_>| {
|
||||
to_owned![interface_ref, displayed_room_ids];
|
||||
async move {
|
||||
let interface = interface_ref.read();
|
||||
let receiver = &interface.receiver();
|
||||
handle_controls(receiver, &displayed_room_ids).await
|
||||
}
|
||||
});
|
||||
|
||||
let rendered_rooms_tabs = render_rooms_tabs(rooms_ref, displayed_room_ids);
|
||||
|
||||
cx.render(rsx! {
|
||||
style { STYLE_SHEET },
|
||||
|
||||
@@ -60,7 +119,7 @@ pub fn ChatsWindow(cx: Scope<ChatsWindowProps>) -> Element {
|
||||
div {
|
||||
class: ClassName::TABS,
|
||||
|
||||
rendered_room_tabs.into_iter(),
|
||||
rendered_rooms_tabs.into_iter(),
|
||||
},
|
||||
|
||||
div {
|
||||
|
@@ -1,13 +1,12 @@
|
||||
use std::cell::RefCell;
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_free_icons::icons::io_icons::IoChevronDown;
|
||||
use dioxus_free_icons::Icon;
|
||||
use fermi::prelude::*;
|
||||
use matrix_sdk::RoomState;
|
||||
use matrix_sdk::{ruma::OwnedRoomId, RoomState};
|
||||
use tracing::{debug, warn};
|
||||
|
||||
use crate::base::{ByIdRooms, Room, ROOMS};
|
||||
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");
|
||||
|
||||
@@ -24,7 +23,7 @@ fn ContactsArrow(cx: Scope) -> Element {
|
||||
static NO_NAME_REPR: &str = "No name";
|
||||
static NO_SUBJECT_REPR: &str = "No subject";
|
||||
|
||||
pub fn filter_people_conversations(rooms_atom: UseAtomRef<ByIdRooms>) -> Vec<RefCell<Room>> {
|
||||
pub(super) fn filter_people_conversations(rooms_atom: UseAtomRef<ByIdRooms>) -> Vec<RefCell<Room>> {
|
||||
let rooms = rooms_atom.read();
|
||||
let mut filtered_rooms = Vec::<RefCell<Room>>::with_capacity(rooms.len());
|
||||
|
||||
@@ -37,7 +36,7 @@ pub fn filter_people_conversations(rooms_atom: UseAtomRef<ByIdRooms>) -> Vec<Ref
|
||||
filtered_rooms
|
||||
}
|
||||
|
||||
pub fn filter_room_conversations(rooms_atom: UseAtomRef<ByIdRooms>) -> Vec<RefCell<Room>> {
|
||||
pub(super) fn filter_room_conversations(rooms_atom: UseAtomRef<ByIdRooms>) -> Vec<RefCell<Room>> {
|
||||
let rooms = rooms_atom.read();
|
||||
let mut filtered_rooms = Vec::<RefCell<Room>>::with_capacity(rooms.len());
|
||||
|
||||
@@ -50,6 +49,14 @@ pub fn filter_room_conversations(rooms_atom: UseAtomRef<ByIdRooms>) -> Vec<RefCe
|
||||
filtered_rooms
|
||||
}
|
||||
|
||||
// TODO: Handle errors
|
||||
fn on_clicked_room(
|
||||
room_id: &OwnedRoomId,
|
||||
chats_window_interface: &UseAtomRef<ChatsWindowInterface>,
|
||||
) {
|
||||
let _ = chats_window_interface.read().toggle_room(room_id.clone());
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn ContactsSection<'a>(
|
||||
cx: Scope,
|
||||
@@ -58,8 +65,10 @@ pub fn ContactsSection<'a>(
|
||||
) -> Element {
|
||||
debug!("ContactsSection rendering");
|
||||
|
||||
let rooms_atom = use_atom_ref(cx, &ROOMS);
|
||||
let contacts = filter(rooms_atom.clone());
|
||||
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);
|
||||
@@ -80,6 +89,7 @@ pub fn ContactsSection<'a>(
|
||||
.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;
|
||||
|
||||
@@ -93,6 +103,8 @@ pub fn ContactsSection<'a>(
|
||||
);
|
||||
|
||||
rsx!(li {
|
||||
onclick: move |_| on_clicked_room(&room_id, chats_window_interface_ref),
|
||||
|
||||
img {
|
||||
src: "./images/status_online.png",
|
||||
},
|
||||
|
Reference in New Issue
Block a user