diff --git a/deltachat-jsonrpc/src/api.rs b/deltachat-jsonrpc/src/api.rs index fca11560d..4ae04bd3d 100644 --- a/deltachat-jsonrpc/src/api.rs +++ b/deltachat-jsonrpc/src/api.rs @@ -16,6 +16,10 @@ use deltachat::chat::{ }; use deltachat::chatlist::Chatlist; use deltachat::config::{get_all_ui_config_keys, Config}; +use deltachat::constants::{ + DC_GCL_ADD_ALLDONE_HINT, DC_GCL_ADD_SELF, DC_GCL_ADDRESS, DC_GCL_ARCHIVED_ONLY, + DC_GCL_FOR_FORWARDING, DC_GCL_NO_SPECIALS, +}; use deltachat::constants::DC_MSG_ID_DAYMARKER; use deltachat::contact::{may_be_valid_addr, Contact, ContactId, Origin}; use deltachat::context::get_info; @@ -722,17 +726,39 @@ impl CommandApi { // chat list // --------------------------------------------- + /// Returns chat list entry IDs. + /// + /// * `archived_only` - Only return archived chats. If not set, only unarchived chats are returned. + /// * `no_specials` - Do not add the archive link entry to the chatlist. + /// * `for_forwarding` - Sort "Saved messages" to the top of the chatlist; typically used when forwarding. + /// * `add_alldone_hint` - Add a hint entry `DC_CHAT_ID_ALLDONE_HINT` to the chatlist if there are only archived chats. async fn get_chatlist_entries( &self, account_id: u32, - list_flags: Option, + archived_only: Option, + no_specials: Option, + for_forwarding: Option, + add_alldone_hint: Option, query_string: Option, query_contact_id: Option, ) -> Result> { let ctx = self.get_context(account_id).await?; + let mut list_flags: usize = 0; + if archived_only.unwrap_or_default() { + list_flags |= DC_GCL_ARCHIVED_ONLY; + } + if no_specials.unwrap_or_default() { + list_flags |= DC_GCL_NO_SPECIALS; + } + if for_forwarding.unwrap_or_default() { + list_flags |= DC_GCL_FOR_FORWARDING; + } + if add_alldone_hint.unwrap_or_default() { + list_flags |= DC_GCL_ADD_ALLDONE_HINT; + } let list = Chatlist::try_load( &ctx, - list_flags.unwrap_or(0) as usize, + list_flags, query_string.as_deref(), query_contact_id.map(ContactId::new), ) @@ -1664,17 +1690,24 @@ impl CommandApi { /// /// By default, key-contacts are listed. /// - /// * `list_flags` - A combination of flags: - /// - `DC_GCL_ADD_SELF` - Add SELF unless filtered by other parameters. - /// - `DC_GCL_ADDRESS` - List address-contacts instead of key-contacts. + /// * `add_self` - Add SELF contact to the list unless filtered by other parameters. + /// * `address_book` - List address-contacts instead of key-contacts. /// * `query` - A string to filter the list. async fn get_contact_ids( &self, account_id: u32, - list_flags: u32, + add_self: Option, + address_book: Option, query: Option, ) -> Result> { let ctx = self.get_context(account_id).await?; + let mut list_flags: u32 = 0; + if add_self.unwrap_or_default() { + list_flags |= DC_GCL_ADD_SELF; + } + if address_book.unwrap_or_default() { + list_flags |= DC_GCL_ADDRESS; + } let contacts = Contact::get_all(&ctx, list_flags, query.as_deref()).await?; Ok(contacts.into_iter().map(|c| c.to_u32()).collect()) } @@ -1686,10 +1719,18 @@ impl CommandApi { async fn get_contacts( &self, account_id: u32, - list_flags: u32, + add_self: Option, + address_book: Option, query: Option, ) -> Result> { let ctx = self.get_context(account_id).await?; + let mut list_flags: u32 = 0; + if add_self.unwrap_or_default() { + list_flags |= DC_GCL_ADD_SELF; + } + if address_book.unwrap_or_default() { + list_flags |= DC_GCL_ADDRESS; + } let contact_ids = Contact::get_all(&ctx, list_flags, query.as_deref()).await?; let mut contacts: Vec = Vec::with_capacity(contact_ids.len()); for id in contact_ids { diff --git a/deltachat-jsonrpc/src/api/types/message.rs b/deltachat-jsonrpc/src/api/types/message.rs index 3a66a0f98..844969ddc 100644 --- a/deltachat-jsonrpc/src/api/types/message.rs +++ b/deltachat-jsonrpc/src/api/types/message.rs @@ -9,10 +9,10 @@ use deltachat::contact::Contact; use deltachat::context::Context; use deltachat::download; use deltachat::message::Message; +use deltachat::message::MessageState; use deltachat::message::MsgId; use deltachat::message::Viewtype; use deltachat::reaction::get_msg_reactions; -use num_traits::cast::ToPrimitive; use serde::{Deserialize, Serialize}; use typescript_type_def::TypeDef; @@ -48,7 +48,7 @@ pub struct MessageObject { has_location: bool, has_html: bool, view_type: MessageViewtype, - state: u32, + state: JsonrpcMessageState, /// An error text, if there is one. error: Option, @@ -213,10 +213,7 @@ impl MessageObject { has_location: message.has_location(), has_html: message.has_html(), view_type: message.get_viewtype().into(), - state: message - .get_state() - .to_u32() - .context("state conversion to number failed")?, + state: message.get_state().into(), error: message.error(), timestamp: message.get_timestamp(), @@ -363,6 +360,68 @@ impl From for Viewtype { } } +#[derive(Serialize, TypeDef, schemars::JsonSchema)] +#[serde(rename = "MessageState")] +pub enum JsonrpcMessageState { + /// Undefined message state. + Undefined, + + /// Incoming *fresh* message. Fresh messages are neither noticed + /// nor seen and are typically shown in notifications. + InFresh, + + /// Incoming *noticed* message. E.g. chat opened but message not + /// yet read - noticed messages are not counted as unread but did + /// not marked as read nor resulted in MDNs. + InNoticed, + + /// Incoming message, really *seen* by the user. Marked as read on + /// IMAP and MDN may be sent. + InSeen, + + /// For files which need time to be prepared before they can be + /// sent, the message enters this state before OutPending. + OutPreparing, + + /// Message saved as draft. + OutDraft, + + /// The user has pressed the "send" button but the message is not + /// yet sent and is pending in some way. Maybe we're offline (no + /// checkmark). + OutPending, + + /// *Unrecoverable* error (*recoverable* errors result in pending + /// messages). + OutFailed, + + /// Outgoing message successfully delivered to server (one + /// checkmark). Note, that already delivered messages may get into + /// the OutFailed state if we get such a hint from the server. + OutDelivered, + + /// Outgoing message read by the recipient (two checkmarks; this + /// requires goodwill on the receiver's side). + OutMdnRcvd, +} + +impl From for JsonrpcMessageState { + fn from(state: MessageState) -> Self { + match state { + MessageState::Undefined => JsonrpcMessageState::Undefined, + MessageState::InFresh => JsonrpcMessageState::InFresh, + MessageState::InNoticed => JsonrpcMessageState::InNoticed, + MessageState::InSeen => JsonrpcMessageState::InSeen, + MessageState::OutPreparing => JsonrpcMessageState::OutPreparing, + MessageState::OutDraft => JsonrpcMessageState::OutDraft, + MessageState::OutPending => JsonrpcMessageState::OutPending, + MessageState::OutFailed => JsonrpcMessageState::OutFailed, + MessageState::OutDelivered => JsonrpcMessageState::OutDelivered, + MessageState::OutMdnRcvd => JsonrpcMessageState::OutMdnRcvd, + } + } +} + #[derive(Serialize, TypeDef, schemars::JsonSchema)] pub enum DownloadState { Done, diff --git a/deltachat-rpc-client/src/deltachat_rpc_client/account.py b/deltachat-rpc-client/src/deltachat_rpc_client/account.py index 522e6e5eb..98c1acc94 100644 --- a/deltachat-rpc-client/src/deltachat_rpc_client/account.py +++ b/deltachat-rpc-client/src/deltachat_rpc_client/account.py @@ -9,7 +9,7 @@ from warnings import warn from ._utils import AttrDict, futuremethod from .chat import Chat -from .const import ChatlistFlag, ContactFlag, EventType, SpecialContactId +from .const import EventType, SpecialContactId from .contact import Contact from .message import Message @@ -246,14 +246,10 @@ class Account: :param with_self: if True the self-contact is also included if it matches the query. :param snapshot: If True return a list of contact snapshots instead of Contact instances. """ - flags = 0 - if with_self: - flags |= ContactFlag.ADD_SELF - if snapshot: - contacts = self._rpc.get_contacts(self.id, flags, query) + contacts = self._rpc.get_contacts(self.id, with_self, None, query) return [AttrDict(contact=Contact(self, contact["id"]), **contact) for contact in contacts] - contacts = self._rpc.get_contact_ids(self.id, flags, query) + contacts = self._rpc.get_contact_ids(self.id, with_self, None, query) return [Contact(self, contact_id) for contact_id in contacts] @property @@ -288,17 +284,15 @@ class Account: as needed. :param snapshot: If True return a list of chat snapshots instead of Chat instances. """ - flags = 0 - if archived_only: - flags |= ChatlistFlag.ARCHIVED_ONLY - if for_forwarding: - flags |= ChatlistFlag.FOR_FORWARDING - if no_specials: - flags |= ChatlistFlag.NO_SPECIALS - if alldone_hint: - flags |= ChatlistFlag.ADD_ALLDONE_HINT - - entries = self._rpc.get_chatlist_entries(self.id, flags, query, contact and contact.id) + entries = self._rpc.get_chatlist_entries( + self.id, + archived_only, + no_specials, + for_forwarding, + alldone_hint, + query, + contact and contact.id, + ) if not snapshot: return [Chat(self, entry) for entry in entries] diff --git a/deltachat-rpc-client/src/deltachat_rpc_client/const.py b/deltachat-rpc-client/src/deltachat_rpc_client/const.py index cee9536be..c052c1a87 100644 --- a/deltachat-rpc-client/src/deltachat_rpc_client/const.py +++ b/deltachat-rpc-client/src/deltachat_rpc_client/const.py @@ -183,19 +183,19 @@ class SystemMessageType(str, Enum): WEBXDC_INFO_MESSAGE = "WebxdcInfoMessage" -class MessageState(IntEnum): +class MessageState(str, Enum): """State of the message.""" - UNDEFINED = 0 - IN_FRESH = 10 - IN_NOTICED = 13 - IN_SEEN = 16 - OUT_PREPARING = 18 - OUT_DRAFT = 19 - OUT_PENDING = 20 - OUT_FAILED = 24 - OUT_DELIVERED = 26 - OUT_MDN_RCVD = 28 + UNDEFINED = "Undefined" + IN_FRESH = "InFresh" + IN_NOTICED = "InNoticed" + IN_SEEN = "InSeen" + OUT_PREPARING = "OutPreparing" + OUT_DRAFT = "OutDraft" + OUT_PENDING = "OutPending" + OUT_FAILED = "OutFailed" + OUT_DELIVERED = "OutDelivered" + OUT_MDN_RCVD = "OutMdnRcvd" class MessageId(IntEnum):