🚧 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:
22
src/base.rs
22
src/base.rs
@@ -3,7 +3,7 @@
|
|||||||
// (used by [UnboundedReceiver]) by adding 'futures_util' as a dependency to your project
|
// (used by [UnboundedReceiver]) by adding 'futures_util' as a dependency to your project
|
||||||
// and adding the use futures_util::stream::StreamExt;
|
// and adding the use futures_util::stream::StreamExt;
|
||||||
use futures_util::stream::StreamExt;
|
use futures_util::stream::StreamExt;
|
||||||
use std::{cell::RefCell, collections::HashMap, sync::Arc};
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use fermi::*;
|
use fermi::*;
|
||||||
@@ -15,9 +15,9 @@ use matrix_sdk::{
|
|||||||
use tokio::select;
|
use tokio::select;
|
||||||
use tracing::{debug, error, warn};
|
use tracing::{debug, error, warn};
|
||||||
|
|
||||||
|
use crate::components::chats_window::interface::Interface as ChatsWinInterface;
|
||||||
use crate::matrix_interface::client::{Client, RoomTopicEvent};
|
use crate::matrix_interface::client::{Client, RoomTopicEvent};
|
||||||
use crate::matrix_interface::requester::Receivers;
|
use crate::matrix_interface::requester::{Receivers, Requester};
|
||||||
use crate::matrix_interface::requester::Requester;
|
|
||||||
use crate::matrix_interface::worker_tasks::LoginStyle;
|
use crate::matrix_interface::worker_tasks::LoginStyle;
|
||||||
|
|
||||||
// #[derive(Clone, Debug)]
|
// #[derive(Clone, Debug)]
|
||||||
@@ -41,7 +41,7 @@ use crate::matrix_interface::worker_tasks::LoginStyle;
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone)]
|
||||||
pub struct Room {
|
pub struct Room {
|
||||||
pub matrix_room: Arc<MatrixRoom>,
|
pub matrix_room: Arc<MatrixRoom>,
|
||||||
pub topic: Option<RefCell<String>>,
|
pub topic: Option<RefCell<String>>,
|
||||||
@@ -186,10 +186,7 @@ pub async fn login(
|
|||||||
app_settings_ref: UseAtomRef<AppSettings>,
|
app_settings_ref: UseAtomRef<AppSettings>,
|
||||||
session_ref: UseAtomRef<Session>,
|
session_ref: UseAtomRef<Session>,
|
||||||
) {
|
) {
|
||||||
error!("=== LOGIN BEG ===");
|
|
||||||
|
|
||||||
while let Some(is_logged) = rx.next().await {
|
while let Some(is_logged) = rx.next().await {
|
||||||
error!("State updated");
|
|
||||||
if !is_logged {
|
if !is_logged {
|
||||||
let homeserver_url = session_ref.read().homeserver_url.clone();
|
let homeserver_url = session_ref.read().homeserver_url.clone();
|
||||||
let username = session_ref.read().username.clone();
|
let username = session_ref.read().username.clone();
|
||||||
@@ -198,9 +195,12 @@ pub async fn login(
|
|||||||
if homeserver_url.is_some() && username.is_some() && password.is_some() {
|
if homeserver_url.is_some() && username.is_some() && password.is_some() {
|
||||||
let client = Client::spawn(homeserver_url.unwrap()).await;
|
let client = Client::spawn(homeserver_url.unwrap()).await;
|
||||||
|
|
||||||
client.init();
|
client.init().await;
|
||||||
|
|
||||||
match client.login(LoginStyle::Password(username.unwrap(), password.unwrap())) {
|
match client
|
||||||
|
.login(LoginStyle::Password(username.unwrap(), password.unwrap()))
|
||||||
|
.await
|
||||||
|
{
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
debug!("successfully logged");
|
debug!("successfully logged");
|
||||||
session_ref.write().is_logged = true;
|
session_ref.write().is_logged = true;
|
||||||
@@ -221,8 +221,6 @@ pub async fn login(
|
|||||||
error!("=== LOGIN END ===");
|
error!("=== LOGIN END ===");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static ROOMS: AtomRef<ByIdRooms> = AtomRef(|_| ByIdRooms::new());
|
|
||||||
|
|
||||||
pub struct Session {
|
pub struct Session {
|
||||||
pub homeserver_url: Option<String>,
|
pub homeserver_url: Option<String>,
|
||||||
pub username: Option<String>,
|
pub username: Option<String>,
|
||||||
@@ -250,4 +248,6 @@ impl Session {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub static ROOMS: AtomRef<ByIdRooms> = AtomRef(|_| ByIdRooms::new());
|
||||||
pub static SESSION: AtomRef<Session> = AtomRef(|_| Session::new());
|
pub static SESSION: AtomRef<Session> = AtomRef(|_| Session::new());
|
||||||
|
pub static CHATS_WIN_INTERFACE: AtomRef<ChatsWinInterface> = AtomRef(|_| ChatsWinInterface::new());
|
||||||
|
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;
|
mod edit_section;
|
||||||
|
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use fermi::*;
|
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::avatar_selector::AvatarSelector;
|
||||||
use crate::components::icons::DownArrowIcon;
|
use crate::components::icons::DownArrowIcon;
|
||||||
use crate::matrix_interface::requester::Receivers;
|
use crate::matrix_interface::requester::Receivers;
|
||||||
|
|
||||||
use edit_section::EditSection;
|
use edit_section::EditSection;
|
||||||
|
use interface::{Interface, Tasks};
|
||||||
|
|
||||||
turf::style_sheet!("src/components/chats_window/chats_window.scss");
|
turf::style_sheet!("src/components/chats_window/chats_window.scss");
|
||||||
|
|
||||||
pub struct ChatsWindowProps {
|
pub struct ChatsWindowProps {
|
||||||
pub receivers: Receivers,
|
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 {
|
pub fn ChatsWindow(cx: Scope<ChatsWindowProps>) -> Element {
|
||||||
debug!("ChatsWindow rendering");
|
debug!("ChatsWindow rendering");
|
||||||
|
|
||||||
let receivers = &cx.props.receivers;
|
|
||||||
|
|
||||||
use_init_atom_root(cx);
|
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 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| {
|
let sync_rooms_coro = use_coroutine(cx, |rx| {
|
||||||
to_owned![receivers];
|
to_owned![receivers];
|
||||||
|
|
||||||
sync_rooms(rx, receivers, rooms_ref.clone())
|
sync_rooms(rx, receivers, rooms_ref.clone())
|
||||||
});
|
});
|
||||||
sync_rooms_coro.send(true);
|
sync_rooms_coro.send(true);
|
||||||
|
|
||||||
let rooms = rooms_ref.read();
|
let _: &Coroutine<()> = use_coroutine(cx, |_: UnboundedReceiver<_>| {
|
||||||
let rendered_room_tabs = rooms.values().map(|room| {
|
to_owned![interface_ref, displayed_room_ids];
|
||||||
let room = room.borrow();
|
async move {
|
||||||
let room_name = room.name().unwrap_or(room.id().to_string());
|
let interface = interface_ref.read();
|
||||||
rsx!(
|
let receiver = &interface.receiver();
|
||||||
div {
|
handle_controls(receiver, &displayed_room_ids).await
|
||||||
class: ClassName::TAB,
|
}
|
||||||
|
|
||||||
button {
|
|
||||||
img {
|
|
||||||
src: "./images/status_online.png",
|
|
||||||
},
|
|
||||||
|
|
||||||
"{room_name}",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let rendered_rooms_tabs = render_rooms_tabs(rooms_ref, displayed_room_ids);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
style { STYLE_SHEET },
|
style { STYLE_SHEET },
|
||||||
|
|
||||||
@@ -60,7 +119,7 @@ pub fn ChatsWindow(cx: Scope<ChatsWindowProps>) -> Element {
|
|||||||
div {
|
div {
|
||||||
class: ClassName::TABS,
|
class: ClassName::TABS,
|
||||||
|
|
||||||
rendered_room_tabs.into_iter(),
|
rendered_rooms_tabs.into_iter(),
|
||||||
},
|
},
|
||||||
|
|
||||||
div {
|
div {
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
use std::cell::RefCell;
|
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use dioxus_free_icons::icons::io_icons::IoChevronDown;
|
use dioxus_free_icons::icons::io_icons::IoChevronDown;
|
||||||
use dioxus_free_icons::Icon;
|
use dioxus_free_icons::Icon;
|
||||||
use fermi::prelude::*;
|
use fermi::prelude::*;
|
||||||
use matrix_sdk::RoomState;
|
use matrix_sdk::{ruma::OwnedRoomId, RoomState};
|
||||||
use tracing::{debug, warn};
|
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");
|
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_NAME_REPR: &str = "No name";
|
||||||
static NO_SUBJECT_REPR: &str = "No subject";
|
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 rooms = rooms_atom.read();
|
||||||
let mut filtered_rooms = Vec::<RefCell<Room>>::with_capacity(rooms.len());
|
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
|
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 rooms = rooms_atom.read();
|
||||||
let mut filtered_rooms = Vec::<RefCell<Room>>::with_capacity(rooms.len());
|
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
|
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]
|
#[component]
|
||||||
pub fn ContactsSection<'a>(
|
pub fn ContactsSection<'a>(
|
||||||
cx: Scope,
|
cx: Scope,
|
||||||
@@ -58,8 +65,10 @@ pub fn ContactsSection<'a>(
|
|||||||
) -> Element {
|
) -> Element {
|
||||||
debug!("ContactsSection rendering");
|
debug!("ContactsSection rendering");
|
||||||
|
|
||||||
let rooms_atom = use_atom_ref(cx, &ROOMS);
|
let rooms_atom_ref = use_atom_ref(cx, &ROOMS);
|
||||||
let contacts = filter(rooms_atom.clone());
|
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 contacts_len = contacts.len();
|
||||||
|
|
||||||
let show = use_state(cx, || false);
|
let show = use_state(cx, || false);
|
||||||
@@ -80,6 +89,7 @@ pub fn ContactsSection<'a>(
|
|||||||
.borrow()
|
.borrow()
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let room_name = room.name().unwrap_or(NO_NAME_REPR.to_string());
|
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 is_invited = room.matrix_room.state() == RoomState::Invited;
|
||||||
|
|
||||||
@@ -93,6 +103,8 @@ pub fn ContactsSection<'a>(
|
|||||||
);
|
);
|
||||||
|
|
||||||
rsx!(li {
|
rsx!(li {
|
||||||
|
onclick: move |_| on_clicked_room(&room_id, chats_window_interface_ref),
|
||||||
|
|
||||||
img {
|
img {
|
||||||
src: "./images/status_online.png",
|
src: "./images/status_online.png",
|
||||||
},
|
},
|
||||||
|
16
src/main.rs
16
src/main.rs
@@ -1,14 +1,15 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
pub mod components;
|
||||||
|
pub mod matrix_interface;
|
||||||
|
pub mod utils;
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use dioxus_desktop::Config;
|
use dioxus_desktop::Config;
|
||||||
use fermi::*;
|
use fermi::*;
|
||||||
use tracing::{debug, Level};
|
use tracing::{debug, Level};
|
||||||
|
|
||||||
pub mod components;
|
use crate::base::{login, sync_rooms, APP_SETTINGS, CHATS_WIN_INTERFACE, ROOMS, SESSION};
|
||||||
pub mod matrix_interface;
|
|
||||||
|
|
||||||
use crate::base::{login, sync_rooms, APP_SETTINGS, ROOMS, SESSION};
|
|
||||||
use crate::components::chats_window::{ChatsWindow, ChatsWindowProps};
|
use crate::components::chats_window::{ChatsWindow, ChatsWindowProps};
|
||||||
use crate::components::main_window::MainWindow;
|
use crate::components::main_window::MainWindow;
|
||||||
|
|
||||||
@@ -22,6 +23,7 @@ fn App(cx: Scope) -> Element {
|
|||||||
let app_settings_ref = use_atom_ref(cx, &APP_SETTINGS);
|
let app_settings_ref = use_atom_ref(cx, &APP_SETTINGS);
|
||||||
let session_ref = use_atom_ref(cx, &SESSION);
|
let session_ref = use_atom_ref(cx, &SESSION);
|
||||||
let rooms_ref = use_atom_ref(cx, &ROOMS);
|
let rooms_ref = use_atom_ref(cx, &ROOMS);
|
||||||
|
let chats_win_interface_ref = use_atom_ref(cx, &CHATS_WIN_INTERFACE);
|
||||||
|
|
||||||
let chats_win_state = use_state(cx, || None);
|
let chats_win_state = use_state(cx, || None);
|
||||||
|
|
||||||
@@ -55,7 +57,11 @@ fn App(cx: Scope) -> Element {
|
|||||||
.borrow()
|
.borrow()
|
||||||
.receivers
|
.receivers
|
||||||
.clone();
|
.clone();
|
||||||
let chats_props = ChatsWindowProps { receivers };
|
|
||||||
|
let chats_props = ChatsWindowProps {
|
||||||
|
receivers,
|
||||||
|
interface: chats_win_interface_ref.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
let chats_dom = VirtualDom::new_with_props(ChatsWindow, chats_props);
|
let chats_dom = VirtualDom::new_with_props(ChatsWindow, chats_props);
|
||||||
|
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
use std::cell::RefCell;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use dioxus::prelude::to_owned;
|
use dioxus::prelude::*;
|
||||||
use tokio::sync::broadcast::Sender;
|
use tokio::sync::broadcast::Sender;
|
||||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
|
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
|
||||||
use tokio::sync::{broadcast, oneshot};
|
use tokio::sync::{broadcast, oneshot};
|
||||||
@@ -157,12 +156,10 @@ impl Client {
|
|||||||
|
|
||||||
async fn on_original_sync_room_member_event(
|
async fn on_original_sync_room_member_event(
|
||||||
_ev: OriginalSyncRoomMemberEvent,
|
_ev: OriginalSyncRoomMemberEvent,
|
||||||
room: MatrixRoom,
|
_room: MatrixRoom,
|
||||||
_client: MatrixClient,
|
_client: MatrixClient,
|
||||||
) {
|
) {
|
||||||
debug!("== on_original_sync_room_member_event ==");
|
debug!("== on_original_sync_room_member_event ==");
|
||||||
let room_id = room.room_id();
|
|
||||||
dbg!(room_id);
|
|
||||||
|
|
||||||
// let mut store = store_ctx.read().unwrap().to_owned();
|
// let mut store = store_ctx.read().unwrap().to_owned();
|
||||||
// dbg!(store.rooms.keys());
|
// dbg!(store.rooms.keys());
|
||||||
@@ -403,11 +400,11 @@ impl Client {
|
|||||||
WorkerTask::Init(reply) => {
|
WorkerTask::Init(reply) => {
|
||||||
assert!(!self.initialized);
|
assert!(!self.initialized);
|
||||||
self.init();
|
self.init();
|
||||||
reply.send(());
|
reply.send(()).await;
|
||||||
}
|
}
|
||||||
WorkerTask::Login(style, reply) => {
|
WorkerTask::Login(style, reply) => {
|
||||||
assert!(self.initialized);
|
assert!(self.initialized);
|
||||||
reply.send(self.login_and_sync(style).await);
|
reply.send(self.login_and_sync(style).await).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,15 +1,15 @@
|
|||||||
use std::cell::RefCell;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use dioxus::prelude::*;
|
||||||
use matrix_sdk::Client as MatrixClient;
|
use matrix_sdk::Client as MatrixClient;
|
||||||
use tokio::sync::broadcast::Receiver;
|
use tokio::sync::broadcast::Receiver;
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
|
|
||||||
use super::client::RoomTopicEvent;
|
use super::client::RoomTopicEvent;
|
||||||
use super::worker_tasks::{oneshot, LoginStyle, WorkerTask};
|
use super::worker_tasks::{LoginStyle, WorkerTask};
|
||||||
use crate::base::Room;
|
use crate::base::Room;
|
||||||
|
use crate::utils::oneshot;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Receivers {
|
pub struct Receivers {
|
||||||
pub rooms_receiver: RefCell<Receiver<Room>>,
|
pub rooms_receiver: RefCell<Receiver<Room>>,
|
||||||
pub room_topic_receiver: RefCell<Receiver<RoomTopicEvent>>,
|
pub room_topic_receiver: RefCell<Receiver<RoomTopicEvent>>,
|
||||||
@@ -24,7 +24,6 @@ impl Clone for Receivers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Requester {
|
pub struct Requester {
|
||||||
pub matrix_client: Arc<MatrixClient>,
|
pub matrix_client: Arc<MatrixClient>,
|
||||||
pub tx: UnboundedSender<WorkerTask>,
|
pub tx: UnboundedSender<WorkerTask>,
|
||||||
@@ -32,15 +31,23 @@ pub struct Requester {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Requester {
|
impl Requester {
|
||||||
pub fn init(&self) {
|
pub async fn init(&self) -> anyhow::Result<()> {
|
||||||
let (reply, response) = oneshot();
|
let (reply, mut response) = oneshot();
|
||||||
|
// TODO: Handle error case.
|
||||||
self.tx.send(WorkerTask::Init(reply)).unwrap();
|
self.tx.send(WorkerTask::Init(reply)).unwrap();
|
||||||
response.recv()
|
match response.recv().await {
|
||||||
|
Some(result) => Ok(result),
|
||||||
|
None => Err(anyhow::Error::msg("TBD")),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn login(&self, style: LoginStyle) -> anyhow::Result<()> {
|
pub async fn login(&self, style: LoginStyle) -> anyhow::Result<()> {
|
||||||
let (reply, response) = oneshot();
|
let (reply, mut response) = oneshot();
|
||||||
|
// TODO: Handle error case.
|
||||||
self.tx.send(WorkerTask::Login(style, reply)).unwrap();
|
self.tx.send(WorkerTask::Login(style, reply)).unwrap();
|
||||||
response.recv()
|
match response.recv().await {
|
||||||
|
Some(result) => result,
|
||||||
|
None => Err(anyhow::Error::msg("TBD")),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,31 +1,6 @@
|
|||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
|
use crate::utils::Sender;
|
||||||
|
|
||||||
pub struct ClientResponse<T>(Receiver<T>);
|
|
||||||
pub struct ClientReply<T>(SyncSender<T>);
|
|
||||||
|
|
||||||
impl<T> ClientResponse<T> {
|
|
||||||
pub(super) fn recv(self) -> T {
|
|
||||||
self.0
|
|
||||||
.recv()
|
|
||||||
.expect("failed to receive response from client thread")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> ClientReply<T> {
|
|
||||||
pub(super) fn send(self, t: T) {
|
|
||||||
self.0.send(t).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn oneshot<T>() -> (ClientReply<T>, ClientResponse<T>) {
|
|
||||||
let (tx, rx) = sync_channel(1);
|
|
||||||
let reply = ClientReply(tx);
|
|
||||||
let response = ClientResponse(rx);
|
|
||||||
|
|
||||||
(reply, response)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum LoginStyle {
|
pub enum LoginStyle {
|
||||||
@@ -36,9 +11,9 @@ pub enum LoginStyle {
|
|||||||
pub enum WorkerTask {
|
pub enum WorkerTask {
|
||||||
// Init(AsyncProgramStore, ClientReply<()>),
|
// Init(AsyncProgramStore, ClientReply<()>),
|
||||||
// Init(ClientReply<()>),
|
// Init(ClientReply<()>),
|
||||||
Init(ClientReply<()>),
|
Init(Sender<()>),
|
||||||
//Login(LoginStyle, ClientReply<EditInfo>),
|
//Login(LoginStyle, ClientReply<EditInfo>),
|
||||||
Login(LoginStyle, ClientReply<anyhow::Result<()>>),
|
Login(LoginStyle, Sender<anyhow::Result<()>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for WorkerTask {
|
impl Debug for WorkerTask {
|
||||||
|
28
src/utils.rs
Normal file
28
src/utils.rs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
use tokio::sync::mpsc::{channel, Receiver as _Receiver, Sender as _Sender};
|
||||||
|
|
||||||
|
pub struct Receiver<T>(_Receiver<T>);
|
||||||
|
|
||||||
|
impl<T> Receiver<T> {
|
||||||
|
pub(super) async fn recv(&mut self) -> Option<T> {
|
||||||
|
self.0.recv().await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Sender<T>(_Sender<T>);
|
||||||
|
|
||||||
|
// TODO: Handle error
|
||||||
|
impl<T> Sender<T> {
|
||||||
|
pub(super) async fn send(self, t: T) {
|
||||||
|
// self.0.send(t).unwrap();
|
||||||
|
let _ = self.0.send(t).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Rename the name of the following fn
|
||||||
|
pub fn oneshot<T>() -> (Sender<T>, Receiver<T>) {
|
||||||
|
let (tx, rx) = channel(32);
|
||||||
|
let sender = Sender(tx);
|
||||||
|
let receiver = Receiver(rx);
|
||||||
|
|
||||||
|
(sender, receiver)
|
||||||
|
}
|
Reference in New Issue
Block a user