Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions deltachat-ffi/deltachat.h
Original file line number Diff line number Diff line change
Expand Up @@ -4473,6 +4473,7 @@ int dc_msg_is_info (const dc_msg_t* msg);
* - DC_INFO_WEBXDC_INFO_MESSAGE (32) - Info-message created by webxdc app sending `update.info`
* - DC_INFO_CHAT_E2EE (50) - Info-message for "Chat is end-to-end-encrypted"
* - DC_INFO_GROUP_DESCRIPTION_CHANGED (70) - Info-message "Description changed", UI should open the profile with the description
* - DC_INFO_MESSAGE_PINNED (71) - Message pinned, UI should scroll to the pinned message returned by dc_msg_get_parent()
*
* For the messages that refer to a CONTACT,
* dc_msg_get_info_contact_id() returns the contact ID.
Expand Down Expand Up @@ -4532,6 +4533,7 @@ uint32_t dc_msg_get_info_contact_id (const dc_msg_t* msg);
#define DC_INFO_WEBXDC_INFO_MESSAGE 32
#define DC_INFO_CHAT_E2EE 50
#define DC_INFO_GROUP_DESCRIPTION_CHANGED 70
#define DC_INFO_MESSAGE_PINNED 71


/**
Expand Down Expand Up @@ -4849,6 +4851,8 @@ dc_msg_t* dc_msg_get_quoted_msg (const dc_msg_t* msg);
* Used for Webxdc-info-messages
* to jump to the corresponding instance that created the info message.
*
* For Pinned-info-messages, this refers to the pinned message.
*
* For quotes, please use the more specialized
* dc_msg_get_quoted_text() and dc_msg_get_quoted_msg().
*
Expand Down Expand Up @@ -4888,6 +4892,20 @@ uint32_t dc_msg_get_original_msg_id (const dc_msg_t* msg);
*/
uint32_t dc_msg_get_saved_msg_id (const dc_msg_t* msg);


/**
* Check if the message is pinned.
*
* Pinned messages should be marked by a pin needle in the UI.
* To pin messages or get all pinned messages, use jsonrpc's "setPinnedMessageState" and "getPinnedMessages".
*
* @memberof dc_msg_t
* @param msg The message object.
* @return 1=message is pinned, 0=message not pinned.
*/
int dc_msg_is_pinned (const dc_msg_t* msg);


