mirror of
https://github.com/chatmail/core.git
synced 2026-05-06 06:46:35 +03:00
add possibility to mute chat in core
This commit is contained in:
109
src/chat.rs
109
src/chat.rs
@@ -422,6 +422,7 @@ pub struct Chat {
|
|||||||
blocked: Blocked,
|
blocked: Blocked,
|
||||||
pub param: Params,
|
pub param: Params,
|
||||||
is_sending_locations: bool,
|
is_sending_locations: bool,
|
||||||
|
pub mute_duration: MuteDuration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Chat {
|
impl Chat {
|
||||||
@@ -429,7 +430,7 @@ impl Chat {
|
|||||||
pub fn load_from_db(context: &Context, chat_id: ChatId) -> Result<Self, Error> {
|
pub fn load_from_db(context: &Context, chat_id: ChatId) -> Result<Self, Error> {
|
||||||
let res = context.sql.query_row(
|
let res = context.sql.query_row(
|
||||||
"SELECT c.type, c.name, c.grpid, c.param, c.archived,
|
"SELECT c.type, c.name, c.grpid, c.param, c.archived,
|
||||||
c.blocked, c.locations_send_until
|
c.blocked, c.locations_send_until, c.muted_until
|
||||||
FROM chats c
|
FROM chats c
|
||||||
WHERE c.id=?;",
|
WHERE c.id=?;",
|
||||||
params![chat_id],
|
params![chat_id],
|
||||||
@@ -443,6 +444,7 @@ impl Chat {
|
|||||||
archived: row.get(4)?,
|
archived: row.get(4)?,
|
||||||
blocked: row.get::<_, Option<_>>(5)?.unwrap_or_default(),
|
blocked: row.get::<_, Option<_>>(5)?.unwrap_or_default(),
|
||||||
is_sending_locations: row.get(6)?,
|
is_sending_locations: row.get(6)?,
|
||||||
|
mute_duration: MuteDuration::deserialize(row.get(7)?),
|
||||||
};
|
};
|
||||||
Ok(c)
|
Ok(c)
|
||||||
},
|
},
|
||||||
@@ -658,6 +660,7 @@ impl Chat {
|
|||||||
profile_image: self.get_profile_image(context).unwrap_or_else(PathBuf::new),
|
profile_image: self.get_profile_image(context).unwrap_or_else(PathBuf::new),
|
||||||
subtitle: self.get_subtitle(context),
|
subtitle: self.get_subtitle(context),
|
||||||
draft,
|
draft,
|
||||||
|
is_muted: self.is_muted(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -684,6 +687,14 @@ impl Chat {
|
|||||||
self.is_sending_locations
|
self.is_sending_locations
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_muted(&self) -> bool {
|
||||||
|
match self.mute_duration {
|
||||||
|
MuteDuration::NotMuted => false,
|
||||||
|
MuteDuration::Forever => true,
|
||||||
|
MuteDuration::MutedUntilTimestamp(timestamp) => timestamp > time(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn prepare_msg_raw(
|
fn prepare_msg_raw(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
@@ -968,6 +979,11 @@ pub struct ChatInfo {
|
|||||||
/// which contain non-text parts. Perhaps it should be a
|
/// which contain non-text parts. Perhaps it should be a
|
||||||
/// simple `has_draft` bool instead.
|
/// simple `has_draft` bool instead.
|
||||||
pub draft: String,
|
pub draft: String,
|
||||||
|
|
||||||
|
/// Wether the chat is muted
|
||||||
|
///
|
||||||
|
/// The exact time its muted can be found out via the `chat.mute_duration` property
|
||||||
|
pub is_muted:bool,
|
||||||
// ToDo:
|
// ToDo:
|
||||||
// - [ ] deaddrop,
|
// - [ ] deaddrop,
|
||||||
// - [ ] summary,
|
// - [ ] summary,
|
||||||
@@ -1901,6 +1917,56 @@ pub fn shall_attach_selfavatar(context: &Context, chat_id: ChatId) -> Result<boo
|
|||||||
Ok(needs_attach)
|
Ok(needs_attach)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum MuteDuration {
|
||||||
|
NotMuted,
|
||||||
|
Forever,
|
||||||
|
MutedUntilTimestamp(i64),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MuteDuration {
|
||||||
|
// TODO use serde compatible functions?
|
||||||
|
fn serialize (&self) -> i64 {
|
||||||
|
match &self {
|
||||||
|
MuteDuration::NotMuted => 0,
|
||||||
|
MuteDuration::Forever => 1,
|
||||||
|
MuteDuration::MutedUntilTimestamp(timestamp) => *timestamp as i64, // TODO make this pretier?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize (value: i64) -> MuteDuration {
|
||||||
|
match value {
|
||||||
|
0 => MuteDuration::NotMuted,
|
||||||
|
1 => MuteDuration::Forever,
|
||||||
|
_ => MuteDuration::MutedUntilTimestamp(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_muted (
|
||||||
|
context: &Context,
|
||||||
|
chat_id: ChatId,
|
||||||
|
duration: MuteDuration
|
||||||
|
) -> Result<(), Error>{
|
||||||
|
let mut success = false;
|
||||||
|
ensure!(!chat_id.is_special(), "Invalid chat ID");
|
||||||
|
if real_group_exists(context, chat_id) && sql::execute(
|
||||||
|
context,
|
||||||
|
&context.sql,
|
||||||
|
"UPDATE chats SET muted_until=? WHERE id=?;",
|
||||||
|
params![duration.serialize(), chat_id],
|
||||||
|
).is_ok() {
|
||||||
|
context.call_cb(Event::ChatModified(chat_id));
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !success {
|
||||||
|
bail!("Failed to set name");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn remove_contact_from_chat(
|
pub fn remove_contact_from_chat(
|
||||||
context: &Context,
|
context: &Context,
|
||||||
chat_id: ChatId,
|
chat_id: ChatId,
|
||||||
@@ -2386,6 +2452,7 @@ pub fn add_info_msg(context: &Context, chat_id: ChatId, text: impl AsRef<str>) {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
use crate::contact::Contact;
|
use crate::contact::Contact;
|
||||||
use crate::test_utils::*;
|
use crate::test_utils::*;
|
||||||
@@ -2413,7 +2480,8 @@ mod tests {
|
|||||||
"color": 15895624,
|
"color": 15895624,
|
||||||
"profile_image": "",
|
"profile_image": "",
|
||||||
"subtitle": "bob@example.com",
|
"subtitle": "bob@example.com",
|
||||||
"draft": ""
|
"draft": "",
|
||||||
|
"is_muted": false
|
||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
@@ -2777,4 +2845,41 @@ mod tests {
|
|||||||
assert!(chat_id.set_selfavatar_timestamp(&t.ctx, time()).is_ok());
|
assert!(chat_id.set_selfavatar_timestamp(&t.ctx, time()).is_ok());
|
||||||
assert!(!shall_attach_selfavatar(&t.ctx, chat_id).unwrap());
|
assert!(!shall_attach_selfavatar(&t.ctx, chat_id).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_mute_duration() {
|
||||||
|
let t = dummy_context();
|
||||||
|
let chat_id = create_group_chat(&t.ctx, VerifiedStatus::Unverified, "foo").unwrap();
|
||||||
|
// Initial
|
||||||
|
assert_eq!(
|
||||||
|
Chat::load_from_db(&t.ctx, chat_id).unwrap().is_muted(),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
// Forever
|
||||||
|
set_muted(&t.ctx, chat_id, MuteDuration::Forever).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
Chat::load_from_db(&t.ctx, chat_id).unwrap().is_muted(),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
// unMute
|
||||||
|
set_muted(&t.ctx, chat_id, MuteDuration::NotMuted).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
Chat::load_from_db(&t.ctx, chat_id).unwrap().is_muted(),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
// Timed in the future
|
||||||
|
let current_timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap() + Duration::from_secs(3600);
|
||||||
|
set_muted(&t.ctx, chat_id, MuteDuration::MutedUntilTimestamp(current_timestamp.as_secs() as i64)).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
Chat::load_from_db(&t.ctx, chat_id).unwrap().is_muted(),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
// Time in the past
|
||||||
|
let past_timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap() - Duration::from_secs(3600);
|
||||||
|
set_muted(&t.ctx, chat_id, MuteDuration::MutedUntilTimestamp(past_timestamp.as_secs() as i64)).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
Chat::load_from_db(&t.ctx, chat_id).unwrap().is_muted(),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -885,6 +885,14 @@ fn open(
|
|||||||
update_icons = true;
|
update_icons = true;
|
||||||
sql.set_raw_config_int(context, "dbversion", 61)?;
|
sql.set_raw_config_int(context, "dbversion", 61)?;
|
||||||
}
|
}
|
||||||
|
if dbversion < 62 {
|
||||||
|
info!(context, "[migration] v62");
|
||||||
|
sql.execute(
|
||||||
|
"ALTER TABLE chats ADD COLUMN muted_until INTEGER DEFAULT 0;",
|
||||||
|
NO_PARAMS,
|
||||||
|
)?;
|
||||||
|
sql.set_raw_config_int(context, "dbversion", 62)?;
|
||||||
|
}
|
||||||
|
|
||||||
// (2) updates that require high-level objects
|
// (2) updates that require high-level objects
|
||||||
// (the structure is complete now and all objects are usable)
|
// (the structure is complete now and all objects are usable)
|
||||||
|
|||||||
Reference in New Issue
Block a user