diff --git a/kordophone-db/src/repository.rs b/kordophone-db/src/repository.rs index e200feb..eb18fad 100644 --- a/kordophone-db/src/repository.rs +++ b/kordophone-db/src/repository.rs @@ -131,7 +131,7 @@ impl<'a> Repository<'a> { .execute(self.connection)?; // Update conversation date - self.update_conversation_metadata(conversation_guid, &db_message)?; + self.update_conversation_metadata(conversation_guid)?; Ok(()) } @@ -181,7 +181,7 @@ impl<'a> Repository<'a> { .execute(self.connection)?; // Update conversation date - self.update_conversation_metadata(conversation_guid, &db_messages.last().unwrap())?; + self.update_conversation_metadata(conversation_guid)?; Ok(()) } @@ -243,13 +243,15 @@ impl<'a> Repository<'a> { Ok(()) } - fn update_conversation_metadata(&mut self, conversation_guid: &str, last_message: &MessageRecord) -> Result<()> { + fn update_conversation_metadata(&mut self, conversation_guid: &str) -> Result<()> { let conversation = self.get_conversation_by_guid(conversation_guid)?; if let Some(mut conversation) = conversation { - log::debug!("Updating conversation metadata: {} message: {:?}", conversation_guid, last_message); - conversation.date = last_message.date; - conversation.last_message_preview = Some(last_message.text.clone()); - self.insert_conversation(conversation)?; + if let Some(last_message) = self.get_last_message_for_conversation(conversation_guid)? { + log::debug!("Updating conversation metadata: {} message: {:?}", conversation_guid, last_message); + conversation.date = last_message.date; + conversation.last_message_preview = Some(last_message.text.clone()); + self.insert_conversation(conversation)?; + } } Ok(()) diff --git a/kordophone/src/model/conversation.rs b/kordophone/src/model/conversation.rs index f7b74c3..004b362 100644 --- a/kordophone/src/model/conversation.rs +++ b/kordophone/src/model/conversation.rs @@ -3,6 +3,7 @@ use time::OffsetDateTime; use uuid::Uuid; use super::Identifiable; +use crate::model::message::Message; pub type ConversationID = ::ID; @@ -24,6 +25,9 @@ pub struct Conversation { #[serde(rename = "displayName")] pub display_name: Option, + + #[serde(rename = "lastMessage")] + pub last_message: Option, } impl Conversation { @@ -48,6 +52,7 @@ pub struct ConversationBuilder { last_message_preview: Option, participant_display_names: Option>, display_name: Option, + last_message: Option, } impl ConversationBuilder { @@ -85,6 +90,11 @@ impl ConversationBuilder { self } + pub fn last_message(mut self, last_message: Message) -> Self { + self.last_message = Some(last_message); + self + } + pub fn build(self) -> Conversation { Conversation { guid: self.guid.unwrap_or(Uuid::new_v4().to_string()), @@ -93,6 +103,7 @@ impl ConversationBuilder { last_message_preview: self.last_message_preview, participant_display_names: self.participant_display_names.unwrap_or_default(), display_name: self.display_name, + last_message: self.last_message, } } } diff --git a/kordophoned/src/daemon/update_monitor.rs b/kordophoned/src/daemon/update_monitor.rs index ed65766..7632540 100644 --- a/kordophoned/src/daemon/update_monitor.rs +++ b/kordophoned/src/daemon/update_monitor.rs @@ -11,6 +11,7 @@ use kordophone::api::event_socket::EventSocket; use kordophone::model::event::Event as UpdateEvent; use kordophone_db::database::Database; +use kordophone_db::database::DatabaseAccess; use tokio::sync::mpsc::Sender; use std::sync::Arc; @@ -42,13 +43,32 @@ impl UpdateMonitor { match update { UpdateEvent::ConversationChanged(conversation) => { log::info!(target: target::UPDATES, "Conversation changed: {:?}", conversation); - if conversation.unread_count > 0 { - log::info!(target: target::UPDATES, "Syncing new messages for conversation id: {}", conversation.guid); - self.send_event(|r| Event::SyncConversation(conversation.guid, r)).await - .unwrap_or_else(|e| { - log::error!("Failed to send daemon event: {}", e); - }); + + // Weird. We can get in a loop because calling getMessages triggers a conversation changed + // event for some reason. Check to see if the change event says the last message id is the same + // as the last message id in the database. If so, skip the sync. + let last_message = self.database.with_repository(|r| r.get_last_message_for_conversation(&conversation.guid)).await.unwrap_or_default(); + let should_sync_conversation = match (&last_message, &conversation.last_message) { + (Some(message), Some(conversation_message)) => { + if message.id == conversation_message.guid { + false + } else { + true + } + } + _ => true + }; + + if !should_sync_conversation { + log::info!(target: target::UPDATES, "Skipping sync for conversation id: {}. We already have this message.", conversation.guid); + return; } + + log::info!(target: target::UPDATES, "Syncing new messages for conversation id: {}, last message: {:?}", conversation.guid, last_message); + self.send_event(|r| Event::SyncConversation(conversation.guid, r)).await + .unwrap_or_else(|e| { + log::error!("Failed to send daemon event: {}", e); + }); } UpdateEvent::MessageReceived(conversation, message) => {