/**
* @class dc_contact_t
*
Expand Down Expand Up @@ -5672,6 +5690,7 @@ void dc_jsonrpc_unref(dc_jsonrpc_instance_t* jsonrpc_instance);
* - getAccountFileSize()
* - importVcard(), parseVcard(), makeVcard()
* - sendWebxdcRealtimeData, sendWebxdcRealtimeAdvertisement(), leaveWebxdcRealtime()
* - setPinnedMessageState(), getPinnedMessages()
*
* @memberof dc_jsonrpc_instance_t
* @param jsonrpc_instance jsonrpc instance as returned from dc_jsonrpc_init().
Expand Down Expand Up @@ -7249,6 +7268,12 @@ void dc_event_unref(dc_event_t* event);
/// Used when creating text for the "Encryption Info" dialogs.
#define DC_STR_MESSAGES_ARE_E2EE 242

/// "You pinned a message."
#define DC_STR_MESSAGE_PINNED_BY_YOU 243

/// "Message pinned by %1$s."
#define DC_STR_MESSAGE_PINNED_BY_OTHER 244

/**
* @}
*/
Expand Down
10 changes: 10 additions & 0 deletions deltachat-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3904,6 +3904,16 @@ pub unsafe extern "C" fn dc_msg_get_saved_msg_id(msg: *const dc_msg_t) -> u32 {
.unwrap_or(0)
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn dc_msg_is_pinned(msg: *mut dc_msg_t) -> libc::c_int {
if msg.is_null() {
eprintln!("ignoring careless call to dc_msg_is_pinned()");
return 0;
}
let ffi_msg = unsafe { &*msg };
ffi_msg.message.is_pinned().into()
}

// dc_contact_t

/// FFI struct for [dc_contact_t]
Expand Down
20 changes: 20 additions & 0 deletions deltachat-jsonrpc/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1508,6 +1508,26 @@ impl CommandApi {
MessageNotificationInfo::from_msg_id(&ctx, MsgId::new(message_id)).await
}

/// Sets the "pinned" state for a message.
async fn set_pinned_message_state(
&self,
account_id: u32,
message_id: u32,
pinned_state: bool,
) -> Result<()> {
let ctx = self.get_context(account_id).await?;
deltachat::pinned_messages::set_pinned_state(&ctx, MsgId::new(message_id), pinned_state)
.await
}

/// Returns all pinned messages of a chat.
async fn get_pinned_messages(&self, account_id: u32, chat_id: u32) -> Result<Vec<u32>> {
let ctx = self.get_context(account_id).await?;
let msg_ids =
deltachat::pinned_messages::get_pinned_messages(&ctx, ChatId::new(chat_id)).await?;
Ok(msg_ids.into_iter().map(|id| id.to_u32()).collect())
}

/// Delete messages. The messages are deleted on the current device and
/// on the IMAP server.
async fn delete_messages(&self, account_id: u32, message_ids: Vec<u32>) -> Result<()> {
Expand Down
7 changes: 7 additions & 0 deletions deltachat-jsonrpc/src/api/types/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ pub struct MessageObject {

saved_message_id: Option<u32>,

is_pinned: bool,

reactions: Option<JsonrpcReactions>,

vcard_contact: Option<VcardContact>,
Expand Down Expand Up @@ -263,6 +265,7 @@ impl MessageObject {
.await?
.map(|id| id.to_u32()),

is_pinned: message.is_pinned(),
reactions,

vcard_contact: vcard_contacts.first().cloned(),
Expand Down Expand Up @@ -425,6 +428,8 @@ pub enum SystemMessageType {

CallAccepted,
CallEnded,
MessagePinned,
MessageUnpinned,
}

impl From<deltachat::mimeparser::SystemMessage> for SystemMessageType {
Expand Down Expand Up @@ -454,6 +459,8 @@ impl From<deltachat::mimeparser::SystemMessage> for SystemMessageType {
SystemMessage::SecurejoinWaitTimeout => SystemMessageType::SecurejoinWaitTimeout,
SystemMessage::CallAccepted => SystemMessageType::CallAccepted,
SystemMessage::CallEnded => SystemMessageType::CallEnded,
SystemMessage::MessagePinned => SystemMessageType::MessagePinned,
SystemMessage::MessageUnpinned => SystemMessageType::MessageUnpinned,
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4612,6 +4612,7 @@ pub async fn forward_msgs_2ctx(
msg.rfc724_mid = create_outgoing_rfc724_mid();
msg.pre_rfc724_mid.clear();
msg.timestamp_sort = now;
msg.pinned = false;
chat.prepare_msg_raw(ctx_dst, &mut msg, None).await?;

if !create_send_msg_jobs(ctx_dst, &mut msg).await?.is_empty() {
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ mod param;
mod pgp;
#[cfg(feature = "internals")]
pub mod pgp;
pub mod pinned_messages;
pub mod provider;
pub mod qr;
pub mod qr_code_generator;
Expand Down
10 changes: 10 additions & 0 deletions src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ pub struct Message {
pub(crate) in_reply_to: Option<String>,
pub(crate) is_dc_message: MessengerMessage,
pub(crate) original_msg_id: MsgId,
pub(crate) pinned: bool,
pub(crate) mime_modified: bool,
pub(crate) chat_visibility: ChatVisibility,
pub(crate) chat_blocked: Blocked,
Expand Down Expand Up @@ -530,6 +531,7 @@ impl Message {
m.error AS error,
m.msgrmsg AS msgrmsg,
m.starred AS original_msg_id,
m.pinned AS pinned,
m.mime_modified AS mime_modified,
m.txt AS txt,
m.subject AS subject,
Expand Down Expand Up @@ -588,6 +590,7 @@ impl Message {
.filter(|error| !error.is_empty()),
is_dc_message: row.get("msgrmsg")?,
original_msg_id: row.get("original_msg_id")?,
pinned: row.get("pinned")?,
mime_modified: row.get("mime_modified")?,
text,
additional_text: String::new(),
Expand Down Expand Up @@ -1080,6 +1083,8 @@ impl Message {
| SystemMessage::IrohNodeAddr
| SystemMessage::CallAccepted
| SystemMessage::CallEnded
| SystemMessage::MessagePinned // UI should scroll to pinned message on tapping
| SystemMessage::MessageUnpinned // UI should scroll to unpinned message on tapping
| SystemMessage::Unknown => Ok(None),
}
}
Expand Down Expand Up @@ -1346,6 +1351,11 @@ impl Message {
Ok(res)
}

/// Returns true if the message is pinned.
pub fn is_pinned(&self) -> bool {
self.pinned
}

/// Force the message to be sent in plain text.
pub(crate) fn force_plaintext(&mut self) {
self.param.set_int(Param::ForcePlaintext, 1);
Expand Down
14 changes: 14 additions & 0 deletions src/mimefactory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1812,6 +1812,8 @@ impl MimeFactory {
SystemMessage::ChatE2ee => {}
SystemMessage::CallAccepted => {}
SystemMessage::CallEnded => {}
SystemMessage::MessagePinned => {}
SystemMessage::MessageUnpinned => {}
}

if command == SystemMessage::GroupDescriptionChanged
Expand Down Expand Up @@ -1937,6 +1939,18 @@ impl MimeFactory {
mail_builder::headers::raw::Raw::new("call-ended").into(),
));
}
SystemMessage::MessagePinned => {
headers.push((
"Chat-Content",
mail_builder::headers::raw::Raw::new("message-pinned").into(),
));
}
SystemMessage::MessageUnpinned => {
headers.push((
"Chat-Content",
mail_builder::headers::raw::Raw::new("message-unpinned").into(),
));
}
_ => {}
}

Expand Down
10 changes: 10 additions & 0 deletions src/mimeparser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,12 @@ pub enum SystemMessage {

/// Group or broadcast channel description changed.
GroupDescriptionChanged = 70,

/// Message pinned. The pinned message is referred in `In-Reply-To:` header.
MessagePinned = 71,

/// Message unpinned. The unpinned message is referred in `In-Reply-To:` header.
MessageUnpinned = 72,
}

impl MimeMessage {
Expand Down Expand Up @@ -741,6 +747,10 @@ impl MimeMessage {
self.is_system_message = SystemMessage::CallAccepted;
} else if value == "call-ended" {
self.is_system_message = SystemMessage::CallEnded;
} else if value == "message-pinned" {
self.is_system_message = SystemMessage::MessagePinned;
} else if value == "message-unpinned" {
self.is_system_message = SystemMessage::MessageUnpinned;
}
} else if self.get_header(HeaderDef::ChatGroupMemberRemoved).is_some() {
self.is_system_message = SystemMessage::MemberRemovedFromGroup;
Expand Down
Loading
Loading