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

@@ -21,7 +21,7 @@ use deltachat::peerstate::*;
use deltachat::qr::*; use deltachat::qr::*;
use deltachat::sql; use deltachat::sql;
use deltachat::x::*; use deltachat::x::*;
use num_traits::FromPrimitive; use deltachat::Event;
/// Reset database tables. This function is called from Core cmdline. /// Reset database tables. This function is called from Core cmdline.
/// Argument is a bitmask, executing single or multiple actions in one call. /// Argument is a bitmask, executing single or multiple actions in one call.
@@ -86,7 +86,10 @@ pub unsafe fn dc_reset_tables(context: &Context, bits: i32) -> i32 {
info!(context, "(8) Rest but server config reset."); info!(context, "(8) Rest but server config reset.");
} }
context.call_cb(Event::MSGS_CHANGED, 0, 0); context.call_cb(Event::MsgsChanged {
chat_id: 0,
msg_id: 0,
});
1 1
} }
@@ -198,11 +201,10 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
as_str(real_spec) as_str(real_spec)
); );
if read_cnt > 0 { if read_cnt > 0 {
context.call_cb( context.call_cb(Event::MsgsChanged {
Event::MSGS_CHANGED, chat_id: 0,
0 as libc::uintptr_t, msg_id: 0,
0 as libc::uintptr_t, });
);
} }
success = 1 success = 1
} }
@@ -1016,16 +1018,17 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
res.get_text2() res.get_text2()
); );
} }
"event" => { // TODO: implement this again, unclear how to match this through though, without writing a parser.
ensure!(!arg1.is_empty(), "Argument <id> missing."); // "event" => {
let event = arg1.parse()?; // ensure!(!arg1.is_empty(), "Argument <id> missing.");
let event = Event::from_u32(event).ok_or(format_err!("Event::from_u32({})", event))?; // let event = arg1.parse()?;
let r = context.call_cb(event, 0 as libc::uintptr_t, 0 as libc::uintptr_t); // let event = Event::from_u32(event).ok_or(format_err!("Event::from_u32({})", event))?;
println!( // let r = context.call_cb(event, 0 as libc::uintptr_t, 0 as libc::uintptr_t);
"Sending event {:?}({}), received value {}.", // println!(
event, event as usize, r as libc::c_int, // "Sending event {:?}({}), received value {}.",
); // event, event as usize, r as libc::c_int,
} // );
// }
"fileinfo" => { "fileinfo" => {
ensure!(!arg1.is_empty(), "Argument <file> missing."); ensure!(!arg1.is_empty(), "Argument <file> missing.");

View File

@@ -22,13 +22,13 @@ use std::sync::{Arc, Mutex, RwLock};
use deltachat::config; use deltachat::config;
use deltachat::configure::*; use deltachat::configure::*;
use deltachat::constants::*;
use deltachat::context::*; use deltachat::context::*;
use deltachat::dc_tools::*; use deltachat::dc_tools::*;
use deltachat::job::*; use deltachat::job::*;
use deltachat::oauth2::*; use deltachat::oauth2::*;
use deltachat::securejoin::*; use deltachat::securejoin::*;
use deltachat::x::*; use deltachat::x::*;
use deltachat::Event;
use rustyline::completion::{Completer, FilenameCompleter, Pair}; use rustyline::completion::{Completer, FilenameCompleter, Pair};
use rustyline::config::OutputStreamType; use rustyline::config::OutputStreamType;
use rustyline::error::ReadlineError; use rustyline::error::ReadlineError;
@@ -43,96 +43,78 @@ use self::cmdline::*;
// Event Handler // Event Handler
fn receive_event( fn receive_event(_context: &Context, event: Event) -> libc::uintptr_t {
_context: &Context,
event: Event,
data1: libc::uintptr_t,
data2: libc::uintptr_t,
) -> libc::uintptr_t {
match event { match event {
Event::GET_STRING => {} Event::GetString { .. } => {}
Event::INFO => { Event::Info(msg) => {
/* do not show the event as this would fill the screen */ /* do not show the event as this would fill the screen */
println!("{}", to_string(data2 as *const _),); println!("{}", msg);
} }
Event::SMTP_CONNECTED => { Event::SmtpConnected(msg) => {
println!("[DC_EVENT_SMTP_CONNECTED] {}", to_string(data2 as *const _)); println!("[DC_EVENT_SMTP_CONNECTED] {}", msg);
} }
Event::IMAP_CONNECTED => { Event::ImapConnected(msg) => {
println!("[DC_EVENT_IMAP_CONNECTED] {}", to_string(data2 as *const _),); println!("[DC_EVENT_IMAP_CONNECTED] {}", msg);
} }
Event::SMTP_MESSAGE_SENT => { Event::SmtpMessageSent(msg) => {
println!( println!("[DC_EVENT_SMTP_MESSAGE_SENT] {}", msg);
"[DC_EVENT_SMTP_MESSAGE_SENT] {}",
to_string(data2 as *const _),
);
} }
Event::WARNING => { Event::Warning(msg) => {
println!("[Warning] {}", to_string(data2 as *const _),); println!("[Warning] {}", msg);
} }
Event::ERROR => { Event::Error(msg) => {
println!( println!("\x1b[31m[DC_EVENT_ERROR] {}\x1b[0m", msg);
"\x1b[31m[DC_EVENT_ERROR] {}\x1b[0m",
to_string(data2 as *const _),
);
} }
Event::ERROR_NETWORK => { Event::ErrorNetwork(c, msg) => {
println!( println!(
"\x1b[31m[DC_EVENT_ERROR_NETWORK] first={}, msg={}\x1b[0m", "\x1b[31m[DC_EVENT_ERROR_NETWORK] first={}, msg={}\x1b[0m",
data1 as usize, c, msg
to_string(data2 as *const _),
); );
} }
Event::ERROR_SELF_NOT_IN_GROUP => { Event::ErrorSelfNotInGroup(msg) => {
println!( println!("\x1b[31m[DC_EVENT_ERROR_SELF_NOT_IN_GROUP] {}\x1b[0m", msg);
"\x1b[31m[DC_EVENT_ERROR_SELF_NOT_IN_GROUP] {}\x1b[0m",
to_string(data2 as *const _),
);
} }
Event::MSGS_CHANGED => { Event::MsgsChanged { chat_id, msg_id } => {
print!( print!(
"\x1b[33m{{Received DC_EVENT_MSGS_CHANGED({}, {})}}\n\x1b[0m", "\x1b[33m{{Received DC_EVENT_MSGS_CHANGED(chat_id={}, msg_id={})}}\n\x1b[0m",
data1 as usize, data2 as usize, chat_id, msg_id,
); );
} }
Event::CONTACTS_CHANGED => { Event::ContactsChanged(_) => {
print!("\x1b[33m{{Received DC_EVENT_CONTACTS_CHANGED()}}\n\x1b[0m"); print!("\x1b[33m{{Received DC_EVENT_CONTACTS_CHANGED()}}\n\x1b[0m");
} }
Event::LOCATION_CHANGED => { Event::LocationChanged(contact) => {
print!( print!(
"\x1b[33m{{Received DC_EVENT_LOCATION_CHANGED(contact={})}}\n\x1b[0m", "\x1b[33m{{Received DC_EVENT_LOCATION_CHANGED(contact={:?})}}\n\x1b[0m",
data1 as usize, contact,
); );
} }
Event::CONFIGURE_PROGRESS => { Event::ConfigureProgress(progress) => {
print!( print!(
"\x1b[33m{{Received DC_EVENT_CONFIGURE_PROGRESS({} ‰)}}\n\x1b[0m", "\x1b[33m{{Received DC_EVENT_CONFIGURE_PROGRESS({} ‰)}}\n\x1b[0m",
data1 as usize, progress,
); );
} }
Event::IMEX_PROGRESS => { Event::ImexProgress(progress) => {
print!( print!(
"\x1b[33m{{Received DC_EVENT_IMEX_PROGRESS({} ‰)}}\n\x1b[0m", "\x1b[33m{{Received DC_EVENT_IMEX_PROGRESS({} ‰)}}\n\x1b[0m",
data1 as usize, progress,
); );
} }
Event::IMEX_FILE_WRITTEN => { Event::ImexFileWritten(file) => {
print!( print!(
"\x1b[33m{{Received DC_EVENT_IMEX_FILE_WRITTEN({})}}\n\x1b[0m", "\x1b[33m{{Received DC_EVENT_IMEX_FILE_WRITTEN({})}}\n\x1b[0m",
to_string(data1 as *const _) file.display()
); );
} }
Event::CHAT_MODIFIED => { Event::ChatModified(chat) => {
print!( print!(
"\x1b[33m{{Received DC_EVENT_CHAT_MODIFIED({})}}\n\x1b[0m", "\x1b[33m{{Received DC_EVENT_CHAT_MODIFIED({})}}\n\x1b[0m",
data1 as usize, chat
); );
} }
_ => { _ => {
print!( print!("\x1b[33m{{Received {:?}}}\n\x1b[0m", event);
"\x1b[33m{{Received {:?}({}, {})}}\n\x1b[0m",
event, data1 as usize, data2 as usize,
);
} }
} }

View File

@@ -1,6 +1,5 @@
extern crate deltachat; extern crate deltachat;
use std::ffi::CStr;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use std::{thread, time}; use std::{thread, time};
use tempfile::tempdir; use tempfile::tempdir;
@@ -9,31 +8,32 @@ use deltachat::chat;
use deltachat::chatlist::*; use deltachat::chatlist::*;
use deltachat::config; use deltachat::config;
use deltachat::configure::*; use deltachat::configure::*;
use deltachat::constants::Event;
use deltachat::contact::*; use deltachat::contact::*;
use deltachat::context::*; use deltachat::context::*;
use deltachat::job::{ use deltachat::job::{
perform_imap_fetch, perform_imap_idle, perform_imap_jobs, perform_smtp_idle, perform_smtp_jobs, perform_imap_fetch, perform_imap_idle, perform_imap_jobs, perform_smtp_idle, perform_smtp_jobs,
}; };
use deltachat::Event;
fn cb(_ctx: &Context, event: Event, data1: usize, data2: usize) -> usize { fn cb(_ctx: &Context, event: Event) -> usize {
println!("[{:?}]", event); print!("[{:?}]", event);
match event { match event {
Event::CONFIGURE_PROGRESS => { Event::ConfigureProgress(progress) => {
println!(" progress: {}", data1); print!(" progress: {}\n", progress);
0 0
} }
Event::INFO | Event::WARNING | Event::ERROR | Event::ERROR_NETWORK => { Event::Info(msg)
println!( | Event::Warning(msg)
" {}", | Event::Error(msg)
unsafe { CStr::from_ptr(data2 as *const _) } | Event::ErrorNetwork(_, msg) => {
.to_str() print!(" {}\n", msg);
.unwrap() 0
); }
_ => {
print!("\n");
0 0
} }
_ => 0,
} }
} }

View File

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

View File

@@ -1,4 +1,3 @@
use libc::uintptr_t;
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
use crate::constants::*; use crate::constants::*;
@@ -19,14 +18,10 @@ use auto_mozilla::moz_autoconfigure;
macro_rules! progress { macro_rules! progress {
($context:tt, $progress:expr) => { ($context:tt, $progress:expr) => {
assert!( assert!(
$progress >= 0 && $progress <= 1000, $progress > 0 && $progress <= 1000,
"value in range 0..1000 expected with: 0=error, 1..999=progress, 1000=success" "value in range 0..1000 expected with: 0=error, 1..999=progress, 1000=success"
); );
$context.call_cb( $context.call_cb($crate::events::Event::ConfigureProgress($progress));
Event::CONFIGURE_PROGRESS,
$progress as uintptr_t,
0 as uintptr_t,
);
}; };
} }
@@ -567,7 +562,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
dc_free_ongoing(context); 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 //! Constants
#![allow(non_camel_case_types, dead_code)] #![allow(non_camel_case_types, dead_code)]
use lazy_static::lazy_static;
use deltachat_derive::*; use deltachat_derive::*;
use lazy_static::lazy_static;
lazy_static! { lazy_static! {
pub static ref DC_VERSION_STR: String = env!("CARGO_PKG_VERSION").to_string(); 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, // 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. // 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_FILE_COPIED: usize = 2055; // deprecated;
const DC_EVENT_IS_OFFLINE: usize = 2081; // deprecated; const DC_EVENT_IS_OFFLINE: usize = 2081; // deprecated;
const DC_ERROR_SEE_STRING: usize = 0; // deprecated; const DC_ERROR_SEE_STRING: usize = 0; // deprecated;

View File

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

View File

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

View File

@@ -2,7 +2,6 @@ use std::ffi::CString;
use std::path::Path; use std::path::Path;
use std::ptr; use std::ptr;
use libc::uintptr_t;
use mmime::mailmime_content::*; use mmime::mailmime_content::*;
use mmime::mmapstring::*; use mmime::mmapstring::*;
use mmime::other::*; use mmime::other::*;
@@ -16,6 +15,7 @@ use crate::context::Context;
use crate::dc_tools::*; use crate::dc_tools::*;
use crate::e2ee; use crate::e2ee;
use crate::error::*; use crate::error::*;
use crate::events::Event;
use crate::job::*; use crate::job::*;
use crate::key::*; use crate::key::*;
use crate::message::*; 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.",); error!(context, "No Import/export dir/file given.",);
} else { } else {
info!(context, "Import/export process started.",); 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() { if !context.sql.is_open() {
error!(context, "Import/export: Database not opened.",); error!(context, "Import/export: Database not opened.",);
} else { } else {
@@ -551,11 +552,7 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) {
} }
dc_free_ongoing(context); dc_free_ongoing(context);
} }
context.call_cb( context.call_cb(Event::ImexProgress(if 0 != success { 1000 } else { 0 }));
Event::IMEX_PROGRESS,
(if 0 != success { 1000 } else { 0 }) as uintptr_t,
0 as uintptr_t,
);
} }
/******************************************************************************* /*******************************************************************************
@@ -637,7 +634,7 @@ unsafe fn import_backup(context: &Context, backup_to_import: *const libc::c_char
if permille > 990 { if permille > 990 {
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() { if file_blob.is_empty() {
continue; continue;
} }
@@ -773,11 +770,7 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> bool {
if permille > 990 { if permille > 990 {
permille = 990; permille = 990;
} }
context.call_cb( context.call_cb(Event::ImexProgress(permille));
Event::IMEX_PROGRESS,
permille as uintptr_t,
0 as uintptr_t,
);
let name_f = entry.file_name(); let name_f = entry.file_name();
let name = name_f.to_string_lossy(); 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) .set_config_int(context, "backup_time", now as i32)
.is_ok() .is_ok()
{ {
context.call_cb( context.call_cb(Event::ImexFileWritten(
Event::IMEX_FILE_WRITTEN, as_path(dest_pathNfilename).to_path_buf(),
dest_pathNfilename as uintptr_t, ));
0,
);
success = true; success = true;
} }
} }
@@ -1063,11 +1054,7 @@ unsafe fn export_key_to_asc_file(
if !key.write_asc_to_file(as_path(file_name), context) { if !key.write_asc_to_file(as_path(file_name), context) {
error!(context, "Cannot write key to {}", as_str(file_name),); error!(context, "Cannot write key to {}", as_str(file_name),);
} else { } else {
context.call_cb( context.call_cb(Event::ImexFileWritten(as_path(file_name).to_path_buf()));
Event::IMEX_FILE_WRITTEN,
file_name as uintptr_t,
0i32 as uintptr_t,
);
success = true; success = true;
} }
free(file_name as *mut libc::c_void); free(file_name as *mut libc::c_void);
@@ -1079,8 +1066,6 @@ unsafe fn export_key_to_asc_file(
mod tests { mod tests {
use super::*; use super::*;
use num_traits::ToPrimitive;
use crate::test_utils::*; use crate::test_utils::*;
#[test] #[test]
@@ -1103,11 +1088,13 @@ mod tests {
assert!(msg.contains("-----END PGP MESSAGE-----\n")); assert!(msg.contains("-----END PGP MESSAGE-----\n"));
} }
fn ac_setup_msg_cb(ctx: &Context, evt: Event, d1: uintptr_t, d2: uintptr_t) -> uintptr_t { fn ac_setup_msg_cb(ctx: &Context, evt: Event) -> libc::uintptr_t {
if evt == Event::GET_STRING && d1 == StockMessage::AcSetupMsgBody.to_usize().unwrap() { match evt {
unsafe { "hello\r\nthere".strdup() as usize } Event::GetString {
} else { id: StockMessage::AcSetupMsgBody,
logging_cb(ctx, evt, d1, d2) ..
} => 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 std::ptr;
use itertools::join; use itertools::join;
use libc::uintptr_t;
use mmime::clist::*; use mmime::clist::*;
use mmime::mailimf::*; use mmime::mailimf::*;
use mmime::mailimf_types::*; use mmime::mailimf_types::*;
@@ -21,6 +20,7 @@ use crate::dc_mimeparser::*;
use crate::dc_strencode::*; use crate::dc_strencode::*;
use crate::dc_tools::*; use crate::dc_tools::*;
use crate::error::Result; use crate::error::Result;
use crate::events::Event;
use crate::job::*; use crate::job::*;
use crate::location; use crate::location;
use crate::message::*; use crate::message::*;
@@ -31,6 +31,12 @@ use crate::sql;
use crate::stock::StockMessage; use crate::stock::StockMessage;
use crate::x::*; use crate::x::*;
#[derive(Debug, PartialEq, Eq)]
enum CreateEvent {
MsgsChanged,
IncomingMsg,
}
/// Receive a message and add it to the database. /// Receive a message and add it to the database.
pub unsafe fn dc_receive_imf( pub unsafe fn dc_receive_imf(
context: &Context, context: &Context,
@@ -82,7 +88,7 @@ pub unsafe fn dc_receive_imf(
let rfc724_mid = std::ptr::null_mut(); let rfc724_mid = std::ptr::null_mut();
let mut sent_timestamp = 0; let mut sent_timestamp = 0;
let mut created_db_entries = Vec::new(); 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 rr_event_to_send = Vec::new();
let mut to_ids = Vec::with_capacity(16); 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 // helper method to handle early exit and memory cleanup
let cleanup = |context: &Context, let cleanup = |context: &Context,
rfc724_mid: *mut libc::c_char, rfc724_mid: *mut libc::c_char,
create_event_to_send: &Option<Event>, create_event_to_send: &Option<CreateEvent>,
created_db_entries: &Vec<(usize, usize)>, created_db_entries: &Vec<(usize, usize)>,
rr_event_to_send: &Vec<(u32, u32)>| { rr_event_to_send: &Vec<(u32, u32)>| {
free(rfc724_mid.cast()); free(rfc724_mid.cast());
if let Some(create_event_to_send) = create_event_to_send { if let Some(create_event_to_send) = create_event_to_send {
for (msg_id, insert_id) in created_db_entries { 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 { 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, to_self: i32,
insert_msg_id: &mut u32, insert_msg_id: &mut u32,
created_db_entries: &mut Vec<(usize, usize)>, created_db_entries: &mut Vec<(usize, usize)>,
create_event_to_send: &mut Option<Event>, create_event_to_send: &mut Option<CreateEvent>,
) -> Result<()> { ) -> Result<()> {
let mut state: MessageState; let mut state: MessageState;
let mut msgrmsg: libc::c_int; let mut msgrmsg: libc::c_int;
@@ -730,9 +749,9 @@ unsafe fn add_parts(
if 0 != from_id_blocked { if 0 != from_id_blocked {
*create_event_to_send = None; *create_event_to_send = None;
} else if Blocked::Not != chat_id_blocked { } else if Blocked::Not != chat_id_blocked {
*create_event_to_send = Some(Event::MSGS_CHANGED); *create_event_to_send = Some(CreateEvent::MsgsChanged);
} else { } 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 { if send_event {
context.call_cb( context.call_cb(Event::LocationChanged(Some(from_id)));
Event::LOCATION_CHANGED,
from_id as uintptr_t,
0 as uintptr_t,
);
} }
} }
@@ -1321,7 +1336,7 @@ unsafe fn create_or_lookup_group(
) )
.is_ok() .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() { if !X_MrGrpImageChanged.is_empty() {
@@ -1403,7 +1418,7 @@ unsafe fn create_or_lookup_group(
} }
if 0 != send_EVENT_CHAT_MODIFIED { 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 - // 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); 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( cleanup(
grpname, 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_receive_imf::dc_receive_imf;
use crate::dc_tools::CStringExt; use crate::dc_tools::CStringExt;
use crate::dc_tools::*; use crate::dc_tools::*;
use crate::events::Event;
use crate::job::{job_add, Action}; use crate::job::{job_add, Action};
use crate::login_param::LoginParam; use crate::login_param::LoginParam;
use crate::message::{dc_rfc724_mid_exists, dc_update_msg_move_state, dc_update_server_uid}; 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_server: &str = config.imap_server.as_ref();
let imap_port = config.imap_port; let imap_port = config.imap_port;
log_event!( emit_event!(
context, context,
Event::ERROR_NETWORK, Event::ErrorNetwork(
0, 0,
"Could not connect to IMAP-server {}:{}. ({})", format!(
imap_server, "Could not connect to IMAP-server {}:{}. ({})",
imap_port, imap_server, imap_port, err
err )
)
); );
return false; return false;
@@ -460,7 +462,10 @@ impl Imap {
true true
} }
Err((err, _)) => { 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); self.unsetup_handle(context);
false false
@@ -553,13 +558,12 @@ impl Imap {
let caps_list = caps let caps_list = caps
.iter() .iter()
.fold(String::new(), |s, c| s + &format!(" {:?}", c)); .fold(String::new(), |s, c| s + &format!(" {:?}", c));
log_event!( emit_event!(
context, context,
Event::IMAP_CONNECTED, Event::ImapConnected(format!(
0, "IMAP-LOGIN as {}, capabilities: {}",
"IMAP-LOGIN as {}, capabilities: {}", lp.mail_user, caps_list,
lp.mail_user, ))
caps_list,
); );
(false, can_idle, has_xlist) (false, can_idle, has_xlist)
} }

View File

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

View File

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

View File

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

View File

@@ -4,7 +4,8 @@ macro_rules! info {
info!($ctx, $msg,) info!($ctx, $msg,)
}; };
($ctx:expr, $msg:expr, $($args:expr),* $(,)?) => { ($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,) warn!($ctx, $msg,)
}; };
($ctx:expr, $msg:expr, $($args:expr),* $(,)?) => { ($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,) error!($ctx, $msg,)
}; };
($ctx:expr, $msg:expr, $($args:expr),* $(,)?) => { ($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 = format!($msg, $($args),*);
let formatted_c = std::ffi::CString::new(formatted).unwrap(); emit_event!($ctx, $crate::Event::Error(formatted));
$ctx.call_cb($event, $data1 as libc::uintptr_t,
formatted_c.as_ptr() as libc::uintptr_t);
}; };
} }
#[macro_export] #[macro_export]
macro_rules! emit_event { macro_rules! emit_event {
($ctx:expr, $event:expr, $data1:expr, $data2:expr) => { ($ctx:expr, $event:expr) => {
$ctx.call_cb($event, $data1 as libc::uintptr_t, $data2 as libc::uintptr_t); $ctx.call_cb($event);
}; };
} }

View File

@@ -3,7 +3,6 @@ use std::path::{Path, PathBuf};
use std::ptr; use std::ptr;
use deltachat_derive::{FromSql, ToSql}; use deltachat_derive::{FromSql, ToSql};
use libc::uintptr_t;
use phf::phf_map; use phf::phf_map;
use crate::chat::{self, Chat}; use crate::chat::{self, Chat};
@@ -12,6 +11,7 @@ use crate::contact::*;
use crate::context::*; use crate::context::*;
use crate::dc_tools::*; use crate::dc_tools::*;
use crate::error::Error; use crate::error::Error;
use crate::events::Event;
use crate::job::*; use crate::job::*;
use crate::lot::{Lot, LotState, Meaning}; use crate::lot::{Lot, LotState, Meaning};
use crate::param::*; 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 { 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_kill_action(context, Action::Housekeeping);
job_add(context, Action::Housekeeping, 0, Params::new(), 10); 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 { if send_event {
context.call_cb(Event::MSGS_CHANGED, 0, 0); context.call_cb(Event::MsgsChanged {
chat_id: 0,
msg_id: 0,
});
} }
true true
@@ -1023,11 +1029,10 @@ pub fn dc_set_msg_failed(context: &Context, msg_id: u32, error: Option<impl AsRe
) )
.is_ok() .is_ok()
{ {
context.call_cb( context.call_cb(Event::MsgFailed {
Event::MSG_FAILED, chat_id: msg.chat_id,
msg.chat_id as uintptr_t, msg_id,
msg_id as uintptr_t, });
);
} }
} }
} }

View File

@@ -13,6 +13,7 @@ use crate::dc_mimeparser::*;
use crate::dc_tools::*; use crate::dc_tools::*;
use crate::e2ee::*; use crate::e2ee::*;
use crate::error::Error; use crate::error::Error;
use crate::events::Event;
use crate::key::*; use crate::key::*;
use crate::lot::LotState; use crate::lot::LotState;
use crate::message::*; use crate::message::*;
@@ -24,39 +25,29 @@ use crate::token;
pub const NON_ALPHANUMERIC_WITHOUT_DOT: &AsciiSet = &NON_ALPHANUMERIC.remove(b'.'); pub const NON_ALPHANUMERIC_WITHOUT_DOT: &AsciiSet = &NON_ALPHANUMERIC.remove(b'.');
macro_rules! progress { macro_rules! joiner_progress {
($context:tt, $event:expr, $contact_id:expr, $progress:expr) => { ($context:tt, $contact_id:expr, $progress:expr) => {
assert!( assert!(
$progress >= 0 && $progress <= 1000, $progress >= 0 && $progress <= 1000,
"value in range 0..1000 expected with: 0=error, 1..999=progress, 1000=success" "value in range 0..1000 expected with: 0=error, 1..999=progress, 1000=success"
); );
$context.call_cb( $context.call_cb($crate::events::Event::SecurejoinJoinerProgress {
$event, contact_id: $contact_id,
$contact_id as libc::uintptr_t, progress: $progress,
$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
);
}; };
} }
macro_rules! inviter_progress { macro_rules! inviter_progress {
($context:tt, $contact_id:expr, $progress:expr) => { ($context:tt, $contact_id:expr, $progress:expr) => {
progress!( assert!(
$context, $progress >= 0 && $progress <= 1000,
Event::SECUREJOIN_INVITER_PROGRESS, "value in range 0..1000 expected with: 0=error, 1..999=progress, 1000=success"
$contact_id,
$progress
); );
$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); Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinInvited);
info!(context, "Auth verified.",); info!(context, "Auth verified.",);
secure_connection_established(context, contact_chat_id); 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); inviter_progress!(context, contact_id, 600);
if join_vg { if join_vg {
let field_grpid = lookup_field(mimeparser, "Secure-Join-Group").unwrap_or_default(); let field_grpid = lookup_field(mimeparser, "Secure-Join-Group").unwrap_or_default();
@@ -594,7 +585,7 @@ pub fn handle_securejoin_handshake(
return ret; return ret;
} }
Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinJoined); 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 = let cg_member_added =
lookup_field(mimeparser, "Chat-Group-Member-Added").unwrap_or_default(); lookup_field(mimeparser, "Chat-Group-Member-Added").unwrap_or_default();
if join_vg && !addr_equals_self(context, cg_member_added) { 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); let msg = context.stock_string_repl_str(StockMessage::ContactVerified, addr);
chat::add_device_msg(context, contact_chat_id, msg); 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> { 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); let msg = context.stock_string_repl_str(StockMessage::ContactSetupChanged, peeraddr);
chat::add_device_msg(context, contact_chat_id, msg); 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::smtp::client::net::*;
use lettre::*; use lettre::*;
use crate::constants::Event;
use crate::constants::*; use crate::constants::*;
use crate::context::Context; use crate::context::Context;
use crate::events::Event;
use crate::login_param::LoginParam; use crate::login_param::LoginParam;
use crate::oauth2::*; use crate::oauth2::*;
@@ -52,7 +52,7 @@ impl Smtp {
} }
if lp.send_server.is_empty() || lp.send_port == 0 { 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()) { self.from = if let Ok(addr) = EmailAddress::new(lp.addr.clone()) {
@@ -111,13 +111,10 @@ impl Smtp {
.credentials(creds) .credentials(creds)
.connection_reuse(lettre::smtp::ConnectionReuseParameters::ReuseUnlimited); .connection_reuse(lettre::smtp::ConnectionReuseParameters::ReuseUnlimited);
self.transport = Some(client.transport()); self.transport = Some(client.transport());
log_event!( context.call_cb(Event::SmtpConnected(format!(
context,
Event::SMTP_CONNECTED,
0,
"SMTP-LOGIN as {} ok", "SMTP-LOGIN as {} ok",
lp.send_user, lp.send_user,
); )));
true true
} }
Err(err) => { Err(err) => {
@@ -143,12 +140,9 @@ impl Smtp {
match transport.send(mail) { match transport.send(mail) {
Ok(_) => { Ok(_) => {
log_event!( context.call_cb(Event::SmtpMessageSent(
context, "Message was sent to SMTP server".into(),
Event::SMTP_MESSAGE_SENT, ));
0,
"Message was sent to SMTP server",
);
self.transport_connected = true; self.transport_connected = true;
1 1
} }

View File

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

View File

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

View File

@@ -7,7 +7,6 @@ use tempfile::{tempdir, TempDir};
use deltachat::chat::{self, Chat}; use deltachat::chat::{self, Chat};
use deltachat::config; use deltachat::config;
use deltachat::constants::*;
use deltachat::contact::*; use deltachat::contact::*;
use deltachat::context::*; use deltachat::context::*;
use deltachat::dc_imex::*; use deltachat::dc_imex::*;
@@ -16,6 +15,7 @@ use deltachat::keyring::*;
use deltachat::oauth2::*; use deltachat::oauth2::*;
use deltachat::pgp::*; use deltachat::pgp::*;
use deltachat::x::*; use deltachat::x::*;
use deltachat::Event;
use libc; use libc;
/* some data used for testing /* some data used for testing
@@ -562,12 +562,7 @@ fn test_encryption_decryption() {
assert_eq!(plain, original_text); assert_eq!(plain, original_text);
} }
fn cb( fn cb(_context: &Context, _event: Event) -> libc::uintptr_t {
_context: &Context,
_event: Event,
_data1: libc::uintptr_t,
_data2: libc::uintptr_t,
) -> libc::uintptr_t {
0 0
} }