feat: Sync chat visibility across devices (#4817)

This commit is contained in:
iequidoo
2023-10-21 01:59:40 -03:00
committed by iequidoo
parent 79cebe66de
commit e3b08fa92b
2 changed files with 30 additions and 11 deletions

View File

@@ -10,6 +10,7 @@ use std::time::{Duration, SystemTime};
use anyhow::{bail, ensure, Context as _, Result}; use anyhow::{bail, ensure, Context as _, Result};
use deltachat_derive::{FromSql, ToSql}; use deltachat_derive::{FromSql, ToSql};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use strum_macros::EnumIter;
use crate::aheader::EncryptPreference; use crate::aheader::EncryptPreference;
use crate::blob::BlobObject; use crate::blob::BlobObject;
@@ -554,6 +555,7 @@ impl ChatId {
"bad chat_id, can not be special chat: {}", "bad chat_id, can not be special chat: {}",
self self
); );
let (context, nosync) = &context.unwrap_nosync();
context context
.sql .sql
@@ -574,6 +576,11 @@ impl ChatId {
context.emit_msgs_changed_without_ids(); context.emit_msgs_changed_without_ids();
if !nosync {
let chat = Chat::load_from_db(context, self).await?;
chat.add_sync_item(context, ChatAction::SetVisibility(visibility))
.await?;
}
Ok(()) Ok(())
} }
@@ -1882,26 +1889,22 @@ impl Chat {
} }
/// Whether the chat is pinned or archived. /// Whether the chat is pinned or archived.
#[derive(Debug, Copy, Eq, PartialEq, Clone, Serialize, Deserialize)] #[derive(Debug, Copy, Eq, PartialEq, Clone, Serialize, Deserialize, EnumIter)]
#[repr(i8)]
pub enum ChatVisibility { pub enum ChatVisibility {
/// Chat is neither archived nor pinned. /// Chat is neither archived nor pinned.
Normal, Normal = 0,
/// Chat is archived. /// Chat is archived.
Archived, Archived = 1,
/// Chat is pinned to the top of the chatlist. /// Chat is pinned to the top of the chatlist.
Pinned, Pinned = 2,
} }
impl rusqlite::types::ToSql for ChatVisibility { impl rusqlite::types::ToSql for ChatVisibility {
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput> { fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput> {
let visibility = match &self { let val = rusqlite::types::Value::Integer(*self as i64);
ChatVisibility::Normal => 0,
ChatVisibility::Archived => 1,
ChatVisibility::Pinned => 2,
};
let val = rusqlite::types::Value::Integer(visibility);
let out = rusqlite::types::ToSqlOutput::Owned(val); let out = rusqlite::types::ToSqlOutput::Owned(val);
Ok(out) Ok(out)
} }
@@ -4044,6 +4047,7 @@ impl Context {
ChatAction::Block => chat_id.block(self).await, ChatAction::Block => chat_id.block(self).await,
ChatAction::Unblock => chat_id.unblock(self).await, ChatAction::Unblock => chat_id.unblock(self).await,
ChatAction::Accept => chat_id.accept(self).await, ChatAction::Accept => chat_id.accept(self).await,
ChatAction::SetVisibility(v) => chat_id.set_visibility(self, *v).await,
} }
.ok(); .ok();
Ok(()) Ok(())

View File

@@ -5,7 +5,7 @@ use lettre_email::mime::{self};
use lettre_email::PartBuilder; use lettre_email::PartBuilder;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::chat::{self, Chat}; use crate::chat::{self, Chat, ChatVisibility};
use crate::config::Config; use crate::config::Config;
use crate::constants::Blocked; use crate::constants::Blocked;
use crate::contact::ContactId; use crate::contact::ContactId;
@@ -46,6 +46,7 @@ pub(crate) enum ChatAction {
Unblock, Unblock,
Accept, Accept,
SetVisibility(ChatVisibility),
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
@@ -288,6 +289,7 @@ impl Context {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use anyhow::bail; use anyhow::bail;
use strum::IntoEnumIterator;
use super::*; use super::*;
use crate::chat::Chat; use crate::chat::Chat;
@@ -592,6 +594,19 @@ mod tests {
sync(&alices).await?; sync(&alices).await?;
assert_eq!(alices[1].get_chat(&bob).await.blocked, Blocked::Not); assert_eq!(alices[1].get_chat(&bob).await.blocked, Blocked::Not);
assert_eq!(
alices[1].get_chat(&bob).await.get_visibility(),
ChatVisibility::Normal
);
let mut visibilities =
ChatVisibility::iter().chain(std::iter::once(ChatVisibility::Normal));
visibilities.next();
for v in visibilities {
a0b_chat_id.set_visibility(&alices[0], v).await?;
sync(&alices).await?;
assert_eq!(alices[1].get_chat(&bob).await.get_visibility(), v);
}
Ok(()) Ok(())
} }
} }