✨ Add the capability to join a conversation
This commit is contained in:
@@ -44,6 +44,7 @@ pub trait RoomMessagingConsumerInterface {
|
|||||||
#[async_trait(?Send)]
|
#[async_trait(?Send)]
|
||||||
pub trait RoomMessagingProviderInterface {
|
pub trait RoomMessagingProviderInterface {
|
||||||
async fn get_avatar(&self, id: &RoomId) -> anyhow::Result<Option<Avatar>>;
|
async fn get_avatar(&self, id: &RoomId) -> anyhow::Result<Option<Avatar>>;
|
||||||
|
async fn join(&self, room_id: &RoomId) -> anyhow::Result<bool>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait(?Send)]
|
#[async_trait(?Send)]
|
||||||
|
@@ -314,4 +314,10 @@ impl RoomStoreConsumerInterface for Room {
|
|||||||
fn spaces(&self) -> &Vec<SpaceId> {
|
fn spaces(&self) -> &Vec<SpaceId> {
|
||||||
&self.spaces
|
&self.spaces
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn join(&self) {
|
||||||
|
if let Some(messaging_provider) = &self.messaging_provider {
|
||||||
|
let _ = messaging_provider.join(&self.id).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,11 +29,11 @@ pub trait RoomStoreConsumerInterface {
|
|||||||
fn is_direct(&self) -> Option<bool>;
|
fn is_direct(&self) -> Option<bool>;
|
||||||
fn name(&self) -> Option<String>;
|
fn name(&self) -> Option<String>;
|
||||||
fn topic(&self) -> Option<String>;
|
fn topic(&self) -> Option<String>;
|
||||||
|
fn spaces(&self) -> &Vec<SpaceId>;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
async fn avatar(&self) -> Option<Avatar>;
|
async fn avatar(&self) -> Option<Avatar>;
|
||||||
|
async fn join(&self);
|
||||||
fn spaces(&self) -> &Vec<SpaceId>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RoomStoreProviderInterface {
|
pub trait RoomStoreProviderInterface {
|
||||||
|
@@ -776,6 +776,19 @@ impl Client {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn join_room(&self, room_id: &RoomId) -> anyhow::Result<bool> {
|
||||||
|
let client = self.client.as_ref().unwrap();
|
||||||
|
|
||||||
|
if let Some(room) = client.get_room(room_id) {
|
||||||
|
return match room.join().await {
|
||||||
|
Ok(_) => Ok(true),
|
||||||
|
Err(err) => Err(err.into()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
async fn work(&mut self, mut rx: UnboundedReceiver<WorkerTask>) {
|
async fn work(&mut self, mut rx: UnboundedReceiver<WorkerTask>) {
|
||||||
while let Some(task) = rx.recv().await {
|
while let Some(task) = rx.recv().await {
|
||||||
self.run(task).await;
|
self.run(task).await;
|
||||||
@@ -820,6 +833,9 @@ impl Client {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
WorkerTask::JoinRoom(id, reply) => {
|
||||||
|
reply.send(self.join_room(&id).await).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -362,6 +362,10 @@ impl RoomMessagingProviderInterface for Requester {
|
|||||||
async fn get_avatar(&self, room_id: &RoomId) -> anyhow::Result<Option<Avatar>> {
|
async fn get_avatar(&self, room_id: &RoomId) -> anyhow::Result<Option<Avatar>> {
|
||||||
request_to_worker!(self, WorkerTask::GetRoomAvatar, room_id.clone())
|
request_to_worker!(self, WorkerTask::GetRoomAvatar, room_id.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn join(&self, room_id: &RoomId) -> anyhow::Result<bool> {
|
||||||
|
request_to_worker!(self, WorkerTask::JoinRoom, room_id.clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait(?Send)]
|
#[async_trait(?Send)]
|
||||||
|
@@ -23,6 +23,7 @@ pub enum WorkerTask {
|
|||||||
OwnedUserId,
|
OwnedUserId,
|
||||||
Sender<anyhow::Result<Option<Vec<u8>>>>,
|
Sender<anyhow::Result<Option<Vec<u8>>>>,
|
||||||
),
|
),
|
||||||
|
JoinRoom(OwnedRoomId, Sender<anyhow::Result<bool>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for WorkerTask {
|
impl Debug for WorkerTask {
|
||||||
@@ -61,6 +62,10 @@ impl Debug for WorkerTask {
|
|||||||
.field(room_id)
|
.field(room_id)
|
||||||
.field(user_id)
|
.field(user_id)
|
||||||
.finish(),
|
.finish(),
|
||||||
|
WorkerTask::JoinRoom(room_id, _) => f
|
||||||
|
.debug_tuple("WorkerTask::JoinRoom")
|
||||||
|
.field(room_id)
|
||||||
|
.finish(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ use std::{rc::Rc, time::Duration};
|
|||||||
|
|
||||||
use base64::{engine::general_purpose, Engine as _};
|
use base64::{engine::general_purpose, Engine as _};
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
use futures_util::StreamExt;
|
||||||
use tracing::{debug, warn};
|
use tracing::{debug, warn};
|
||||||
|
|
||||||
use super::{button::Button, icons::SearchIcon, text_input::TextInput};
|
use super::{button::Button, icons::SearchIcon, text_input::TextInput};
|
||||||
@@ -431,11 +432,16 @@ pub fn Search() -> Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
enum ConversationOptionsMenuActions {
|
||||||
|
Join(RoomId),
|
||||||
|
Close,
|
||||||
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn ConversationOptionsMenu(
|
fn ConversationOptionsMenu(
|
||||||
room_id: RoomId,
|
room_id: RoomId,
|
||||||
on_close: EventHandler,
|
callbacks: Coroutine<ConversationOptionsMenuActions>,
|
||||||
on_join: EventHandler,
|
|
||||||
) -> Element {
|
) -> Element {
|
||||||
let room = STORE.read().rooms().get(&room_id).unwrap().signal();
|
let room = STORE.read().rooms().get(&room_id).unwrap().signal();
|
||||||
|
|
||||||
@@ -450,7 +456,7 @@ fn ConversationOptionsMenu(
|
|||||||
|
|
||||||
div {
|
div {
|
||||||
class: ClassName::CONVERSATION_OPTIONS_MENU_INNER_AVATAR,
|
class: ClassName::CONVERSATION_OPTIONS_MENU_INNER_AVATAR,
|
||||||
ConversationAvatar { room_id }
|
ConversationAvatar { room_id: room_id.clone() }
|
||||||
}
|
}
|
||||||
|
|
||||||
div {
|
div {
|
||||||
@@ -477,7 +483,9 @@ fn ConversationOptionsMenu(
|
|||||||
div {
|
div {
|
||||||
class: ClassName::CONVERSATION_OPTIONS_MENU_INNER_CLOSE_BUTTON,
|
class: ClassName::CONVERSATION_OPTIONS_MENU_INNER_CLOSE_BUTTON,
|
||||||
RejectButton {
|
RejectButton {
|
||||||
onclick: move |_| on_close(())
|
onclick: move |_| {
|
||||||
|
callbacks.send(ConversationOptionsMenuActions::Close);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,8 +493,8 @@ fn ConversationOptionsMenu(
|
|||||||
class: ClassName::CONVERSATION_OPTIONS_MENU_INNER_JOIN_BUTTON,
|
class: ClassName::CONVERSATION_OPTIONS_MENU_INNER_JOIN_BUTTON,
|
||||||
JoinButton {
|
JoinButton {
|
||||||
onclick: move |_| {
|
onclick: move |_| {
|
||||||
on_join(());
|
callbacks.send(ConversationOptionsMenuActions::Join(room_id.clone()));
|
||||||
on_close(());
|
callbacks.send(ConversationOptionsMenuActions::Close);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -498,26 +506,33 @@ fn ConversationOptionsMenu(
|
|||||||
pub fn Conversations() -> Element {
|
pub fn Conversations() -> Element {
|
||||||
let mut room_id = use_signal(|| None::<RoomId>);
|
let mut room_id = use_signal(|| None::<RoomId>);
|
||||||
|
|
||||||
let on_menu_close = move |_| {
|
|
||||||
room_id.set(None);
|
|
||||||
};
|
|
||||||
|
|
||||||
let on_menu_join = move |_| async move {
|
|
||||||
let rooms = STORE.read().rooms();
|
|
||||||
if let Some(room_id) = room_id.read().to_owned() {
|
|
||||||
if let Some(room) = rooms.get(&room_id) {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let on_pressed_conversation = move |id: RoomId| {
|
let on_pressed_conversation = move |id: RoomId| {
|
||||||
room_id.set(Some(id));
|
room_id.set(Some(id));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let callbacks = use_coroutine(
|
||||||
|
move |mut rx: UnboundedReceiver<ConversationOptionsMenuActions>| async move {
|
||||||
|
while let Some(action) = rx.next().await {
|
||||||
|
match action {
|
||||||
|
ConversationOptionsMenuActions::Join(room_id) => {
|
||||||
|
let rooms = STORE.read().rooms();
|
||||||
|
if let Some(room) = rooms.get(&room_id) {
|
||||||
|
room.join().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConversationOptionsMenuActions::Close => {
|
||||||
|
room_id.set(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
let menu = match room_id.read().as_ref() {
|
let menu = match room_id.read().as_ref() {
|
||||||
Some(room_id) => {
|
Some(room_id) => {
|
||||||
let room_id = room_id.clone();
|
let room_id = room_id.clone();
|
||||||
rsx! {
|
rsx! {
|
||||||
ConversationOptionsMenu { room_id, on_close: on_menu_close, on_join: on_menu_join }
|
ConversationOptionsMenu { room_id, callbacks }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => VNode::empty(),
|
None => VNode::empty(),
|
||||||
|
@@ -33,7 +33,6 @@ pub struct Store {
|
|||||||
pub struct Room {
|
pub struct Room {
|
||||||
store: RefCell<Store>,
|
store: RefCell<Store>,
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
domain: Rc<dyn RoomStoreConsumerInterface>,
|
domain: Rc<dyn RoomStoreConsumerInterface>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,6 +56,10 @@ impl Room {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn join(&self) {
|
||||||
|
self.domain.join().await;
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn get_avatar(&self) -> Option<Avatar> {
|
pub async fn get_avatar(&self) -> Option<Avatar> {
|
||||||
self.domain.avatar().await
|
self.domain.avatar().await
|
||||||
@@ -81,6 +84,11 @@ impl RoomStoreProviderInterface for Room {
|
|||||||
|
|
||||||
fn on_new_member(&self, member: RoomMember) {
|
fn on_new_member(&self, member: RoomMember) {
|
||||||
let mut store = self.store.borrow_mut();
|
let mut store = self.store.borrow_mut();
|
||||||
|
|
||||||
|
if member.is_account_user() {
|
||||||
|
store.is_invited.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
store.members.write().push(member);
|
store.members.write().push(member);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user