refacor: use an enum for events

This commit is contained in:
dignifiedquire
2019-09-15 16:19:27 +02:00
committed by Floris Bruynooghe
parent ac12b2e643
commit 5486ac5b9f
22 changed files with 553 additions and 603 deletions

View File

@@ -2,8 +2,6 @@ use std::ffi::CString;
use std::path::{Path, PathBuf};
use std::ptr;
use libc::uintptr_t;
use crate::chatlist::*;
use crate::config::*;
use crate::constants::*;
@@ -11,6 +9,7 @@ use crate::contact::*;
use crate::context::Context;
use crate::dc_tools::*;
use crate::error::Error;
use crate::events::Event;
use crate::job::*;
use crate::message::*;
use crate::param::*;
@@ -259,11 +258,9 @@ impl Chat {
if (self.typ == Chattype::Group || self.typ == Chattype::VerifiedGroup)
&& 0 == is_contact_in_chat(context, self.id, 1 as u32)
{
log_event!(
emit_event!(
context,
Event::ERROR_SELF_NOT_IN_GROUP,
0,
"Cannot send message; self not in group.",
Event::ErrorSelfNotInGroup("Cannot send message; self not in group.".into())
);
return Ok(0);
}
@@ -502,7 +499,10 @@ pub fn create_by_msg_id(context: &Context, msg_id: u32) -> Result<u32, Error> {
}
if send_event {
context.call_cb(Event::MSGS_CHANGED, 0, 0);
context.call_cb(Event::MsgsChanged {
chat_id: 0,
msg_id: 0,
});
}
ensure!(chat_id > 0, "failed to load create chat");
@@ -542,7 +542,10 @@ pub fn create_by_contact_id(context: &Context, contact_id: u32) -> Result<u32, E
}
};
context.call_cb(Event::MSGS_CHANGED, 0i32 as uintptr_t, 0i32 as uintptr_t);
context.call_cb(Event::MsgsChanged {
chat_id: 0,
msg_id: 0,
});
Ok(chat_id)
}
@@ -635,11 +638,10 @@ pub fn prepare_msg<'a>(
msg.state = MessageState::OutPreparing;
let msg_id = prepare_msg_common(context, chat_id, msg)?;
context.call_cb(
Event::MSGS_CHANGED,
msg.chat_id as uintptr_t,
msg.id as uintptr_t,
);
context.call_cb(Event::MsgsChanged {
chat_id: msg.chat_id,
msg_id: msg.id,
});
Ok(msg_id)
}
@@ -790,14 +792,13 @@ pub fn send_msg(context: &Context, chat_id: u32, msg: &mut Message) -> Result<u3
"Failed to initiate send job"
);
context.call_cb(
Event::MSGS_CHANGED,
msg.chat_id as uintptr_t,
msg.id as uintptr_t,
);
context.call_cb(Event::MsgsChanged {
chat_id: msg.chat_id,
msg_id: msg.id,
});
if msg.param.exists(Param::SetLatitude) {
context.call_cb(Event::LOCATION_CHANGED, DC_CONTACT_ID_SELF as usize, 0);
context.call_cb(Event::LocationChanged(Some(DC_CONTACT_ID_SELF)));
}
if 0 == chat_id {
@@ -845,7 +846,7 @@ pub unsafe fn set_draft(context: &Context, chat_id: u32, msg: Option<&mut Messag
return;
}
if set_draft_raw(context, chat_id, msg) {
context.call_cb(Event::MSGS_CHANGED, chat_id as uintptr_t, 0i32 as uintptr_t);
context.call_cb(Event::MsgsChanged { chat_id, msg_id: 0 });
};
}
@@ -1042,7 +1043,10 @@ pub fn marknoticed_chat(context: &Context, chat_id: u32) -> Result<(), Error> {
params![chat_id as i32],
)?;
context.call_cb(Event::MSGS_CHANGED, 0 as uintptr_t, 0 as uintptr_t);
context.call_cb(Event::MsgsChanged {
chat_id: 0,
msg_id: 0,
});
Ok(())
}
@@ -1064,7 +1068,10 @@ pub fn marknoticed_all_chats(context: &Context) -> Result<(), Error> {
params![],
)?;
context.call_cb(Event::MSGS_CHANGED, 0 as uintptr_t, 0 as uintptr_t);
context.call_cb(Event::MsgsChanged {
msg_id: 0,
chat_id: 0,
});
Ok(())
}
@@ -1169,7 +1176,10 @@ pub fn archive(context: &Context, chat_id: u32, archive: bool) -> Result<(), Err
params![archive, chat_id as i32],
)?;
context.call_cb(Event::MSGS_CHANGED, 0 as uintptr_t, 0 as uintptr_t);
context.call_cb(Event::MsgsChanged {
msg_id: 0,
chat_id: 0,
});
Ok(())
}
@@ -1211,7 +1221,10 @@ pub fn delete(context: &Context, chat_id: u32) -> Result<(), Error> {
params![chat_id as i32],
)?;
context.call_cb(Event::MSGS_CHANGED, 0 as uintptr_t, 0 as uintptr_t);
context.call_cb(Event::MsgsChanged {
msg_id: 0,
chat_id: 0,
});
job_kill_action(context, Action::Housekeeping);
job_add(context, Action::Housekeeping, 0, Params::new(), 10);
@@ -1279,7 +1292,10 @@ pub unsafe fn create_group_chat(
set_draft_raw(context, chat_id, Some(&mut draft_msg));
}
context.call_cb(Event::MSGS_CHANGED, 0 as uintptr_t, 0 as uintptr_t);
context.call_cb(Event::MsgsChanged {
msg_id: 0,
chat_id: 0,
});
}
Ok(chat_id)
@@ -1328,11 +1344,11 @@ pub fn add_contact_to_chat_ex(
|| !Contact::real_exists_by_id(context, contact_id) && contact_id != DC_CONTACT_ID_SELF)
{
if !(is_contact_in_chat(context, chat_id, 1 as u32) == 1) {
log_event!(
emit_event!(
context,
Event::ERROR_SELF_NOT_IN_GROUP,
0,
"Cannot add contact to group; self not in group.",
Event::ErrorSelfNotInGroup(
"Cannot add contact to group; self not in group.".into()
)
);
} else {
/* we should respect this - whatever we send to the group, it gets discarded anyway! */
@@ -1385,13 +1401,12 @@ pub fn add_contact_to_chat_ex(
msg.param.set(Param::Arg, contact.get_addr());
msg.param.set_int(Param::Arg2, flags);
msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default();
context.call_cb(
Event::MSGS_CHANGED,
chat_id as uintptr_t,
msg.id as uintptr_t,
);
context.call_cb(Event::MsgsChanged {
chat_id,
msg_id: msg.id,
});
}
context.call_cb(Event::MSGS_CHANGED, chat_id as uintptr_t, 0 as uintptr_t);
context.call_cb(Event::MsgsChanged { chat_id, msg_id: 0 });
success = true;
}
}
@@ -1474,11 +1489,11 @@ pub unsafe fn remove_contact_from_chat(
if let Ok(chat) = Chat::load_from_db(context, chat_id) {
if real_group_exists(context, chat_id) {
if !(is_contact_in_chat(context, chat_id, 1 as u32) == 1) {
log_event!(
emit_event!(
context,
Event::ERROR_SELF_NOT_IN_GROUP,
0,
"Cannot remove contact from chat; self not in group.",
Event::ErrorSelfNotInGroup(
"Cannot remove contact from chat; self not in group.".into()
)
);
} else {
/* we should respect this - whatever we send to the group, it gets discarded anyway! */
@@ -1504,11 +1519,10 @@ pub unsafe fn remove_contact_from_chat(
msg.param.set_int(Param::Cmd, 5);
msg.param.set(Param::Arg, contact.get_addr());
msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default();
context.call_cb(
Event::MSGS_CHANGED,
chat_id as uintptr_t,
msg.id as uintptr_t,
);
context.call_cb(Event::MsgsChanged {
chat_id,
msg_id: msg.id,
});
}
}
if sql::execute(
@@ -1519,7 +1533,7 @@ pub unsafe fn remove_contact_from_chat(
)
.is_ok()
{
context.call_cb(Event::CHAT_MODIFIED, chat_id as uintptr_t, 0 as uintptr_t);
context.call_cb(Event::ChatModified(chat_id));
success = true;
}
}
@@ -1571,11 +1585,9 @@ pub unsafe fn set_chat_name(
if &chat.name == new_name.as_ref() {
success = true;
} else if !(is_contact_in_chat(context, chat_id, 1) == 1) {
log_event!(
emit_event!(
context,
Event::ERROR_SELF_NOT_IN_GROUP,
0,
"Cannot set chat name; self not in group",
Event::ErrorSelfNotInGroup("Cannot set chat name; self not in group".into())
);
} else {
/* we should respect this - whatever we send to the group, it gets discarded anyway! */
@@ -1604,17 +1616,12 @@ pub unsafe fn set_chat_name(
msg.param.set(Param::Arg, &chat.name);
}
msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default();
context.call_cb(
Event::MSGS_CHANGED,
chat_id as uintptr_t,
msg.id as uintptr_t,
);
context.call_cb(Event::MsgsChanged {
chat_id,
msg_id: msg.id,
});
}
context.call_cb(
Event::CHAT_MODIFIED,
chat_id as uintptr_t,
0i32 as uintptr_t,
);
context.call_cb(Event::ChatModified(chat_id));
success = true;
}
}
@@ -1640,11 +1647,11 @@ pub fn set_chat_profile_image(
if real_group_exists(context, chat_id) {
/* we should respect this - whatever we send to the group, it gets discarded anyway! */
if !(is_contact_in_chat(context, chat_id, DC_CONTACT_ID_SELF) == 1i32) {
log_event!(
emit_event!(
context,
Event::ERROR_SELF_NOT_IN_GROUP,
0,
"Cannot set chat profile image; self not in group.",
Event::ErrorSelfNotInGroup(
"Cannot set chat profile image; self not in group.".into()
)
);
bail!("Failed to set profile image");
}
@@ -1677,9 +1684,15 @@ pub fn set_chat_profile_image(
DC_CONTACT_ID_SELF,
));
msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default();
emit_event!(context, Event::MSGS_CHANGED, chat_id, msg.id);
emit_event!(
context,
Event::MsgsChanged {
chat_id,
msg_id: msg.id
}
);
}
emit_event!(context, Event::CHAT_MODIFIED, chat_id, 0);
emit_event!(context, Event::ChatModified(chat_id));
return Ok(());
}
}
@@ -1773,11 +1786,10 @@ pub unsafe fn forward_msgs(
}
for i in (0..created_db_entries.len()).step_by(2) {
context.call_cb(
Event::MSGS_CHANGED,
created_db_entries[i] as uintptr_t,
created_db_entries[i + 1] as uintptr_t,
);
context.call_cb(Event::MsgsChanged {
chat_id: created_db_entries[i],
msg_id: created_db_entries[i + 1],
});
}
}
@@ -1858,11 +1870,7 @@ pub fn add_device_msg(context: &Context, chat_id: u32, text: impl AsRef<str>) {
as_str(rfc724_mid),
);
unsafe { free(rfc724_mid as *mut libc::c_void) };
context.call_cb(
Event::MSGS_CHANGED,
chat_id as uintptr_t,
msg_id as uintptr_t,
);
context.call_cb(Event::MsgsChanged { chat_id, msg_id });
}
#[cfg(test)]

View File

@@ -1,4 +1,3 @@
use libc::uintptr_t;
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
use crate::constants::*;
@@ -19,14 +18,10 @@ use auto_mozilla::moz_autoconfigure;
macro_rules! progress {
($context:tt, $progress:expr) => {
assert!(
$progress >= 0 && $progress <= 1000,
$progress > 0 && $progress <= 1000,
"value in range 0..1000 expected with: 0=error, 1..999=progress, 1000=success"
);
$context.call_cb(
Event::CONFIGURE_PROGRESS,
$progress as uintptr_t,
0 as uintptr_t,
);
$context.call_cb($crate::events::Event::ConfigureProgress($progress));
};
}
@@ -567,7 +562,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
dc_free_ongoing(context);
}
progress!(context, (if success { 1000 } else { 0 }));
progress!(context, if success { 1000 } else { 0 });
}
/*******************************************************************************

View File

@@ -1,9 +1,8 @@
//! Constants
#![allow(non_camel_case_types, dead_code)]
use lazy_static::lazy_static;
use deltachat_derive::*;
use lazy_static::lazy_static;
lazy_static! {
pub static ref DC_VERSION_STR: String = env!("CARGO_PKG_VERSION").to_string();
@@ -247,242 +246,6 @@ mod tests {
// If you do not want to handle an event, it is always safe to return 0,
// so there is no need to add a "case" for every event.
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
#[repr(u32)]
pub enum Event {
/// The library-user may write an informational string to the log.
/// Passed to the callback given to dc_context_new().
/// This event should not be reported to the end-user using a popup or something like that.
/// @param data1 0
/// @param data2 (const char*) Info string in english language.
/// Must not be free()'d or modified and is valid only until the callback returns.
/// @return 0
INFO = 100,
/// Emitted when SMTP connection is established and login was successful.
///
/// @param data1 0
/// @param data2 (const char*) Info string in english language.
/// Must not be free()'d or modified and is valid only until the callback returns.
/// @return 0
SMTP_CONNECTED = 101,
/// Emitted when IMAP connection is established and login was successful.
///
/// @param data1 0
/// @param data2 (const char*) Info string in english language.
/// Must not be free()'d or modified and is valid only until the callback returns.
/// @return 0
IMAP_CONNECTED = 102,
/// Emitted when a message was successfully sent to the SMTP server.
///
/// @param data1 0
/// @param data2 (const char*) Info string in english language.
/// Must not be free()'d or modified and is valid only until the callback returns.
/// @return 0
SMTP_MESSAGE_SENT = 103,
/// The library-user should write a warning string to the log.
/// Passed to the callback given to dc_context_new().
///
/// This event should not be reported to the end-user using a popup or something like that.
///
/// @param data1 0
/// @param data2 (const char*) Warning string in english language.
/// Must not be free()'d or modified and is valid only until the callback returns.
/// @return 0
WARNING = 300,
/// The library-user should report an error to the end-user.
/// Passed to the callback given to dc_context_new().
///
/// As most things are asynchronous, things may go wrong at any time and the user
/// should not be disturbed by a dialog or so. Instead, use a bubble or so.
///
/// However, for ongoing processes (eg. configure())
/// or for functions that are expected to fail (eg. dc_continue_key_transfer())
/// it might be better to delay showing these events until the function has really
/// failed (returned false). It should be sufficient to report only the _last_ error
/// in a messasge box then.
///
/// @param data1 0
/// @param data2 (const char*) Error string, always set, never NULL. Frequent error strings are
/// localized using #DC_EVENT_GET_STRING, however, most error strings will be in english language.
/// Must not be free()'d or modified and is valid only until the callback returns.
/// @return 0
ERROR = 400,
/// An action cannot be performed because there is no network available.
///
/// The library will typically try over after a some time
/// and when dc_maybe_network() is called.
///
/// Network errors should be reported to users in a non-disturbing way,
/// however, as network errors may come in a sequence,
/// it is not useful to raise each an every error to the user.
/// For this purpose, data1 is set to 1 if the error is probably worth reporting.
///
/// Moreover, if the UI detects that the device is offline,
/// it is probably more useful to report this to the user
/// instead of the string from data2.
///
/// @param data1 (int) 1=first/new network error, should be reported the user;
/// 0=subsequent network error, should be logged only
/// @param data2 (const char*) Error string, always set, never NULL.
/// Must not be free()'d or modified and is valid only until the callback returns.
/// @return 0
ERROR_NETWORK = 401,
/// An action cannot be performed because the user is not in the group.
/// Reported eg. after a call to
/// dc_set_chat_name(), dc_set_chat_profile_image(),
/// dc_add_contact_to_chat(), dc_remove_contact_from_chat(),
/// dc_send_text_msg() or another sending function.
///
/// @param data1 0
/// @param data2 (const char*) Info string in english language.
/// Must not be free()'d or modified
/// and is valid only until the callback returns.
/// @return 0
ERROR_SELF_NOT_IN_GROUP = 410,
/// Messages or chats changed. One or more messages or chats changed for various
/// reasons in the database:
/// - Messages sent, received or removed
/// - Chats created, deleted or archived
/// - A draft has been set
///
/// @param data1 (int) chat_id for single added messages
/// @param data2 (int) msg_id for single added messages
/// @return 0
MSGS_CHANGED = 2000,
/// There is a fresh message. Typically, the user will show an notification
/// when receiving this message.
///
/// There is no extra #DC_EVENT_MSGS_CHANGED event send together with this event.
///
/// @param data1 (int) chat_id
/// @param data2 (int) msg_id
/// @return 0
INCOMING_MSG = 2005,
/// A single message is sent successfully. State changed from DC_STATE_OUT_PENDING to
/// DC_STATE_OUT_DELIVERED, see dc_msg_get_state().
///
/// @param data1 (int) chat_id
/// @param data2 (int) msg_id
/// @return 0
MSG_DELIVERED = 2010,
/// A single message could not be sent. State changed from DC_STATE_OUT_PENDING or DC_STATE_OUT_DELIVERED to
/// DC_STATE_OUT_FAILED, see dc_msg_get_state().
///
/// @param data1 (int) chat_id
/// @param data2 (int) msg_id
/// @return 0
MSG_FAILED = 2012,
/// A single message is read by the receiver. State changed from DC_STATE_OUT_DELIVERED to
/// DC_STATE_OUT_MDN_RCVD, see dc_msg_get_state().
///
/// @param data1 (int) chat_id
/// @param data2 (int) msg_id
/// @return 0
MSG_READ = 2015,
/// 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()
/// and dc_remove_contact_from_chat().
///
/// @param data1 (int) chat_id
/// @param data2 0
/// @return 0
CHAT_MODIFIED = 2020,
/// Contact(s) created, renamed, blocked or deleted.
///
/// @param data1 (int) If not 0, this is the contact_id of an added contact that should be selected.
/// @param data2 0
/// @return 0
CONTACTS_CHANGED = 2030,
/// Location of one or more contact has changed.
///
/// @param data1 (int) contact_id of the contact for which the location has changed.
/// If the locations of several contacts have been changed,
/// eg. after calling dc_delete_all_locations(), this parameter is set to 0.
/// @param data2 0
/// @return 0
LOCATION_CHANGED = 2035,
/// Inform about the configuration progress started by configure().
///
/// @param data1 (int) 0=error, 1-999=progress in permille, 1000=success and done
/// @param data2 0
/// @return 0
CONFIGURE_PROGRESS = 2041,
/// Inform about the import/export progress started by dc_imex().
///
/// @param data1 (int) 0=error, 1-999=progress in permille, 1000=success and done
/// @param data2 0
/// @return 0
IMEX_PROGRESS = 2051,
/// A file has been exported. A file has been written by dc_imex().
/// This event may be sent multiple times by a single call to dc_imex().
///
/// A typical purpose for a handler of this event may be to make the file public to some system
/// services.
///
/// @param data1 (const char*) Path and file name.
/// Must not be free()'d or modified and is valid only until the callback returns.
/// @param data2 0
/// @return 0
IMEX_FILE_WRITTEN = 2052,
/// Progress information of a secure-join handshake from the view of the inviter
/// (Alice, the person who shows the QR code).
///
/// These events are typically sent after a joiner has scanned the QR code
/// generated by dc_get_securejoin_qr().
///
/// @param data1 (int) ID of the contact that wants to join.
/// @param data2 (int) Progress as:
/// 300=vg-/vc-request received, typically shown as "bob@addr joins".
/// 600=vg-/vc-request-with-auth received, vg-member-added/vc-contact-confirm sent, typically shown as "bob@addr verified".
/// 800=vg-member-added-received received, shown as "bob@addr securely joined GROUP", only sent for the verified-group-protocol.
/// 1000=Protocol finished for this contact.
/// @return 0
SECUREJOIN_INVITER_PROGRESS = 2060,
/// Progress information of a secure-join handshake from the view of the joiner
/// (Bob, the person who scans the QR code).
/// The events are typically sent while dc_join_securejoin(), which
/// may take some time, is executed.
/// @param data1 (int) ID of the inviting contact.
/// @param data2 (int) Progress as:
/// 400=vg-/vc-request-with-auth sent, typically shown as "alice@addr verified, introducing myself."
/// (Bob has verified alice and waits until Alice does the same for him)
/// @return 0
SECUREJOIN_JOINER_PROGRESS = 2061,
// the following events are functions that should be provided by the frontends
/// Requeste a localized string from the frontend.
/// @param data1 (int) ID of the string to request, one of the DC_STR_/// constants.
/// @param data2 (int) The count. If the requested string contains a placeholder for a numeric value,
/// the ui may use this value to return different strings on different plural forms.
/// @return (const char*) Null-terminated UTF-8 string.
/// The string will be free()'d by the core,
/// so it must be allocated using malloc() or a compatible function.
/// Return 0 if the ui cannot provide the requested string
/// the core will use a default string in english language then.
GET_STRING = 2091,
}
const DC_EVENT_FILE_COPIED: usize = 2055; // deprecated;
const DC_EVENT_IS_OFFLINE: usize = 2081; // deprecated;
const DC_ERROR_SEE_STRING: usize = 0; // deprecated;

View File

@@ -2,7 +2,6 @@ use std::path::PathBuf;
use deltachat_derive::*;
use itertools::Itertools;
use libc::uintptr_t;
use rusqlite;
use crate::aheader::EncryptPreference;
@@ -12,6 +11,7 @@ use crate::context::Context;
use crate::dc_tools::*;
use crate::e2ee;
use crate::error::Result;
use crate::events::Event;
use crate::key::*;
use crate::login_param::LoginParam;
use crate::message::MessageState;
@@ -214,15 +214,13 @@ impl Contact {
let (contact_id, sth_modified) =
Contact::add_or_lookup(context, name, addr, Origin::ManuallyCreated)?;
let blocked = Contact::is_blocked_load(context, contact_id);
context.call_cb(
Event::CONTACTS_CHANGED,
(if sth_modified == Modifier::Created {
contact_id
context.call_cb(Event::ContactsChanged(
if sth_modified == Modifier::Created {
Some(contact_id)
} else {
0
}) as uintptr_t,
0 as uintptr_t,
);
None
},
));
if blocked {
Contact::unblock(context, contact_id);
}
@@ -243,7 +241,10 @@ impl Contact {
)
.is_ok()
{
context.call_cb(Event::MSGS_CHANGED, 0, 0);
context.call_cb(Event::MsgsChanged {
chat_id: 0,
msg_id: 0,
});
}
}
@@ -436,7 +437,7 @@ impl Contact {
}
}
if modify_cnt > 0 {
context.call_cb(Event::CONTACTS_CHANGED, 0 as uintptr_t, 0 as uintptr_t);
context.call_cb(Event::ContactsChanged(None));
}
Ok(modify_cnt)
@@ -673,7 +674,7 @@ impl Contact {
params![contact_id as i32],
) {
Ok(_) => {
context.call_cb(Event::CONTACTS_CHANGED, 0, 0);
context.call_cb(Event::ContactsChanged(None));
return Ok(());
}
Err(err) => {
@@ -938,11 +939,7 @@ fn set_block_contact(context: &Context, contact_id: u32, new_blocking: bool) {
params![new_blocking, 100, contact_id as i32],
).is_ok() {
Contact::mark_noticed(context, contact_id);
context.call_cb(
Event::CONTACTS_CHANGED,
0,
0,
);
context.call_cb(Event::ContactsChanged(None));
}
}
}

View File

@@ -9,6 +9,7 @@ use crate::chat::*;
use crate::constants::*;
use crate::contact::*;
use crate::error::*;
use crate::events::Event;
use crate::imap::*;
use crate::job::*;
use crate::job_thread::JobThread;
@@ -33,7 +34,7 @@ use crate::sql::Sql;
///
/// This callback must return 0 unless stated otherwise in the event
/// description at [Event].
pub type ContextCallback = dyn Fn(&Context, Event, uintptr_t, uintptr_t) -> uintptr_t + Send + Sync;
pub type ContextCallback = dyn Fn(&Context, Event) -> uintptr_t + Send + Sync;
#[derive(DebugStub)]
pub struct Context {
@@ -133,8 +134,8 @@ impl Context {
self.blobdir.as_path()
}
pub fn call_cb(&self, event: Event, data1: uintptr_t, data2: uintptr_t) -> uintptr_t {
(*self.cb)(self, event, data1, data2)
pub fn call_cb(&self, event: Event) -> uintptr_t {
(*self.cb)(self, event)
}
pub fn get_info(&self) -> HashMap<&'static str, String> {
@@ -433,7 +434,7 @@ mod tests {
let tmp = tempfile::tempdir().unwrap();
let dbfile = tmp.path().join("db.sqlite");
std::fs::write(&dbfile, b"123").unwrap();
let res = Context::new(Box::new(|_, _, _, _| 0), "FakeOs".into(), dbfile);
let res = Context::new(Box::new(|_, _| 0), "FakeOs".into(), dbfile);
assert!(res.is_err());
}
@@ -441,7 +442,7 @@ mod tests {
fn test_blobdir_exists() {
let tmp = tempfile::tempdir().unwrap();
let dbfile = tmp.path().join("db.sqlite");
Context::new(Box::new(|_, _, _, _| 0), "FakeOS".into(), dbfile).unwrap();
Context::new(Box::new(|_, _| 0), "FakeOS".into(), dbfile).unwrap();
let blobdir = tmp.path().join("db.sqlite-blobs");
assert!(blobdir.is_dir());
}
@@ -452,7 +453,7 @@ mod tests {
let dbfile = tmp.path().join("db.sqlite");
let blobdir = tmp.path().join("db.sqlite-blobs");
std::fs::write(&blobdir, b"123").unwrap();
let res = Context::new(Box::new(|_, _, _, _| 0), "FakeOS".into(), dbfile);
let res = Context::new(Box::new(|_, _| 0), "FakeOS".into(), dbfile);
assert!(res.is_err());
}
@@ -462,7 +463,7 @@ mod tests {
let subdir = tmp.path().join("subdir");
let dbfile = subdir.join("db.sqlite");
let dbfile2 = dbfile.clone();
Context::new(Box::new(|_, _, _, _| 0), "FakeOS".into(), dbfile).unwrap();
Context::new(Box::new(|_, _| 0), "FakeOS".into(), dbfile).unwrap();
assert!(subdir.is_dir());
assert!(dbfile2.is_file());
}
@@ -472,7 +473,7 @@ mod tests {
let tmp = tempfile::tempdir().unwrap();
let dbfile = tmp.path().join("db.sqlite");
let blobdir = tmp.path().join("blobs");
let res = Context::with_blobdir(Box::new(|_, _, _, _| 0), "FakeOS".into(), dbfile, blobdir);
let res = Context::with_blobdir(Box::new(|_, _| 0), "FakeOS".into(), dbfile, blobdir);
assert!(res.is_err());
}

View File

@@ -2,7 +2,6 @@ use std::ffi::CString;
use std::path::Path;
use std::ptr;
use libc::uintptr_t;
use mmime::mailmime_content::*;
use mmime::mmapstring::*;
use mmime::other::*;
@@ -16,6 +15,7 @@ use crate::context::Context;
use crate::dc_tools::*;
use crate::e2ee;
use crate::error::*;
use crate::events::Event;
use crate::job::*;
use crate::key::*;
use crate::message::*;
@@ -502,7 +502,8 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) {
error!(context, "No Import/export dir/file given.",);
} else {
info!(context, "Import/export process started.",);
context.call_cb(Event::IMEX_PROGRESS, 10 as uintptr_t, 0 as uintptr_t);
context.call_cb(Event::ImexProgress(10));
if !context.sql.is_open() {
error!(context, "Import/export: Database not opened.",);
} else {
@@ -551,11 +552,7 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) {
}
dc_free_ongoing(context);
}
context.call_cb(
Event::IMEX_PROGRESS,
(if 0 != success { 1000 } else { 0 }) as uintptr_t,
0 as uintptr_t,
);
context.call_cb(Event::ImexProgress(if 0 != success { 1000 } else { 0 }));
}
/*******************************************************************************
@@ -637,7 +634,7 @@ unsafe fn import_backup(context: &Context, backup_to_import: *const libc::c_char
if permille > 990 {
permille = 990
}
context.call_cb(Event::IMEX_PROGRESS, permille as uintptr_t, 0);
context.call_cb(Event::ImexProgress(permille));
if file_blob.is_empty() {
continue;
}
@@ -773,11 +770,7 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> bool {
if permille > 990 {
permille = 990;
}
context.call_cb(
Event::IMEX_PROGRESS,
permille as uintptr_t,
0 as uintptr_t,
);
context.call_cb(Event::ImexProgress(permille));
let name_f = entry.file_name();
let name = name_f.to_string_lossy();
@@ -828,11 +821,9 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> bool {
.set_config_int(context, "backup_time", now as i32)
.is_ok()
{
context.call_cb(
Event::IMEX_FILE_WRITTEN,
dest_pathNfilename as uintptr_t,
0,
);
context.call_cb(Event::ImexFileWritten(
as_path(dest_pathNfilename).to_path_buf(),
));
success = true;
}
}
@@ -1063,11 +1054,7 @@ unsafe fn export_key_to_asc_file(
if !key.write_asc_to_file(as_path(file_name), context) {
error!(context, "Cannot write key to {}", as_str(file_name),);
} else {
context.call_cb(
Event::IMEX_FILE_WRITTEN,
file_name as uintptr_t,
0i32 as uintptr_t,
);
context.call_cb(Event::ImexFileWritten(as_path(file_name).to_path_buf()));
success = true;
}
free(file_name as *mut libc::c_void);
@@ -1079,8 +1066,6 @@ unsafe fn export_key_to_asc_file(
mod tests {
use super::*;
use num_traits::ToPrimitive;
use crate::test_utils::*;
#[test]
@@ -1103,11 +1088,13 @@ mod tests {
assert!(msg.contains("-----END PGP MESSAGE-----\n"));
}
fn ac_setup_msg_cb(ctx: &Context, evt: Event, d1: uintptr_t, d2: uintptr_t) -> uintptr_t {
if evt == Event::GET_STRING && d1 == StockMessage::AcSetupMsgBody.to_usize().unwrap() {
unsafe { "hello\r\nthere".strdup() as usize }
} else {
logging_cb(ctx, evt, d1, d2)
fn ac_setup_msg_cb(ctx: &Context, evt: Event) -> libc::uintptr_t {
match evt {
Event::GetString {
id: StockMessage::AcSetupMsgBody,
..
} => unsafe { "hello\r\nthere".strdup() as usize },
_ => logging_cb(ctx, evt),
}
}

View File

@@ -2,7 +2,6 @@ use std::ffi::CString;
use std::ptr;
use itertools::join;
use libc::uintptr_t;
use mmime::clist::*;
use mmime::mailimf::*;
use mmime::mailimf_types::*;
@@ -21,6 +20,7 @@ use crate::dc_mimeparser::*;
use crate::dc_strencode::*;
use crate::dc_tools::*;
use crate::error::Result;
use crate::events::Event;
use crate::job::*;
use crate::location;
use crate::message::*;
@@ -31,6 +31,12 @@ use crate::sql;
use crate::stock::StockMessage;
use crate::x::*;
#[derive(Debug, PartialEq, Eq)]
enum CreateEvent {
MsgsChanged,
IncomingMsg,
}
/// Receive a message and add it to the database.
pub unsafe fn dc_receive_imf(
context: &Context,
@@ -82,7 +88,7 @@ pub unsafe fn dc_receive_imf(
let rfc724_mid = std::ptr::null_mut();
let mut sent_timestamp = 0;
let mut created_db_entries = Vec::new();
let mut create_event_to_send = Some(Event::MSGS_CHANGED);
let mut create_event_to_send = Some(CreateEvent::MsgsChanged);
let mut rr_event_to_send = Vec::new();
let mut to_ids = Vec::with_capacity(16);
@@ -90,18 +96,31 @@ pub unsafe fn dc_receive_imf(
// helper method to handle early exit and memory cleanup
let cleanup = |context: &Context,
rfc724_mid: *mut libc::c_char,
create_event_to_send: &Option<Event>,
create_event_to_send: &Option<CreateEvent>,
created_db_entries: &Vec<(usize, usize)>,
rr_event_to_send: &Vec<(u32, u32)>| {
free(rfc724_mid.cast());
if let Some(create_event_to_send) = create_event_to_send {
for (msg_id, insert_id) in created_db_entries {
context.call_cb(*create_event_to_send, *msg_id, *insert_id);
let event = match create_event_to_send {
CreateEvent::MsgsChanged => Event::MsgsChanged {
msg_id: *msg_id as u32,
chat_id: *insert_id as u32,
},
CreateEvent::IncomingMsg => Event::IncomingMsg {
msg_id: *msg_id as u32,
chat_id: *insert_id as u32,
},
};
context.call_cb(event);
}
}
for (chat_id, msg_id) in rr_event_to_send {
context.call_cb(Event::MSG_READ, *chat_id as uintptr_t, *msg_id as uintptr_t);
context.call_cb(Event::MsgRead {
chat_id: *chat_id,
msg_id: *msg_id,
});
}
};
@@ -279,7 +298,7 @@ unsafe fn add_parts(
to_self: i32,
insert_msg_id: &mut u32,
created_db_entries: &mut Vec<(usize, usize)>,
create_event_to_send: &mut Option<Event>,
create_event_to_send: &mut Option<CreateEvent>,
) -> Result<()> {
let mut state: MessageState;
let mut msgrmsg: libc::c_int;
@@ -730,9 +749,9 @@ unsafe fn add_parts(
if 0 != from_id_blocked {
*create_event_to_send = None;
} else if Blocked::Not != chat_id_blocked {
*create_event_to_send = Some(Event::MSGS_CHANGED);
*create_event_to_send = Some(CreateEvent::MsgsChanged);
} else {
*create_event_to_send = Some(Event::INCOMING_MSG);
*create_event_to_send = Some(CreateEvent::IncomingMsg);
}
}
@@ -967,11 +986,7 @@ fn save_locations(
}
}
if send_event {
context.call_cb(
Event::LOCATION_CHANGED,
from_id as uintptr_t,
0 as uintptr_t,
);
context.call_cb(Event::LocationChanged(Some(from_id)));
}
}
@@ -1321,7 +1336,7 @@ unsafe fn create_or_lookup_group(
)
.is_ok()
{
context.call_cb(Event::CHAT_MODIFIED, chat_id as uintptr_t, 0);
context.call_cb(Event::ChatModified(chat_id));
}
}
if !X_MrGrpImageChanged.is_empty() {
@@ -1403,7 +1418,7 @@ unsafe fn create_or_lookup_group(
}
if 0 != send_EVENT_CHAT_MODIFIED {
context.call_cb(Event::CHAT_MODIFIED, chat_id as uintptr_t, 0 as uintptr_t);
context.call_cb(Event::ChatModified(chat_id));
}
// check the number of receivers -
@@ -1578,7 +1593,7 @@ unsafe fn create_or_lookup_adhoc_group(
chat::add_to_chat_contacts_table(context, chat_id, member_id);
}
context.call_cb(Event::CHAT_MODIFIED, chat_id as uintptr_t, 0 as uintptr_t);
context.call_cb(Event::ChatModified(chat_id));
cleanup(
grpname,

232
src/events.rs Normal file
View File

@@ -0,0 +1,232 @@
use std::path::PathBuf;
use strum::EnumProperty;
use crate::stock::StockMessage;
impl Event {
/// Returns the corresponding Event id.
pub fn as_id(&self) -> i32 {
self.get_str("id")
.expect("missing id")
.parse()
.expect("invalid id")
}
}
#[derive(Debug, Clone, PartialEq, Eq, EnumProperty)]
pub enum Event {
/// The library-user may write an informational string to the log.
/// Passed to the callback given to dc_context_new().
/// This event should not be reported to the end-user using a popup or something like that.
///
/// @return 0
#[strum(props(id = "100"))]
Info(String),
/// Emitted when SMTP connection is established and login was successful.
///
/// @return 0
#[strum(props(id = "101"))]
SmtpConnected(String),
/// Emitted when IMAP connection is established and login was successful.
///
/// @return 0
#[strum(props(id = "102"))]
ImapConnected(String),
/// Emitted when a message was successfully sent to the SMTP server.
///
/// @return 0
#[strum(props(id = "103"))]
SmtpMessageSent(String),
/// The library-user should write a warning string to the log.
/// Passed to the callback given to dc_context_new().
///
/// This event should not be reported to the end-user using a popup or something like that.
///
/// @return 0
#[strum(props(id = "300"))]
Warning(String),
/// The library-user should report an error to the end-user.
/// Passed to the callback given to dc_context_new().
///
/// As most things are asynchronous, things may go wrong at any time and the user
/// should not be disturbed by a dialog or so. Instead, use a bubble or so.
///
/// However, for ongoing processes (eg. configure())
/// or for functions that are expected to fail (eg. dc_continue_key_transfer())
/// it might be better to delay showing these events until the function has really
/// failed (returned false). It should be sufficient to report only the _last_ error
/// in a messasge box then.
///
/// @return
#[strum(props(id = "400"))]
Error(String),
/// An action cannot be performed because there is no network available.
///
/// The library will typically try over after a some time
/// and when dc_maybe_network() is called.
///
/// Network errors should be reported to users in a non-disturbing way,
/// however, as network errors may come in a sequence,
/// it is not useful to raise each an every error to the user.
/// For this purpose, data1 is set to 1 if the error is probably worth reporting.
///
/// Moreover, if the UI detects that the device is offline,
/// it is probably more useful to report this to the user
/// instead of the string from data2.
///
/// @param data1 (usize) 1=first/new network error, should be reported the user;
/// 0=subsequent network error, should be logged only
/// @param data2 (String) string
/// @return 0
#[strum(props(id = "401"))]
ErrorNetwork(usize, String),
/// An action cannot be performed because the user is not in the group.
/// Reported eg. after a call to
/// dc_set_chat_name(), dc_set_chat_profile_image(),
/// dc_add_contact_to_chat(), dc_remove_contact_from_chat(),
/// dc_send_text_msg() or another sending function.
///
/// @return 0
#[strum(props(id = "410"))]
ErrorSelfNotInGroup(String),
/// Messages or chats changed. One or more messages or chats changed for various
/// reasons in the database:
/// - Messages sent, received or removed
/// - Chats created, deleted or archived
/// - A draft has been set
///
/// @return 0
#[strum(props(id = "2000"))]
MsgsChanged { chat_id: u32, msg_id: u32 },
/// There is a fresh message. Typically, the user will show an notification
/// when receiving this message.
///
/// There is no extra #DC_EVENT_MSGS_CHANGED event send together with this event.
///
/// @return 0
#[strum(props(id = "2005"))]
IncomingMsg { chat_id: u32, msg_id: u32 },
/// A single message is sent successfully. State changed from DC_STATE_OUT_PENDING to
/// DC_STATE_OUT_DELIVERED, see dc_msg_get_state().
///
/// @return 0
#[strum(props(id = "2010"))]
MsgDelivered { chat_id: u32, msg_id: u32 },
/// A single message could not be sent. State changed from DC_STATE_OUT_PENDING or DC_STATE_OUT_DELIVERED to
/// DC_STATE_OUT_FAILED, see dc_msg_get_state().
///
/// @return 0
#[strum(props(id = "2012"))]
MsgFailed { chat_id: u32, msg_id: u32 },
/// A single message is read by the receiver. State changed from DC_STATE_OUT_DELIVERED to
/// DC_STATE_OUT_MDN_RCVD, see dc_msg_get_state().
///
/// @return 0
#[strum(props(id = "2015"))]
MsgRead { chat_id: u32, msg_id: 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()
/// and dc_remove_contact_from_chat().
///
/// @return 0
#[strum(props(id = "2020"))]
ChatModified(u32),
/// Contact(s) created, renamed, blocked or deleted.
///
/// @param data1 (int) If set, this is the contact_id of an added contact that should be selected.
/// @return 0
#[strum(props(id = "2030"))]
ContactsChanged(Option<u32>),
/// Location of one or more contact has changed.
///
/// @param data1 (u32) contact_id of the contact for which the location has changed.
/// If the locations of several contacts have been changed,
/// eg. after calling dc_delete_all_locations(), this parameter is set to `None`.
/// @return 0
#[strum(props(id = "2035"))]
LocationChanged(Option<u32>),
/// Inform about the configuration progress started by configure().
///
/// @param data1 (usize) 0=error, 1-999=progress in permille, 1000=success and done
/// @return 0
#[strum(props(id = "2041"))]
ConfigureProgress(usize),
/// Inform about the import/export progress started by dc_imex().
///
/// @param data1 (usize) 0=error, 1-999=progress in permille, 1000=success and done
/// @param data2 0
/// @return 0
#[strum(props(id = "2051"))]
ImexProgress(usize),
/// A file has been exported. A file has been written by dc_imex().
/// This event may be sent multiple times by a single call to dc_imex().
///
/// A typical purpose for a handler of this event may be to make the file public to some system
/// services.
///
/// @param data2 0
/// @return 0
#[strum(props(id = "2052"))]
ImexFileWritten(PathBuf),
/// Progress information of a secure-join handshake from the view of the inviter
/// (Alice, the person who shows the QR code).
///
/// These events are typically sent after a joiner has scanned the QR code
/// generated by dc_get_securejoin_qr().
///
/// @param data1 (int) ID of the contact that wants to join.
/// @param data2 (int) Progress as:
/// 300=vg-/vc-request received, typically shown as "bob@addr joins".
/// 600=vg-/vc-request-with-auth received, vg-member-added/vc-contact-confirm sent, typically shown as "bob@addr verified".
/// 800=vg-member-added-received received, shown as "bob@addr securely joined GROUP", only sent for the verified-group-protocol.
/// 1000=Protocol finished for this contact.
/// @return 0
#[strum(props(id = "2060"))]
SecurejoinInviterProgress { contact_id: u32, progress: usize },
/// Progress information of a secure-join handshake from the view of the joiner
/// (Bob, the person who scans the QR code).
/// The events are typically sent while dc_join_securejoin(), which
/// may take some time, is executed.
/// @param data1 (int) ID of the inviting contact.
/// @param data2 (int) Progress as:
/// 400=vg-/vc-request-with-auth sent, typically shown as "alice@addr verified, introducing myself."
/// (Bob has verified alice and waits until Alice does the same for him)
/// @return 0
#[strum(props(id = "2061"))]
SecurejoinJoinerProgress { contact_id: u32, progress: usize },
// the following events are functions that should be provided by the frontends
/// Requeste a localized string from the frontend.
/// @param data1 (int) ID of the string to request, one of the DC_STR_/// constants.
/// @param data2 (int) The count. If the requested string contains a placeholder for a numeric value,
/// the ui may use this value to return different strings on different plural forms.
/// @return (const char*) Null-terminated UTF-8 string.
/// The string will be free()'d by the core,
/// so it must be allocated using malloc() or a compatible function.
/// Return 0 if the ui cannot provide the requested string
/// the core will use a default string in english language then.
#[strum(props(id = "2091"))]
GetString { id: StockMessage, count: usize },
}

View File

@@ -12,6 +12,7 @@ use crate::context::Context;
use crate::dc_receive_imf::dc_receive_imf;
use crate::dc_tools::CStringExt;
use crate::dc_tools::*;
use crate::events::Event;
use crate::job::{job_add, Action};
use crate::login_param::LoginParam;
use crate::message::{dc_rfc724_mid_exists, dc_update_msg_move_state, dc_update_server_uid};
@@ -437,14 +438,15 @@ impl Imap {
let imap_server: &str = config.imap_server.as_ref();
let imap_port = config.imap_port;
log_event!(
emit_event!(
context,
Event::ERROR_NETWORK,
0,
"Could not connect to IMAP-server {}:{}. ({})",
imap_server,
imap_port,
err
Event::ErrorNetwork(
0,
format!(
"Could not connect to IMAP-server {}:{}. ({})",
imap_server, imap_port, err
)
)
);
return false;
@@ -460,7 +462,10 @@ impl Imap {
true
}
Err((err, _)) => {
log_event!(context, Event::ERROR_NETWORK, 0, "Cannot login ({})", err);
emit_event!(
context,
Event::ErrorNetwork(0, format!("Cannot login ({})", err))
);
self.unsetup_handle(context);
false
@@ -553,13 +558,12 @@ impl Imap {
let caps_list = caps
.iter()
.fold(String::new(), |s, c| s + &format!(" {:?}", c));
log_event!(
emit_event!(
context,
Event::IMAP_CONNECTED,
0,
"IMAP-LOGIN as {}, capabilities: {}",
lp.mail_user,
caps_list,
Event::ImapConnected(format!(
"IMAP-LOGIN as {}, capabilities: {}",
lp.mail_user, caps_list,
))
);
(false, can_idle, has_xlist)
}

View File

@@ -3,7 +3,6 @@ use std::ptr;
use std::time::Duration;
use deltachat_derive::{FromSql, ToSql};
use libc::uintptr_t;
use mmime::clist::*;
use rand::{thread_rng, Rng};
@@ -14,6 +13,7 @@ use crate::context::Context;
use crate::dc_imex::*;
use crate::dc_mimefactory::*;
use crate::dc_tools::*;
use crate::events::Event;
use crate::imap::*;
use crate::location;
use crate::login_param::LoginParam;
@@ -189,11 +189,10 @@ impl Job {
params![self.foreign_id as i32],
)
.unwrap_or_default();
context.call_cb(
Event::MSG_DELIVERED,
chat_id as uintptr_t,
self.foreign_id as uintptr_t,
);
context.call_cb(Event::MsgDelivered {
chat_id: chat_id as u32,
msg_id: self.foreign_id,
});
}
}
} else {

View File

@@ -26,6 +26,9 @@ mod log;
#[macro_use]
pub mod error;
pub(crate) mod events;
pub use events::*;
mod aheader;
pub mod chat;
pub mod chatlist;

View File

@@ -1,14 +1,13 @@
use bitflags::bitflags;
use libc::uintptr_t;
use quick_xml;
use quick_xml::events::{BytesEnd, BytesStart, BytesText};
use crate::chat;
use crate::constants::Event;
use crate::constants::*;
use crate::context::*;
use crate::dc_tools::*;
use crate::error::Error;
use crate::events::Event;
use crate::job::*;
use crate::message::*;
use crate::param::*;
@@ -225,11 +224,7 @@ pub fn send_locations_to_chat(context: &Context, chat_id: u32, seconds: i64) {
context.stock_system_msg(StockMessage::MsgLocationDisabled, "", "", 0);
chat::add_device_msg(context, chat_id, stock_str);
}
context.call_cb(
Event::CHAT_MODIFIED,
chat_id as uintptr_t,
0i32 as uintptr_t,
);
context.call_cb(Event::ChatModified(chat_id));
if 0 != seconds {
schedule_MAYBE_SEND_LOCATIONS(context, 0i32);
job_add(
@@ -292,7 +287,7 @@ pub fn set(context: &Context, latitude: f64, longitude: f64, accuracy: f64) -> l
}
}
if continue_streaming {
context.call_cb(Event::LOCATION_CHANGED, 1, 0);
context.call_cb(Event::LocationChanged(Some(1)));
};
schedule_MAYBE_SEND_LOCATIONS(context, 0);
}
@@ -369,7 +364,7 @@ fn is_marker(txt: &str) -> bool {
pub fn delete_all(context: &Context) -> Result<(), Error> {
sql::execute(context, &context.sql, "DELETE FROM locations;", params![])?;
context.call_cb(Event::LOCATION_CHANGED, 0, 0);
context.call_cb(Event::LocationChanged(None));
Ok(())
}
@@ -653,11 +648,7 @@ pub fn job_do_DC_JOB_MAYBE_SEND_LOC_ENDED(context: &Context, job: &mut Job) {
).is_ok() {
let stock_str = context.stock_system_msg(StockMessage::MsgLocationDisabled, "", "", 0);
chat::add_device_msg(context, chat_id, stock_str);
context.call_cb(
Event::CHAT_MODIFIED,
chat_id as usize,
0,
);
context.call_cb(Event::ChatModified(chat_id));
}
}
}

View File

@@ -4,7 +4,8 @@ macro_rules! info {
info!($ctx, $msg,)
};
($ctx:expr, $msg:expr, $($args:expr),* $(,)?) => {
log_event!($ctx, $crate::constants::Event::INFO, 0, $msg, $($args),*);
let formatted = format!($msg, $($args),*);
emit_event!($ctx, $crate::Event::Info(formatted));
};
}
@@ -14,7 +15,8 @@ macro_rules! warn {
warn!($ctx, $msg,)
};
($ctx:expr, $msg:expr, $($args:expr),* $(,)?) => {
log_event!($ctx, $crate::constants::Event::WARNING, 0, $msg, $($args),*);
let formatted = format!($msg, $($args),*);
emit_event!($ctx, $crate::Event::Warning(formatted));
};
}
@@ -24,26 +26,14 @@ macro_rules! error {
error!($ctx, $msg,)
};
($ctx:expr, $msg:expr, $($args:expr),* $(,)?) => {
log_event!($ctx, $crate::constants::Event::ERROR, 0, $msg, $($args),*);
};
}
#[macro_export]
macro_rules! log_event {
($ctx:expr, $data1:expr, $msg:expr) => {
log_event!($ctx, $data1, $msg,)
};
($ctx:expr, $event:expr, $data1:expr, $msg:expr, $($args:expr),* $(,)?) => {
let formatted = format!($msg, $($args),*);
let formatted_c = std::ffi::CString::new(formatted).unwrap();
$ctx.call_cb($event, $data1 as libc::uintptr_t,
formatted_c.as_ptr() as libc::uintptr_t);
emit_event!($ctx, $crate::Event::Error(formatted));
};
}
#[macro_export]
macro_rules! emit_event {
($ctx:expr, $event:expr, $data1:expr, $data2:expr) => {
$ctx.call_cb($event, $data1 as libc::uintptr_t, $data2 as libc::uintptr_t);
($ctx:expr, $event:expr) => {
$ctx.call_cb($event);
};
}

View File

@@ -3,7 +3,6 @@ use std::path::{Path, PathBuf};
use std::ptr;
use deltachat_derive::{FromSql, ToSql};
use libc::uintptr_t;
use phf::phf_map;
use crate::chat::{self, Chat};
@@ -12,6 +11,7 @@ use crate::contact::*;
use crate::context::*;
use crate::dc_tools::*;
use crate::error::Error;
use crate::events::Event;
use crate::job::*;
use crate::lot::{Lot, LotState, Meaning};
use crate::param::*;
@@ -518,7 +518,10 @@ pub unsafe fn dc_delete_msgs(context: &Context, msg_ids: *const u32, msg_cnt: li
}
if 0 != msg_cnt {
context.call_cb(Event::MSGS_CHANGED, 0 as uintptr_t, 0 as uintptr_t);
context.call_cb(Event::MsgsChanged {
chat_id: 0,
msg_id: 0,
});
job_kill_action(context, Action::Housekeeping);
job_add(context, Action::Housekeeping, 0, Params::new(), 10);
};
@@ -586,7 +589,10 @@ pub fn dc_markseen_msgs(context: &Context, msg_ids: *const u32, msg_cnt: usize)
}
if send_event {
context.call_cb(Event::MSGS_CHANGED, 0, 0);
context.call_cb(Event::MsgsChanged {
chat_id: 0,
msg_id: 0,
});
}
true
@@ -1023,11 +1029,10 @@ pub fn dc_set_msg_failed(context: &Context, msg_id: u32, error: Option<impl AsRe
)
.is_ok()
{
context.call_cb(
Event::MSG_FAILED,
msg.chat_id as uintptr_t,
msg_id as uintptr_t,
);
context.call_cb(Event::MsgFailed {
chat_id: msg.chat_id,
msg_id,
});
}
}
}

View File

@@ -13,6 +13,7 @@ use crate::dc_mimeparser::*;
use crate::dc_tools::*;
use crate::e2ee::*;
use crate::error::Error;
use crate::events::Event;
use crate::key::*;
use crate::lot::LotState;
use crate::message::*;
@@ -24,39 +25,29 @@ use crate::token;
pub const NON_ALPHANUMERIC_WITHOUT_DOT: &AsciiSet = &NON_ALPHANUMERIC.remove(b'.');
macro_rules! progress {
($context:tt, $event:expr, $contact_id:expr, $progress:expr) => {
macro_rules! joiner_progress {
($context:tt, $contact_id:expr, $progress:expr) => {
assert!(
$progress >= 0 && $progress <= 1000,
"value in range 0..1000 expected with: 0=error, 1..999=progress, 1000=success"
);
$context.call_cb(
$event,
$contact_id as libc::uintptr_t,
$progress as libc::uintptr_t,
);
};
}
macro_rules! joiner_progress {
($context:tt, $contact_id:expr, $progress:expr) => {
progress!(
$context,
Event::SECUREJOIN_JOINER_PROGRESS,
$contact_id,
$progress
);
$context.call_cb($crate::events::Event::SecurejoinJoinerProgress {
contact_id: $contact_id,
progress: $progress,
});
};
}
macro_rules! inviter_progress {
($context:tt, $contact_id:expr, $progress:expr) => {
progress!(
$context,
Event::SECUREJOIN_INVITER_PROGRESS,
$contact_id,
$progress
assert!(
$progress >= 0 && $progress <= 1000,
"value in range 0..1000 expected with: 0=error, 1..999=progress, 1000=success"
);
$context.call_cb($crate::events::Event::SecurejoinInviterProgress {
contact_id: $contact_id,
progress: $progress,
});
};
}
@@ -523,7 +514,7 @@ pub fn handle_securejoin_handshake(
Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinInvited);
info!(context, "Auth verified.",);
secure_connection_established(context, contact_chat_id);
emit_event!(context, Event::CONTACTS_CHANGED, contact_id, 0);
emit_event!(context, Event::ContactsChanged(Some(contact_id)));
inviter_progress!(context, contact_id, 600);
if join_vg {
let field_grpid = lookup_field(mimeparser, "Secure-Join-Group").unwrap_or_default();
@@ -594,7 +585,7 @@ pub fn handle_securejoin_handshake(
return ret;
}
Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinJoined);
emit_event!(context, Event::CONTACTS_CHANGED, 0, 0);
emit_event!(context, Event::ContactsChanged(None));
let cg_member_added =
lookup_field(mimeparser, "Chat-Group-Member-Added").unwrap_or_default();
if join_vg && !addr_equals_self(context, cg_member_added) {
@@ -657,7 +648,7 @@ fn secure_connection_established(context: &Context, contact_chat_id: u32) {
};
let msg = context.stock_string_repl_str(StockMessage::ContactVerified, addr);
chat::add_device_msg(context, contact_chat_id, msg);
emit_event!(context, Event::CHAT_MODIFIED, contact_chat_id, 0);
emit_event!(context, Event::ChatModified(contact_chat_id));
}
fn lookup_field(mimeparser: &dc_mimeparser_t, key: &str) -> Option<String> {
@@ -771,7 +762,7 @@ pub fn handle_degrade_event(context: &Context, peerstate: &Peerstate) {
let msg = context.stock_string_repl_str(StockMessage::ContactSetupChanged, peeraddr);
chat::add_device_msg(context, contact_chat_id, msg);
emit_event!(context, Event::CHAT_MODIFIED, contact_chat_id, 0);
emit_event!(context, Event::ChatModified(contact_chat_id));
}
}
}

View File

@@ -1,9 +1,9 @@
use lettre::smtp::client::net::*;
use lettre::*;
use crate::constants::Event;
use crate::constants::*;
use crate::context::Context;
use crate::events::Event;
use crate::login_param::LoginParam;
use crate::oauth2::*;
@@ -52,7 +52,7 @@ impl Smtp {
}
if lp.send_server.is_empty() || lp.send_port == 0 {
log_event!(context, Event::ERROR_NETWORK, 0, "SMTP bad parameters.",);
context.call_cb(Event::ErrorNetwork(0, "SMTP bad parameters.".into()));
}
self.from = if let Ok(addr) = EmailAddress::new(lp.addr.clone()) {
@@ -111,13 +111,10 @@ impl Smtp {
.credentials(creds)
.connection_reuse(lettre::smtp::ConnectionReuseParameters::ReuseUnlimited);
self.transport = Some(client.transport());
log_event!(
context,
Event::SMTP_CONNECTED,
0,
context.call_cb(Event::SmtpConnected(format!(
"SMTP-LOGIN as {} ok",
lp.send_user,
);
)));
true
}
Err(err) => {
@@ -143,12 +140,9 @@ impl Smtp {
match transport.send(mail) {
Ok(_) => {
log_event!(
context,
Event::SMTP_MESSAGE_SENT,
0,
"Message was sent to SMTP server",
);
context.call_cb(Event::SmtpMessageSent(
"Message was sent to SMTP server".into(),
));
self.transport_connected = true;
1
}

View File

@@ -3,10 +3,10 @@ use std::borrow::Cow;
use strum::EnumProperty;
use strum_macros::EnumProperty;
use crate::constants::Event;
use crate::contact::*;
use crate::context::Context;
use crate::dc_tools::*;
use crate::events::Event;
use libc::free;
/// Stock strings
@@ -128,7 +128,7 @@ impl Context {
/// translation, then this string will be returned. Otherwise a
/// default (English) string is returned.
pub fn stock_str(&self, id: StockMessage) -> Cow<str> {
let ptr = self.call_cb(Event::GET_STRING, id as usize, 0) as *mut libc::c_char;
let ptr = self.call_cb(Event::GetString { id, count: 0 }) as *mut libc::c_char;
if ptr.is_null() {
Cow::Borrowed(id.fallback())
} else {
@@ -259,16 +259,13 @@ mod tests {
assert_eq!(t.ctx.stock_str(StockMessage::NoMessages), "No messages.");
}
fn test_stock_str_no_fallback_cb(
_ctx: &Context,
evt: Event,
d1: uintptr_t,
_d2: uintptr_t,
) -> uintptr_t {
if evt == Event::GET_STRING && d1 == StockMessage::NoMessages.to_usize().unwrap() {
unsafe { "Hello there".strdup() as usize }
} else {
0
fn test_stock_str_no_fallback_cb(_ctx: &Context, evt: Event) -> uintptr_t {
match evt {
Event::GetString {
id: StockMessage::NoMessages,
..
} => unsafe { "Hello there".strdup() as usize },
_ => 0,
}
}

View File

@@ -2,14 +2,13 @@
//!
//! This module is only compiled for test runs.
use std::ffi::CStr;
use libc::uintptr_t;
use tempfile::{tempdir, TempDir};
use crate::config::Config;
use crate::constants::{Event, KeyType};
use crate::constants::KeyType;
use crate::context::{Context, ContextCallback};
use crate::events::Event;
use crate::key;
/// A Context and temporary directory.
@@ -32,7 +31,7 @@ pub fn test_context(callback: Option<Box<ContextCallback>>) -> TestContext {
let dbfile = dir.path().join("db.sqlite");
let cb: Box<ContextCallback> = match callback {
Some(cb) => cb,
None => Box::new(|_, _, _, _| 0),
None => Box::new(|_, _| 0),
};
let ctx = Context::new(cb, "FakeOs".into(), dbfile).unwrap();
TestContext { ctx: ctx, dir: dir }
@@ -47,12 +46,11 @@ pub fn dummy_context() -> TestContext {
test_context(None)
}
pub fn logging_cb(_ctx: &Context, evt: Event, _d1: uintptr_t, d2: uintptr_t) -> uintptr_t {
let to_str = unsafe { |x| CStr::from_ptr(x as *const libc::c_char).to_str().unwrap() };
pub fn logging_cb(_ctx: &Context, evt: Event) -> uintptr_t {
match evt {
Event::INFO => println!("I: {}", to_str(d2)),
Event::WARNING => println!("W: {}", to_str(d2)),
Event::ERROR => println!("E: {}", to_str(d2)),
Event::Info(msg) => println!("I: {}", msg),
Event::Warning(msg) => println!("W: {}", msg),
Event::Error(msg) => println!("E: {}", msg),
_ => (),
}
0