diff options
Diffstat (limited to '')
-rw-r--r-- | filamento/src/db.rs | 144 | ||||
-rw-r--r-- | filamento/src/lib.rs | 21 | ||||
-rw-r--r-- | filamento/src/logic/local_only.rs | 7 | ||||
-rw-r--r-- | filamento/src/logic/offline.rs | 12 | ||||
-rw-r--r-- | filamento/src/logic/online.rs | 7 |
5 files changed, 138 insertions, 53 deletions
diff --git a/filamento/src/db.rs b/filamento/src/db.rs index 9d4b4e9..1b5afe6 100644 --- a/filamento/src/db.rs +++ b/filamento/src/db.rs @@ -344,6 +344,14 @@ impl Db { result } + pub(crate) async fn read_chat_and_user(&self, chat: JID) -> Result<(Chat, User), Error> { + let (result, recv) = oneshot::channel(); + let command = DbCommand::ReadChatAndUser { chat, result }; + self.sender.send(command); + let result = recv.await?; + result + } + pub(crate) async fn mark_chat_as_chatted(&self, chat: JID) -> Result<(), Error> { let (result, recv) = oneshot::channel(); let command = DbCommand::MarkChatAsChatted { chat, result }; @@ -605,6 +613,10 @@ pub enum DbCommand { chat: JID, result: oneshot::Sender<Result<Chat, Error>>, }, + ReadChatAndUser { + chat: JID, + result: oneshot::Sender<Result<(Chat, User), Error>>, + }, MarkChatAsChatted { chat: JID, result: oneshot::Sender<Result<(), Error>>, @@ -700,45 +712,46 @@ impl Display for DbCommand { #[rustfmt::skip] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(match self { - DbCommand::CreateUser { user, result } => "CreateUser", - DbCommand::ReadUser { user, result } => "ReadUser", - DbCommand::DeleteUserNick { jid, result } => "DeleteUserNick", - DbCommand::UpsertUserNick { jid, nick, result } => "UpsertUserNick", - DbCommand::DeleteUserAvatar { jid, result } => "DeleteUserAvatar", - DbCommand::UpsertUserAvatar { jid, avatar, result } => "UpsertUserAvatar", - DbCommand::UpdateUser { user, result } => "UpdateUser", - DbCommand::CreateContact { contact, result } => "CreateContact", - DbCommand::ReadContact { contact, result } => "ReadContact", - DbCommand::ReadContactOpt { contact, result } => "ReadContactOpt", - DbCommand::UpdateContact { contact, result } => "UpdateContact", - DbCommand::UpsertContact { contact, result } => "UpsertContact", - DbCommand::DeleteContact { contact, result } => "DeleteContact", - DbCommand::ReplaceCachedRoster { roster, result } => "ReplaceCachedRoster", - DbCommand::ReadCachedRoster { result } => "ReadCachedRoster", - DbCommand::ReadCachedRosterWithUsers { result } => "ReadCachedRosterWithUsers", - DbCommand::CreateChat { chat, result } => "CreateChat", - DbCommand::ReadChat { chat, result } => "ReadChat", - DbCommand::MarkChatAsChatted { chat, result } => "MarkChatAsChatted", - DbCommand::UpdateChatCorrespondent { old_chat, new_correspondent, result } => "UpdateChatCorrespondent", - DbCommand::DeleteChat { chat, result } => "DeleteChat", - DbCommand::ReadChats { result } => "ReadChats", - DbCommand::ReadChatsOrdered { result } => "ReadChatsOrdered", - DbCommand::ReadChatsOrderedWithLatestMessages { result } => "ReadChatsOrderedWithLatestMessages", - DbCommand::ReadChatsOrderedWithLatestMessagesAndUsers { result } => "ReadChatsOrderedWithLatestMessagesAndUsers", - DbCommand::CreateMessage { message, chat, from, result } => "CreateMessage", - DbCommand::UpsertChatAndUser { chat, result } => "UpsertChatAndUser", - DbCommand::CreateMessageWithUserResource { message, chat, from, result } => "CreateMessageWithUserResource", - DbCommand::UpdateMessageDelivery { message, delivery, result } => "UpdateMessageDelivery", - DbCommand::DeleteMessage { message, result } => "DeleteMessage", - DbCommand::ReadMessage { message, result } => "ReadMessage", - DbCommand::ReadMessageHistory { chat, result } => "ReadMessageHistory", - DbCommand::ReadMessageHistoryWithUsers { chat, result } => "ReadMessageHistoryWithUsers", - DbCommand::ReadCachedStatus { result } => "ReadCachedStatus", - DbCommand::UpsertCachedStatus { status, result } => "UpsertCachedStatus", - DbCommand::DeleteCachedStatus { result } => "DeleteCachedStatus", - DbCommand::ReadCapabilities { node, result } => "ReadCapabilities", - DbCommand::UpsertCapabilities { node, capabilities, result } => "UpsertCapabilities", - }) + DbCommand::CreateUser { user, result } => "CreateUser", + DbCommand::ReadUser { user, result } => "ReadUser", + DbCommand::DeleteUserNick { jid, result } => "DeleteUserNick", + DbCommand::UpsertUserNick { jid, nick, result } => "UpsertUserNick", + DbCommand::DeleteUserAvatar { jid, result } => "DeleteUserAvatar", + DbCommand::UpsertUserAvatar { jid, avatar, result } => "UpsertUserAvatar", + DbCommand::UpdateUser { user, result } => "UpdateUser", + DbCommand::CreateContact { contact, result } => "CreateContact", + DbCommand::ReadContact { contact, result } => "ReadContact", + DbCommand::ReadContactOpt { contact, result } => "ReadContactOpt", + DbCommand::UpdateContact { contact, result } => "UpdateContact", + DbCommand::UpsertContact { contact, result } => "UpsertContact", + DbCommand::DeleteContact { contact, result } => "DeleteContact", + DbCommand::ReplaceCachedRoster { roster, result } => "ReplaceCachedRoster", + DbCommand::ReadCachedRoster { result } => "ReadCachedRoster", + DbCommand::ReadCachedRosterWithUsers { result } => "ReadCachedRosterWithUsers", + DbCommand::CreateChat { chat, result } => "CreateChat", + DbCommand::ReadChat { chat, result } => "ReadChat", + DbCommand::MarkChatAsChatted { chat, result } => "MarkChatAsChatted", + DbCommand::UpdateChatCorrespondent { old_chat, new_correspondent, result } => "UpdateChatCorrespondent", + DbCommand::DeleteChat { chat, result } => "DeleteChat", + DbCommand::ReadChats { result } => "ReadChats", + DbCommand::ReadChatsOrdered { result } => "ReadChatsOrdered", + DbCommand::ReadChatsOrderedWithLatestMessages { result } => "ReadChatsOrderedWithLatestMessages", + DbCommand::ReadChatsOrderedWithLatestMessagesAndUsers { result } => "ReadChatsOrderedWithLatestMessagesAndUsers", + DbCommand::CreateMessage { message, chat, from, result } => "CreateMessage", + DbCommand::UpsertChatAndUser { chat, result } => "UpsertChatAndUser", + DbCommand::CreateMessageWithUserResource { message, chat, from, result } => "CreateMessageWithUserResource", + DbCommand::UpdateMessageDelivery { message, delivery, result } => "UpdateMessageDelivery", + DbCommand::DeleteMessage { message, result } => "DeleteMessage", + DbCommand::ReadMessage { message, result } => "ReadMessage", + DbCommand::ReadMessageHistory { chat, result } => "ReadMessageHistory", + DbCommand::ReadMessageHistoryWithUsers { chat, result } => "ReadMessageHistoryWithUsers", + DbCommand::ReadCachedStatus { result } => "ReadCachedStatus", + DbCommand::UpsertCachedStatus { status, result } => "UpsertCachedStatus", + DbCommand::DeleteCachedStatus { result } => "DeleteCachedStatus", + DbCommand::ReadCapabilities { node, result } => "ReadCapabilities", + DbCommand::UpsertCapabilities { node, capabilities, result } => "UpsertCapabilities", + DbCommand::ReadChatAndUser { chat, result } => "ReadChatAndUser", + }) } } @@ -863,6 +876,9 @@ impl DbActor { DbCommand::ReadChat { chat, result } => { result.send(self.read_chat(chat)); } + DbCommand::ReadChatAndUser { chat, result } => { + result.send(self.read_chat_and_user(chat)); + } DbCommand::MarkChatAsChatted { chat, result } => { result.send(self.mark_chat_as_chatted(chat)); } @@ -1272,8 +1288,10 @@ impl DbActor { // TODO: what happens if a correspondent changes from a user to a contact? maybe just have correspondent be a user, then have the client make the user show up as a contact in ui if they are in the loaded roster. + /// should be a bare jid + /// TODO: this is NOT a read pub(crate) fn read_chat(&self, chat: JID) -> Result<Chat, Error> { - let chat = self.db.query_row( + let chat_opt = self.db.query_row( "select correspondent, have_chatted from chats where correspondent = ?1", [&chat], |row| { @@ -1282,8 +1300,50 @@ impl DbActor { have_chatted: row.get(1)?, }) }, - )?; - Ok(chat) + ).optional()?; + match chat_opt { + Some(chat) => return Ok(chat), + None => { + let chat = Chat { + correspondent: chat, + have_chatted: false, + }; + self.create_chat(chat.clone())?; + Ok(chat) + } + } + } + + pub(crate) fn read_chat_and_user(&self, chat: JID) -> Result<(Chat, User), Error> { + let user = self.read_user(chat.clone())?; + let chat_opt = self.db.query_row( + "select correspondent, have_chatted, jid, nick, avatar from chats join users on correspondent = jid where correspondent = ?1", + [&chat], + |row| { + Ok(( + Chat { + correspondent: row.get(0)?, + have_chatted: row.get(1)?, + }, + User { + jid: row.get(2)?, + nick: row.get(3)?, + avatar: row.get(4)?, + } + )) + }, + ).optional()?; + match chat_opt { + Some(chat) => return Ok(chat), + None => { + let chat = Chat { + correspondent: chat, + have_chatted: false, + }; + self.create_chat(chat.clone())?; + Ok((chat, user)) + } + } } pub(crate) fn mark_chat_as_chatted(&self, chat: JID) -> Result<(), Error> { diff --git a/filamento/src/lib.rs b/filamento/src/lib.rs index 8b27441..068bfe8 100644 --- a/filamento/src/lib.rs +++ b/filamento/src/lib.rs @@ -69,6 +69,8 @@ pub enum Command<Fs: FileStore> { ), /// get a specific chat by jid GetChat(JID, oneshot::Sender<Result<Chat, DatabaseError>>), + /// get a specific chat and user by jid + GetChatAndUser(JID, oneshot::Sender<Result<(Chat, User), DatabaseError>>), /// get message history for chat (does appropriate mam things) GetMessage(Uuid, oneshot::Sender<Result<Message, DatabaseError>>), // TODO: paging and filtering @@ -269,8 +271,9 @@ impl<Fs: FileStore + Clone + Send + Sync + 'static> Client<Fs> { } impl<Fs: FileStore> Client<Fs> { - pub async fn connect(&self) -> Result<(), CommandError<ConnectionError>> { - let (send, recv) = oneshot::channel::<Result<(), ConnectionError>>(); + /// returns the resource + pub async fn connect(&self) -> Result<String, CommandError<ConnectionError>> { + let (send, recv) = oneshot::channel::<Result<String, ConnectionError>>(); self.send(CoreClientCommand::Connect(send)) .await .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))?; @@ -278,7 +281,7 @@ impl<Fs: FileStore> Client<Fs> { .await .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))? .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))??; - Ok(()) + Ok(result) } pub async fn disconnect(&self, offline: Offline) -> Result<(), ActorError> { @@ -382,6 +385,18 @@ impl<Fs: FileStore> Client<Fs> { Ok(chat) } + pub async fn get_chat_and_user(&self, jid: JID) -> Result<(Chat, User), CommandError<DatabaseError>> { + let (send, recv) = oneshot::channel(); + self.send(CoreClientCommand::Command(Command::GetChatAndUser(jid, send))) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))?; + let result= timeout(self.timeout, recv) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))? + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))??; + Ok(result) + } + pub async fn get_message(&self, id: Uuid) -> Result<Message, CommandError<DatabaseError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command(Command::GetMessage(id, send))) diff --git a/filamento/src/logic/local_only.rs b/filamento/src/logic/local_only.rs index a22efbd..f5705f4 100644 --- a/filamento/src/logic/local_only.rs +++ b/filamento/src/logic/local_only.rs @@ -44,6 +44,13 @@ pub async fn handle_get_chat<Fs: FileStore + Clone>( Ok(logic.db().read_chat(jid).await?) } +pub async fn handle_get_chat_and_user<Fs: FileStore + Clone>( + logic: &ClientLogic<Fs>, + jid: JID, +) -> Result<(Chat, User), DatabaseError> { + Ok(logic.db().read_chat_and_user(jid).await?) +} + pub async fn handle_get_message<Fs: FileStore + Clone>( logic: &ClientLogic<Fs>, id: Uuid, diff --git a/filamento/src/logic/offline.rs b/filamento/src/logic/offline.rs index 42a38ca..606b04f 100644 --- a/filamento/src/logic/offline.rs +++ b/filamento/src/logic/offline.rs @@ -19,13 +19,9 @@ use crate::{ }; use super::{ - ClientLogic, local_only::{ - handle_delete_chat, handle_delete_messaage, handle_get_chat, handle_get_chats, - handle_get_chats_ordered, handle_get_chats_ordered_with_latest_messages, - handle_get_chats_ordered_with_latest_messages_and_users, handle_get_message, - handle_get_messages, handle_get_messages_with_users, handle_get_user, - }, + handle_delete_chat, handle_delete_messaage, handle_get_chat, handle_get_chat_and_user, handle_get_chats, handle_get_chats_ordered, handle_get_chats_ordered_with_latest_messages, handle_get_chats_ordered_with_latest_messages_and_users, handle_get_message, handle_get_messages, handle_get_messages_with_users, handle_get_user + }, ClientLogic }; pub async fn handle_offline<Fs: FileStore + Clone>(logic: ClientLogic<Fs>, command: Command<Fs>) { @@ -89,6 +85,10 @@ pub async fn handle_offline_result<Fs: FileStore + Clone>( let chats = handle_get_chat(logic, jid).await; sender.send(chats); } + Command::GetChatAndUser(jid, sender) => { + let chat = handle_get_chat_and_user(logic, jid).await; + let _ = sender.send(chat); + } Command::GetMessage(id, sender) => { let message = handle_get_message(logic, id).await; let _ = sender.send(message); diff --git a/filamento/src/logic/online.rs b/filamento/src/logic/online.rs index 969e08a..9814ff2 100644 --- a/filamento/src/logic/online.rs +++ b/filamento/src/logic/online.rs @@ -23,8 +23,7 @@ use crate::{ use super::{ local_only::{ - handle_get_message, - handle_delete_chat, handle_delete_messaage, handle_get_chat, handle_get_chats, handle_get_chats_ordered, handle_get_chats_ordered_with_latest_messages, handle_get_chats_ordered_with_latest_messages_and_users, handle_get_messages, handle_get_messages_with_users, handle_get_user + handle_delete_chat, handle_delete_messaage, handle_get_chat, handle_get_chat_and_user, handle_get_chats, handle_get_chats_ordered, handle_get_chats_ordered_with_latest_messages, handle_get_chats_ordered_with_latest_messages_and_users, handle_get_message, handle_get_messages, handle_get_messages_with_users, handle_get_user }, ClientLogic }; @@ -1111,6 +1110,10 @@ pub async fn handle_online_result<Fs: FileStore + Clone>( let chat = handle_get_chat(logic, jid).await; let _ = sender.send(chat); } + Command::GetChatAndUser(jid, sender) => { + let chat = handle_get_chat_and_user(logic, jid).await; + let _ = sender.send(chat); + } Command::GetMessage(id, sender) => { let message = handle_get_message(logic, id).await; let _ = sender.send(message); |