Add DC_EVENT_MSG_DELETE_TIMEOUT_CHANGED

This event tells the client when the next message will be deleted. When
this event is received, the client should start a timer and update
current chat or chatlist when timeout expires.
This commit is contained in:
Alexander Krotov
2020-05-20 01:22:56 +03:00
parent 9d033e2ea1
commit f3137d87c5
5 changed files with 71 additions and 7 deletions

View File

@@ -4405,6 +4405,17 @@ int64_t dc_lot_get_timestamp (const dc_lot_t* lot);
*/
#define DC_EVENT_MSG_READ 2015
/**
* Time left until the next message deletion has changed.
*
* The only parameter is the number of seconds left until next message
* deletion. It is rounded up. If the timer is 0, it means there are no
* messages to be deleted in the future.
*
* @param data1 (int) Timer in seconds
* @param data2 (int) 0
*/
#define DC_EVENT_MSG_DELETE_TIMEOUT_CHANGED 2016
/**
* Chat changed. The name or the image of a chat group was changed or members were added or removed.

View File

@@ -167,6 +167,9 @@ impl ContextWrapper {
msg_id.to_u32() as uintptr_t,
);
}
Event::MsgDeleteTimeoutChanged { timer } => {
ffi_cb(self, event_id, timer as uintptr_t, 0);
}
Event::ChatModified(chat_id) => {
ffi_cb(self, event_id, chat_id.to_u32() as uintptr_t, 0);
}

View File

@@ -1,6 +1,6 @@
//! # Chat module
use std::convert::TryFrom;
use std::convert::{TryFrom, TryInto};
use std::path::{Path, PathBuf};
use std::time::{Duration, SystemTime};
@@ -931,6 +931,7 @@ impl Chat {
} else {
error!(context, "Cannot send message, not configured.",);
}
update_autodelete_timeout(context);
Ok(MsgId::new(msg_id))
}
@@ -1600,11 +1601,48 @@ pub fn marknoticed_all_chats(context: &Context) -> Result<(), Error> {
Ok(())
}
/// Emits an event to update the time until the next local deletion.
///
/// This takes into account only per-chat timeouts, because global device
/// timeouts are at least one hour long and deletion is triggered often enough
/// by user actions.
pub fn update_autodelete_timeout(context: &Context) {
let autodelete_timestamp: Option<i64> = match context.sql.query_get_value_result(
"SELECT autodelete_timestamp \
FROM msgs \
WHERE autodelete_timestamp != 0 \
ORDER BY autodelete_timestamp ASC \
LIMIT 1",
rusqlite::NO_PARAMS,
) {
Err(err) => {
warn!(context, "Can't calculate next autodelete timeout: {}", err);
return;
}
Ok(autodelete_timestamp) => autodelete_timestamp,
};
let timer = if let Some(next_autodelete) = autodelete_timestamp {
let now = time();
if now > next_autodelete {
1
} else {
(next_autodelete - now)
.try_into()
.unwrap_or(u32::MAX)
.saturating_add(1)
}
} else {
0
};
emit_event!(context, Event::MsgDeleteTimeoutChanged { timer });
}
/// Deletes messages which are expired according to "delete_device_after" setting.
///
/// Returns true if any message is deleted, so event can be emitted. If nothing
/// has been deleted, returns false.
pub fn delete_device_expired_messages(context: &Context) -> Result<bool, Error> {
pub(crate) fn delete_device_expired_messages(context: &Context) -> Result<bool, Error> {
let now = time();
let threshold_timestamp = match context.get_config_delete_device_after() {
@@ -1650,7 +1688,11 @@ pub fn delete_device_expired_messages(context: &Context) -> Result<bool, Error>
],
)?;
Ok(rows_modified > 0)
let updated = rows_modified > 0;
if updated {
update_autodelete_timeout(context);
}
Ok(updated)
}
pub fn get_chat_media(

View File

@@ -132,6 +132,14 @@ pub enum Event {
#[strum(props(id = "2015"))]
MsgRead { chat_id: ChatId, msg_id: MsgId },
/// Time left until the next message deletion has changed.
///
/// The only parameter is the number of seconds left until next message
/// deletion. It is rounded up. If the timer is 0, it means there are no
/// messages to be deleted in the future.
#[strum(props(id = "2016"))]
MsgDeleteTimeoutChanged { timer: u32 },
/// Chat changed. The name or the image of a chat group was changed or members were added or removed.
/// Or the verify state of a chat has changed.
/// See dc_set_chat_name(), dc_set_chat_profile_image(), dc_add_contact_to_chat()

View File

@@ -6,7 +6,7 @@ use deltachat_derive::{FromSql, ToSql};
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use crate::chat::{self, Chat, ChatId};
use crate::chat::{self, update_autodelete_timeout, Chat, ChatId};
use crate::constants::*;
use crate::contact::*;
use crate::context::*;
@@ -157,10 +157,10 @@ impl MsgId {
WHERE (autodelete_timestamp == 0 OR autodelete_timestamp > ?) \
AND id = ?",
params![autodelete_timestamp, autodelete_timestamp, self],
)
} else {
Ok(())
)?;
update_autodelete_timeout(context);
}
Ok(())
}
/// Bad evil escape hatch.