Add API to get next fresh message

Rust: Context.get_next_fresh_msg()
C: dc_get_next_fresh_msg()
JSON-RPC: get_next_fresh_msg method
This commit is contained in:
link2xt
2022-11-27 11:37:24 +00:00
parent 08de326930
commit f02888e3cc
5 changed files with 58 additions and 2 deletions

View File

@@ -6,6 +6,7 @@
### API-Changes
- Add Python API to send reactions #3762
- Add API to get next fresh message
### Fixes
- Make sure malformed messsages will never block receiving further messages anymore #3771

View File

@@ -1278,6 +1278,16 @@ int dc_estimate_deletion_cnt (dc_context_t* context, int from_ser
dc_array_t* dc_get_fresh_msgs (dc_context_t* context);
/**
* Returns the ID of the fresh message of any chat.
*
* @memberof dc_context_t
* @param context The context object as returned from dc_context_new().
* @return Message ID of the next fresh message. Returns 0 on error.
*/
dc_array_t* dc_get_next_fresh_msg (dc_context_t* context);
/**
* Mark all messages in a chat as _noticed_.
* _Noticed_ messages are no longer _fresh_ and do not count as being unseen

View File

@@ -1243,6 +1243,20 @@ pub unsafe extern "C" fn dc_get_fresh_msgs(
})
}
#[no_mangle]
pub unsafe extern "C" fn dc_get_next_fresh_msg(context: *mut dc_context_t) -> u32 {
if context.is_null() {
eprintln!("ignoring careless call to dc_get_next_fresh_msg()");
return 0;
}
let ctx = &*context;
block_on(ctx.get_next_fresh_msg())
.log_err(ctx, "Failed to get next fresh message")
.unwrap_or_default()
.to_u32()
}
#[no_mangle]
pub unsafe extern "C" fn dc_marknoticed_chat(context: *mut dc_context_t, chat_id: u32) {
if context.is_null() {

View File

@@ -372,6 +372,15 @@ impl CommandApi {
.collect())
}
/// Returns the message ID of the oldest fresh message.
///
/// If there are no such messages, waits until there is one.
async fn get_next_fresh_msg(&self, account_id: u32) -> Result<u32> {
let ctx = self.get_context(account_id).await?;
let msg_id = ctx.get_next_fresh_msg().await?;
Ok(msg_id.to_u32())
}
/// Get the number of _fresh_ messages in a chat.
/// Typically used to implement a badge with a number in the chatlist.
///

View File

@@ -9,7 +9,7 @@ use std::time::{Duration, Instant, SystemTime};
use anyhow::{ensure, Result};
use async_channel::{self as channel, Receiver, Sender};
use tokio::sync::{Mutex, RwLock};
use tokio::sync::{Mutex, Notify, RwLock};
use crate::chat::{get_chat_cnt, ChatId};
use crate::config::Config;
@@ -205,6 +205,11 @@ pub struct InnerContext {
pub(crate) translated_stockstrings: StockStrings,
pub(crate) events: Events,
/// Notify about fresh messages.
///
/// This notification is used only internally for [`InternalContext.get_next_fresh_msg()`].
pub(crate) notify_fresh_message: Notify,
pub(crate) scheduler: RwLock<Option<Scheduler>>,
pub(crate) ratelimit: RwLock<Ratelimit>,
@@ -354,6 +359,7 @@ impl Context {
wrong_pw_warning_mutex: Mutex::new(()),
translated_stockstrings: stockstrings,
events,
notify_fresh_message: Notify::new(),
scheduler: RwLock::new(None),
ratelimit: RwLock::new(Ratelimit::new(Duration::new(60, 0), 6.0)), // Allow to send 6 messages immediately, no more than once every 10 seconds.
quota: RwLock::new(None),
@@ -451,9 +457,12 @@ impl Context {
self.emit_event(EventType::MsgsChanged { chat_id, msg_id });
}
/// Emits an IncomingMsg event with specified chat and message ids
/// Emits an IncomingMsg event with specified chat and message ids.
///
/// Notifies `get_next_fresh_msg()` that there might be a new fresh message.
pub fn emit_incoming_msg(&self, chat_id: ChatId, msg_id: MsgId) {
self.emit_event(EventType::IncomingMsg { chat_id, msg_id });
self.notify_fresh_message.notify_one();
}
/// Returns a receiver for emitted events.
@@ -751,6 +760,19 @@ impl Context {
Ok(list)
}
/// Returns oldest fresh message in unmuted and unblocked chats.
///
/// If there are no such messages, waits until there is one.
pub async fn get_next_fresh_msg(&self) -> Result<MsgId> {
loop {
if let Some(msg_id) = self.get_fresh_msgs().await?.last() {
return Ok(*msg_id);
} else {
self.notify_fresh_message.notified().await;
}
}
}
/// Searches for messages containing the query string.
///
/// If `chat_id` is provided this searches only for messages in this chat, if `chat_id`