From cd56089a73d8c045a9160dfdb820b997dfd61e80 Mon Sep 17 00:00:00 2001 From: Brayan Vargas <86427419+b-avb@users.noreply.github.com> Date: Wed, 27 Mar 2024 08:12:47 -0500 Subject: [PATCH] feat: add command helper (#67) --- src/components/atoms/helper.rs | 19 +-- .../organisms/chat/utils/handle_command.rs | 26 +-- src/hooks/use_send_message.rs | 47 +++--- src/pages/chat/chat_list.rs | 149 ++++++++++++++++-- 4 files changed, 190 insertions(+), 51 deletions(-) diff --git a/src/components/atoms/helper.rs b/src/components/atoms/helper.rs index 23742da..acbdb7f 100644 --- a/src/components/atoms/helper.rs +++ b/src/components/atoms/helper.rs @@ -3,21 +3,23 @@ use dioxus::prelude::*; pub struct HelperData { pub title: String, pub description: String, + pub subtitle: String, pub example: String, } #[derive(Props)] pub struct HelperProps<'a> { helper: HelperData, - _on_click: EventHandler<'a, MouseEvent>, + on_click: EventHandler<'a, MouseEvent>, } pub fn Helper<'a>(cx: Scope<'a, HelperProps<'a>>) -> Element<'a> { - cx.render(rsx!( + render!(rsx!( section { - class: "helper", - span { + class: "helper", + onclick: move |event| cx.props.on_click.call(event), h3 { + class: "helper__title", "{cx.props.helper.title}" }, p { @@ -25,14 +27,13 @@ pub fn Helper<'a>(cx: Scope<'a, HelperProps<'a>>) -> Element<'a> { "{cx.props.helper.description}" }, h4 { - class: "helper__title", - "Ejemplo" + class: "helper__subtitle", + "{cx.props.helper.subtitle}" }, p { - class: "helper__description", + class: "helper__example", "{cx.props.helper.example}" } - } - } + } )) } diff --git a/src/components/organisms/chat/utils/handle_command.rs b/src/components/organisms/chat/utils/handle_command.rs index 986c7ed..b5c555a 100644 --- a/src/components/organisms/chat/utils/handle_command.rs +++ b/src/components/organisms/chat/utils/handle_command.rs @@ -1,7 +1,5 @@ -use matrix_sdk::{ruma::RoomId, Client}; -use ruma::OwnedRoomId; - use crate::{pages::chat::chat::MessageItem, services::matrix::matrix::join_room}; +use matrix_sdk::{ruma::RoomId, Client}; pub enum CommandError { RoomIdNotFound, @@ -10,10 +8,15 @@ pub enum CommandError { RequestFailed, } +pub enum Command { + Join(String), + PublicRooms, +} + pub async fn handle_command( message_item: &MessageItem, client: &Client, -) -> Result { +) -> Result { let query: Vec = message_item .msg .trim() @@ -22,14 +25,17 @@ pub async fn handle_command( .collect(); let action = query.get(0).ok_or(CommandError::ActionNotFound)?.as_str(); - let rid = query.get(1).ok_or(CommandError::InvalidRoomId)?; - - let room_id = RoomId::parse(rid).map_err(|_| CommandError::InvalidRoomId)?; match action { - "!join" => join_room(client, &room_id) - .await - .map_err(|_| CommandError::RequestFailed), + "!join" => { + let rid = query.get(1).ok_or(CommandError::InvalidRoomId)?; + let room_id = RoomId::parse(rid).map_err(|_| CommandError::InvalidRoomId)?; + join_room(client, &room_id) + .await + .map(|id| Command::Join(id.to_string())) + .map_err(|_| CommandError::RequestFailed) + } + "!rooms" => Ok(Command::PublicRooms), _ => Err(CommandError::ActionNotFound), } } diff --git a/src/hooks/use_send_message.rs b/src/hooks/use_send_message.rs index 58760b8..3b3985b 100644 --- a/src/hooks/use_send_message.rs +++ b/src/hooks/use_send_message.rs @@ -11,8 +11,8 @@ use std::time::{Duration, UNIX_EPOCH}; use uuid::Uuid; use crate::{ - components::organisms::chat::utils::handle_command, - hooks::factory::message_factory::MessageFactory, + components::organisms::chat::utils::handle_command::{self, Command}, + hooks::{factory::message_factory::MessageFactory, use_public::PublicState}, pages::chat::chat::MessageItem, services::matrix::matrix::{send_message, TimelineMessageType, TimelineRelation}, }; @@ -23,6 +23,7 @@ use super::{ use_init_app::MessageDispatchId, use_messages::use_messages, use_notification::use_notification, + use_public::use_public, use_reply::use_reply, use_session::use_session, use_thread::{use_thread, UseThreadState}, @@ -51,6 +52,7 @@ pub fn use_send_message(cx: &ScopeState) -> &UseSendMessageState { let messages = use_messages(cx); let session = use_session(cx); let replying_to = use_reply(cx); + let public = use_public(cx); let threading_to = use_thread(cx); let message_factory = use_message_factory(cx); @@ -85,32 +87,35 @@ pub fn use_send_message(cx: &ScopeState) -> &UseSendMessageState { messages, session, message_dispatch_id, - message_factory + message_factory, + public ]; async move { while let Some(message_item) = rx.next().await { if message_item.msg.starts_with('!') { - let Err(error) = handle_command(&message_item, &client.get()).await else { - return; - }; + match handle_command::handle_command(&message_item, &client.get()).await { + Ok(Command::Join(_)) => {} + Ok(Command::PublicRooms) => public.set(PublicState { show: true }), + Err(error) => { + let message = match error { + handle_command::CommandError::RoomIdNotFound => { + &key_commands_join_errors_room_not_found + } + handle_command::CommandError::ActionNotFound => { + &key_commands_join_errors_action_not_found + } + handle_command::CommandError::InvalidRoomId => { + &key_commands_join_errors_invalid_room + } + handle_command::CommandError::RequestFailed => { + &key_commands_join_errors_request_failed + } + }; - let message = match error { - handle_command::CommandError::RoomIdNotFound => { - &key_commands_join_errors_room_not_found - } - handle_command::CommandError::ActionNotFound => { - &key_commands_join_errors_action_not_found + notification.handle_error(message); } - handle_command::CommandError::InvalidRoomId => { - &key_commands_join_errors_invalid_room - } - handle_command::CommandError::RequestFailed => { - &key_commands_join_errors_request_failed - } - }; - - notification.handle_error(message) + } } else { let mut back_messages = messages.get(); let uuid = Uuid::new_v4().to_string(); diff --git a/src/pages/chat/chat_list.rs b/src/pages/chat/chat_list.rs index b3b3f84..651dabb 100644 --- a/src/pages/chat/chat_list.rs +++ b/src/pages/chat/chat_list.rs @@ -6,16 +6,35 @@ use dioxus_std::{i18n::use_i18, translate}; use crate::{ components::{ atoms::{ - input::InputType, message::Messages, room::RoomItem, MessageInput, Space, SpaceSkeleton, + helper::HelperData, input::InputType, message::Messages, room::RoomItem, Helper, + MessageInput, Space, SpaceSkeleton, }, molecules::{ rooms::{CurrentRoom, FormRoomEvent}, RoomsList, }, - organisms::{chat::ActiveRoom, main::TitleHeaderMain}, + organisms::{ + chat::{ + utils::handle_command::{self, Command}, + ActiveRoom, PreviewRoom, PublicRooms, + }, + main::TitleHeaderMain, + }, }, hooks::{ - use_client::use_client, use_lifecycle::use_lifecycle, use_messages::use_messages, use_notification::use_notification, use_room::use_room, use_session::use_session + use_client::use_client, + use_lifecycle::use_lifecycle, + use_messages::use_messages, + use_notification::use_notification, + use_public::{use_public, PublicState}, + use_room::use_room, + use_room_preview::{use_room_preview, PreviewRoom}, + use_rooms::{use_rooms, RoomsList}, + use_session::use_session, + }, + pages::chat::chat::MessageItem, + services::matrix::matrix::{ + invited_rooms, list_rooms_and_spaces, public_rooms_and_spaces, Conversations, }, services::matrix::matrix::{list_rooms_and_spaces, Conversations}, }; @@ -45,7 +64,7 @@ pub fn ChatList(cx: Scope) -> Element { let title_header = use_shared_state::(cx).expect("Unable to read title header"); let is_loading = use_state(cx, || false); - + let r = room.clone(); use_lifecycle( &cx, @@ -114,6 +133,66 @@ pub fn ChatList(cx: Scope) -> Element { } }); + enum ScrollToPosition { + Top, + Bottom, + Right, + Left, + Custom(f64, f64), + } + + let on_scroll_chat_list_wrapper = move |position: ScrollToPosition| { + if let Some(e) = chat_list_wrapper_ref.read().as_ref() { + let (x, y) = match position { + ScrollToPosition::Top | ScrollToPosition::Left => (0.0, 0.0), + ScrollToPosition::Bottom => (0.0, e.get_bounding_client_rect().height()), + ScrollToPosition::Right => (e.get_bounding_client_rect().width(), 0.0), + ScrollToPosition::Custom(x, y) => (x, y), + }; + e.scroll_to_with_x_and_y(x, y); + } + }; + + let on_click_invitation = move |evt: FormRoomEvent| { + preview.set(PreviewRoom::Invited(evt.room.clone())); + room.default(); + }; + + let on_click_room = move |evt: FormRoomEvent| { + room.set(evt.room.clone()); + room_tabs.with_mut(|tabs| tabs.insert(evt.room, vec![])); + messages.reset(); + preview.default(); + + on_scroll_chat_list_wrapper(ScrollToPosition::Right); + }; + + let on_click_helper = move |_| { + on_scroll_chat_list_wrapper(ScrollToPosition::Right); + cx.spawn({ + to_owned![client, notification, public]; + async move { + let message_item = MessageItem { + room_id: String::new(), + msg: String::from("!rooms"), + reply_to: None, + send_to_thread: false, + }; + match handle_command::handle_command(&message_item, &client).await { + Ok(Command::Join(_)) => {} + Ok(Command::PublicRooms) => public.set(PublicState { show: true }), + Err(error) => { + let message = match error { + _ => "Error", + }; + + notification.handle_error(message); + } + } + } + }) + }; + render! { section { class: "chat-list options", @@ -217,13 +296,61 @@ pub fn ChatList(cx: Scope) -> Element { } ) - if !room.get().name.is_empty() { - rsx!( - section { - class: "chat-list__active-room", - ActiveRoom {} - } - ) + + div { + class: "chat-list__content", + onclick: move |_| { + on_scroll_chat_list_wrapper(ScrollToPosition::Right) + }, + if public.get().show { + rsx!( + section { + class: "chat-list__active-room", + PublicRooms { + on_back: move |_| { + on_scroll_chat_list_wrapper(ScrollToPosition::Left) + } + } + } + ) + } else if !preview.get().is_none() { + rsx!( + section { + class: "chat-list__active-room", + PreviewRoom { + on_back: move |_| { + on_scroll_chat_list_wrapper(ScrollToPosition::Left) + } + } + } + ) + } else if !room.get().name.is_empty(){ + rsx!( + section { + class: "chat-list__active-room", + ActiveRoom { + on_back: move |_| { + on_scroll_chat_list_wrapper(ScrollToPosition::Left) + } + } + } + ) + } else { + rsx!( + section { + class: "chat-list__static", + Helper { + helper: HelperData { + title: key_chat_helper_rooms_title, + description: key_chat_helper_rooms_description, + subtitle: key_chat_helper_rooms_subtitle, + example: String::from("!rooms") + }, + on_click: on_click_helper + } + } + ) + } } } }