diff --git a/Cargo.lock b/Cargo.lock index 092f302a5..2ba404916 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -871,6 +871,7 @@ dependencies = [ "human-panic", "libc", "num-traits", + "rand", "serde_json", "thiserror", ] diff --git a/deltachat-ffi/Cargo.toml b/deltachat-ffi/Cargo.toml index 7f10d5e00..5b346bd5d 100644 --- a/deltachat-ffi/Cargo.toml +++ b/deltachat-ffi/Cargo.toml @@ -23,6 +23,7 @@ serde_json = "1.0" async-std = "1.6.0" anyhow = "1.0.28" thiserror = "1.0.14" +rand = "0.7.3" [features] default = ["vendored"] diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 853f5fb6e..18026a058 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -76,13 +76,17 @@ pub unsafe extern "C" fn dc_context_new( }; let ctx = if blobdir.is_null() || *blobdir == 0 { - block_on(Context::new(os_name, as_path(dbfile).to_path_buf().into())) - } else { - block_on(Context::with_blobdir( + use rand::Rng; + // generate random ID as this functionality is not yet available on the C-api. + let id = rand::thread_rng().gen(); + block_on(Context::new( os_name, as_path(dbfile).to_path_buf().into(), - as_path(blobdir).to_path_buf().into(), + id, )) + } else { + eprintln!("blobdir can not be defined explicitly anymore"); + return ptr::null_mut(); }; match ctx { Ok(ctx) => Box::into_raw(Box::new(ctx)), @@ -333,38 +337,38 @@ pub unsafe extern "C" fn dc_event_get_data1_int(event: *mut dc_event_t) -> libc: return 0; } - let event = &*event; + let event = &(*event).typ; match event { - Event::Info(_) - | Event::SmtpConnected(_) - | Event::ImapConnected(_) - | Event::SmtpMessageSent(_) - | Event::ImapMessageDeleted(_) - | Event::ImapMessageMoved(_) - | Event::ImapFolderEmptied(_) - | Event::NewBlobFile(_) - | Event::DeletedBlobFile(_) - | Event::Warning(_) - | Event::Error(_) - | Event::ErrorNetwork(_) - | Event::ErrorSelfNotInGroup(_) => 0, - Event::MsgsChanged { chat_id, .. } - | Event::IncomingMsg { chat_id, .. } - | Event::MsgDelivered { chat_id, .. } - | Event::MsgFailed { chat_id, .. } - | Event::MsgRead { chat_id, .. } - | Event::ChatModified(chat_id) - | Event::ChatEphemeralTimerModified { chat_id, .. } => chat_id.to_u32() as libc::c_int, - Event::ContactsChanged(id) | Event::LocationChanged(id) => { + EventType::Info(_) + | EventType::SmtpConnected(_) + | EventType::ImapConnected(_) + | EventType::SmtpMessageSent(_) + | EventType::ImapMessageDeleted(_) + | EventType::ImapMessageMoved(_) + | EventType::ImapFolderEmptied(_) + | EventType::NewBlobFile(_) + | EventType::DeletedBlobFile(_) + | EventType::Warning(_) + | EventType::Error(_) + | EventType::ErrorNetwork(_) + | EventType::ErrorSelfNotInGroup(_) => 0, + EventType::MsgsChanged { chat_id, .. } + | EventType::IncomingMsg { chat_id, .. } + | EventType::MsgDelivered { chat_id, .. } + | EventType::MsgFailed { chat_id, .. } + | EventType::MsgRead { chat_id, .. } + | EventType::ChatModified(chat_id) + | EventType::ChatEphemeralTimerModified { chat_id, .. } => chat_id.to_u32() as libc::c_int, + EventType::ContactsChanged(id) | EventType::LocationChanged(id) => { let id = id.unwrap_or_default(); id as libc::c_int } - Event::ConfigureProgress(progress) | Event::ImexProgress(progress) => { + EventType::ConfigureProgress(progress) | EventType::ImexProgress(progress) => { *progress as libc::c_int } - Event::ImexFileWritten(_) => 0, - Event::SecurejoinInviterProgress { contact_id, .. } - | Event::SecurejoinJoinerProgress { contact_id, .. } => *contact_id as libc::c_int, + EventType::ImexFileWritten(_) => 0, + EventType::SecurejoinInviterProgress { contact_id, .. } + | EventType::SecurejoinJoinerProgress { contact_id, .. } => *contact_id as libc::c_int, } } @@ -375,36 +379,36 @@ pub unsafe extern "C" fn dc_event_get_data2_int(event: *mut dc_event_t) -> libc: return 0; } - let event = &*event; + let event = &(*event).typ; match event { - Event::Info(_) - | Event::SmtpConnected(_) - | Event::ImapConnected(_) - | Event::SmtpMessageSent(_) - | Event::ImapMessageDeleted(_) - | Event::ImapMessageMoved(_) - | Event::ImapFolderEmptied(_) - | Event::NewBlobFile(_) - | Event::DeletedBlobFile(_) - | Event::Warning(_) - | Event::Error(_) - | Event::ErrorNetwork(_) - | Event::ErrorSelfNotInGroup(_) - | Event::ContactsChanged(_) - | Event::LocationChanged(_) - | Event::ConfigureProgress(_) - | Event::ImexProgress(_) - | Event::ImexFileWritten(_) - | Event::ChatModified(_) => 0, - Event::MsgsChanged { msg_id, .. } - | Event::IncomingMsg { msg_id, .. } - | Event::MsgDelivered { msg_id, .. } - | Event::MsgFailed { msg_id, .. } - | Event::MsgRead { msg_id, .. } => msg_id.to_u32() as libc::c_int, - Event::SecurejoinInviterProgress { progress, .. } - | Event::SecurejoinJoinerProgress { progress, .. } => *progress as libc::c_int, - Event::ChatEphemeralTimerModified { timer, .. } => timer.to_u32() as libc::c_int, + EventType::Info(_) + | EventType::SmtpConnected(_) + | EventType::ImapConnected(_) + | EventType::SmtpMessageSent(_) + | EventType::ImapMessageDeleted(_) + | EventType::ImapMessageMoved(_) + | EventType::ImapFolderEmptied(_) + | EventType::NewBlobFile(_) + | EventType::DeletedBlobFile(_) + | EventType::Warning(_) + | EventType::Error(_) + | EventType::ErrorNetwork(_) + | EventType::ErrorSelfNotInGroup(_) + | EventType::ContactsChanged(_) + | EventType::LocationChanged(_) + | EventType::ConfigureProgress(_) + | EventType::ImexProgress(_) + | EventType::ImexFileWritten(_) + | EventType::ChatModified(_) => 0, + EventType::MsgsChanged { msg_id, .. } + | EventType::IncomingMsg { msg_id, .. } + | EventType::MsgDelivered { msg_id, .. } + | EventType::MsgFailed { msg_id, .. } + | EventType::MsgRead { msg_id, .. } => msg_id.to_u32() as libc::c_int, + EventType::SecurejoinInviterProgress { progress, .. } + | EventType::SecurejoinJoinerProgress { progress, .. } => *progress as libc::c_int, + EventType::ChatEphemeralTimerModified { timer, .. } => timer.to_u32() as libc::c_int, } } @@ -415,45 +419,55 @@ pub unsafe extern "C" fn dc_event_get_data2_str(event: *mut dc_event_t) -> *mut return ptr::null_mut(); } - let event = &*event; + let event = &(*event).typ; match event { - Event::Info(msg) - | Event::SmtpConnected(msg) - | Event::ImapConnected(msg) - | Event::SmtpMessageSent(msg) - | Event::ImapMessageDeleted(msg) - | Event::ImapMessageMoved(msg) - | Event::ImapFolderEmptied(msg) - | Event::NewBlobFile(msg) - | Event::DeletedBlobFile(msg) - | Event::Warning(msg) - | Event::Error(msg) - | Event::ErrorNetwork(msg) - | Event::ErrorSelfNotInGroup(msg) => { + EventType::Info(msg) + | EventType::SmtpConnected(msg) + | EventType::ImapConnected(msg) + | EventType::SmtpMessageSent(msg) + | EventType::ImapMessageDeleted(msg) + | EventType::ImapMessageMoved(msg) + | EventType::ImapFolderEmptied(msg) + | EventType::NewBlobFile(msg) + | EventType::DeletedBlobFile(msg) + | EventType::Warning(msg) + | EventType::Error(msg) + | EventType::ErrorNetwork(msg) + | EventType::ErrorSelfNotInGroup(msg) => { let data2 = msg.to_c_string().unwrap_or_default(); data2.into_raw() } - Event::MsgsChanged { .. } - | Event::IncomingMsg { .. } - | Event::MsgDelivered { .. } - | Event::MsgFailed { .. } - | Event::MsgRead { .. } - | Event::ChatModified(_) - | Event::ContactsChanged(_) - | Event::LocationChanged(_) - | Event::ConfigureProgress(_) - | Event::ImexProgress(_) - | Event::SecurejoinInviterProgress { .. } - | Event::SecurejoinJoinerProgress { .. } - | Event::ChatEphemeralTimerModified { .. } => ptr::null_mut(), - Event::ImexFileWritten(file) => { + EventType::MsgsChanged { .. } + | EventType::IncomingMsg { .. } + | EventType::MsgDelivered { .. } + | EventType::MsgFailed { .. } + | EventType::MsgRead { .. } + | EventType::ChatModified(_) + | EventType::ContactsChanged(_) + | EventType::LocationChanged(_) + | EventType::ConfigureProgress(_) + | EventType::ImexProgress(_) + | EventType::SecurejoinInviterProgress { .. } + | EventType::SecurejoinJoinerProgress { .. } + | EventType::ChatEphemeralTimerModified { .. } => ptr::null_mut(), + EventType::ImexFileWritten(file) => { let data2 = file.to_c_string().unwrap_or_default(); data2.into_raw() } } } +#[no_mangle] +pub unsafe extern "C" fn dc_event_get_account_id(event: *mut dc_event_t) -> u32 { + if event.is_null() { + eprintln!("ignoring careless call to dc_event_get_account_id()"); + return 0; + } + + (*event).id +} + #[no_mangle] pub type dc_event_emitter_t = EventEmitter; @@ -3570,71 +3584,16 @@ pub unsafe extern "C" fn dc_accounts_event_emitter_unref( } #[no_mangle] -pub type dc_accounts_event_t = deltachat::accounts::Event; - -#[no_mangle] -pub unsafe extern "C" fn dc_accounts_event_unref(a: *mut dc_accounts_event_t) { - if a.is_null() { - eprintln!("ignoring careless call to dc_accounts_event_unref()"); - return; - } - - let _ = Box::from_raw(a); -} - -#[no_mangle] -pub unsafe extern "C" fn dc_accounts_event_get_id(event: *mut dc_accounts_event_t) -> libc::c_int { - if event.is_null() { - eprintln!("ignoring careless call to dc_accounts_event_get_id()"); - return 0; - } - - let event = &*event; - event.event.as_id() -} - -#[no_mangle] -pub unsafe extern "C" fn dc_accounts_event_get_data1_int( - event: *mut dc_accounts_event_t, -) -> libc::c_int { - if event.is_null() { - eprintln!("ignoring careless call to dc_accounts_event_get_data1_int()"); - return 0; - } - - dc_event_get_data1_int(&mut (*event).event) -} - -#[no_mangle] -pub unsafe extern "C" fn dc_accounts_event_get_data2_int( - event: *mut dc_accounts_event_t, -) -> libc::c_int { - if event.is_null() { - eprintln!("ignoring careless call to dc_accounts_event_get_data2_int()"); - return 0; - } - - dc_event_get_data2_int(&mut (*event).event) -} - -#[no_mangle] -pub unsafe extern "C" fn dc_accounts_event_get_data2_str( - event: *mut dc_accounts_event_t, -) -> *mut libc::c_char { - if event.is_null() { - eprintln!("ignoring careless call to dc_accounts_event_get_data2_str()"); +pub unsafe extern "C" fn dc_accounts_get_next_event( + emitter: *mut dc_accounts_event_emitter_t, +) -> *mut dc_event_t { + if emitter.is_null() { return ptr::null_mut(); } + let emitter = &*emitter; - dc_event_get_data2_str(&mut (*event).event) -} - -#[no_mangle] -pub unsafe extern "C" fn dc_accounts_event_get_account_id(event: *mut dc_accounts_event_t) -> u32 { - if event.is_null() { - eprintln!("ignoring careless call to dc_accounts_event_get_account_id()"); - return 0; - } - - (*event).id + emitter + .recv_sync() + .map(|ev| Box::into_raw(Box::new(ev))) + .unwrap_or_else(ptr::null_mut) } diff --git a/src/accounts.rs b/src/accounts.rs index eb6e2f916..025c41144 100644 --- a/src/accounts.rs +++ b/src/accounts.rs @@ -13,6 +13,7 @@ use serde::{Deserialize, Serialize}; use crate::context::Context; use crate::error::Result; +use crate::events::Event; /// Account manager, that can handle multiple accounts in a single place. #[derive(Debug, Clone)] @@ -42,7 +43,7 @@ impl Accounts { let config = Config::new(os_name.clone(), dir).await?; let account_config = config.new_account(dir).await?; - Context::new(os_name, account_config.dbfile().into()) + Context::new(os_name, account_config.dbfile().into(), account_config.id) .await .context("failed to create default account")?; @@ -95,7 +96,7 @@ impl Accounts { let os_name = self.config.os_name().await; let account_config = self.config.new_account(&self.dir).await?; - let ctx = Context::new(os_name, account_config.dbfile().into()).await?; + let ctx = Context::new(os_name, account_config.dbfile().into(), account_config.id).await?; self.accounts.write().await.insert(account_config.id, ctx); Ok(account_config.id) @@ -151,9 +152,13 @@ impl Accounts { match res { Ok(_) => { - let ctx = - Context::with_blobdir(self.config.os_name().await, new_dbfile, new_blobdir) - .await?; + let ctx = Context::with_blobdir( + self.config.os_name().await, + new_dbfile, + new_blobdir, + account_config.id, + ) + .await?; self.accounts.write().await.insert(account_config.id, ctx); Ok(account_config.id) } @@ -250,13 +255,14 @@ impl EventEmitter { fn recv_poll(self: Pin<&Self>, _cx: &mut TaskContext<'_>) -> Poll> { for e in &*self.0 { if e.done.load(Ordering::Acquire) { + // skip emitters that are already done continue; } match e.emitter.try_recv() { - Ok(event) => return Poll::Ready(Some(Event { event, id: e.id })), + Ok(event) => return Poll::Ready(Some(event)), Err(async_std::sync::TryRecvError::Disconnected) => { - e.done.store(false, Ordering::Release); + e.done.store(true, Ordering::Release); } Err(async_std::sync::TryRecvError::Empty) => {} } @@ -276,13 +282,6 @@ struct EmitterWrapper { done: AtomicBool, } -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Event { - /// The id of the account that emitted the event. - pub id: u32, - pub event: crate::events::Event, -} - pub const CONFIG_NAME: &str = "accounts.toml"; pub const DB_NAME: &str = "dc.db"; @@ -347,7 +346,12 @@ impl Config { let cfg = &*self.inner.read().await; let mut accounts = HashMap::with_capacity(cfg.accounts.len()); for account_config in &cfg.accounts { - let ctx = Context::new(cfg.os_name.clone(), account_config.dbfile().into()).await?; + let ctx = Context::new( + cfg.os_name.clone(), + account_config.dbfile().into(), + account_config.id, + ) + .await?; accounts.insert(account_config.id, ctx); } @@ -504,7 +508,7 @@ mod tests { assert_eq!(accounts.config.get_selected_account().await, 1); let extern_dbfile: PathBuf = dir.path().join("other").into(); - let ctx = Context::new("my_os".into(), extern_dbfile.clone()) + let ctx = Context::new("my_os".into(), extern_dbfile.clone(), 0) .await .unwrap(); ctx.set_config(crate::config::Config::Addr, Some("me@mail.com")) diff --git a/src/blob.rs b/src/blob.rs index a6efe141b..3fc3028c0 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -15,7 +15,7 @@ use crate::config::Config; use crate::constants::*; use crate::context::Context; use crate::error::Error; -use crate::events::Event; +use crate::events::EventType; use crate::message; /// Represents a file in the blob directory. @@ -67,7 +67,7 @@ impl<'a> BlobObject<'a> { blobdir, name: format!("$BLOBDIR/{}", name), }; - context.emit_event(Event::NewBlobFile(blob.as_name().to_string())); + context.emit_event(EventType::NewBlobFile(blob.as_name().to_string())); Ok(blob) } @@ -155,7 +155,7 @@ impl<'a> BlobObject<'a> { blobdir: context.get_blobdir(), name: format!("$BLOBDIR/{}", name), }; - context.emit_event(Event::NewBlobFile(blob.as_name().to_string())); + context.emit_event(EventType::NewBlobFile(blob.as_name().to_string())); Ok(blob) } diff --git a/src/chat.rs b/src/chat.rs index 74af3f678..886a0aa60 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -17,7 +17,7 @@ use crate::context::Context; use crate::dc_tools::*; use crate::ephemeral::{delete_expired_messages, schedule_ephemeral_task, Timer as EphemeralTimer}; use crate::error::{bail, ensure, format_err, Error}; -use crate::events::Event; +use crate::events::EventType; use crate::job::{self, Action}; use crate::message::{self, InvalidMsgId, Message, MessageState, MsgId}; use crate::mimeparser::SystemMessage; @@ -185,7 +185,7 @@ impl ChatId { ) .await?; - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { msg_id: MsgId::new(0), chat_id: ChatId::new(0), }); @@ -242,7 +242,7 @@ impl ChatId { .execute("DELETE FROM chats WHERE id=?;", paramsv![self]) .await?; - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { msg_id: MsgId::new(0), chat_id: ChatId::new(0), }); @@ -268,7 +268,7 @@ impl ChatId { }; if changed { - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { chat_id: self, msg_id: MsgId::new(0), }); @@ -789,7 +789,7 @@ impl Chat { { emit_event!( context, - Event::ErrorSelfNotInGroup("Cannot send message; self not in group.".into()) + EventType::ErrorSelfNotInGroup("Cannot send message; self not in group.".into()) ); bail!("Cannot set message; self not in group."); } @@ -1146,7 +1146,7 @@ pub async fn create_by_msg_id(context: &Context, msg_id: MsgId) -> Result Result< } }; - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { chat_id: ChatId::new(0), msg_id: MsgId::new(0), }); @@ -1355,7 +1355,7 @@ pub async fn prepare_msg( msg.state = MessageState::OutPreparing; let msg_id = prepare_msg_common(context, chat_id, msg).await?; - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { chat_id: msg.chat_id, msg_id: msg.id, }); @@ -1530,7 +1530,7 @@ pub async fn send_msg_sync( match status { job::Status::Finished(Ok(_)) => { - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { chat_id: msg.chat_id, msg_id: msg.id, }); @@ -1558,13 +1558,13 @@ async fn send_msg_inner( if let Some(send_job) = prepare_send_msg(context, chat_id, msg).await? { job::add(context, send_job).await; - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { chat_id: msg.chat_id, msg_id: msg.id, }); if msg.param.exists(Param::SetLatitude) { - context.emit_event(Event::LocationChanged(Some(DC_CONTACT_ID_SELF))); + context.emit_event(EventType::LocationChanged(Some(DC_CONTACT_ID_SELF))); } } @@ -1665,7 +1665,7 @@ pub async fn get_chat_msgs( // On desktop chatlist is always shown on the side, // and it is important to update the last message shown // there. - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { msg_id: MsgId::new(0), chat_id: ChatId::new(0), }) @@ -1788,7 +1788,7 @@ pub async fn marknoticed_chat(context: &Context, chat_id: ChatId) -> Result<(), ) .await?; - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { chat_id: ChatId::new(0), msg_id: MsgId::new(0), }); @@ -1820,7 +1820,7 @@ pub async fn marknoticed_all_chats(context: &Context) -> Result<(), Error> { ) .await?; - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { msg_id: MsgId::new(0), chat_id: ChatId::new(0), }); @@ -1991,7 +1991,7 @@ pub async fn create_group_chat( chat_id.set_draft_raw(context, &mut draft_msg).await; } - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { msg_id: MsgId::new(0), chat_id: ChatId::new(0), }); @@ -2091,7 +2091,9 @@ pub(crate) async fn add_contact_to_chat_ex( /* we should respect this - whatever we send to the group, it gets discarded anyway! */ emit_event!( context, - Event::ErrorSelfNotInGroup("Cannot add contact to group; self not in group.".into()) + EventType::ErrorSelfNotInGroup( + "Cannot add contact to group; self not in group.".into() + ) ); bail!("can not add contact because our account is not part of it"); } @@ -2149,7 +2151,7 @@ pub(crate) async fn add_contact_to_chat_ex( msg.param.set_int(Param::Arg2, from_handshake.into()); msg.id = send_msg(context, chat_id, &mut msg).await?; } - context.emit_event(Event::ChatModified(chat_id)); + context.emit_event(EventType::ChatModified(chat_id)); Ok(true) } @@ -2311,7 +2313,7 @@ pub async fn set_muted( .await .is_ok() { - context.emit_event(Event::ChatModified(chat_id)); + context.emit_event(EventType::ChatModified(chat_id)); } else { bail!("Failed to set mute duration, chat might not exist -"); } @@ -2343,7 +2345,7 @@ pub async fn remove_contact_from_chat( if !is_contact_in_chat(context, chat_id, DC_CONTACT_ID_SELF).await { emit_event!( context, - Event::ErrorSelfNotInGroup( + EventType::ErrorSelfNotInGroup( "Cannot remove contact from chat; self not in group.".into() ) ); @@ -2391,7 +2393,7 @@ pub async fn remove_contact_from_chat( // removed it first, it would complicate the // check/encryption logic. success = remove_from_chat_contacts_table(context, chat_id, contact_id).await; - context.emit_event(Event::ChatModified(chat_id)); + context.emit_event(EventType::ChatModified(chat_id)); } } } @@ -2451,7 +2453,7 @@ pub async fn set_chat_name( } else if !is_contact_in_chat(context, chat_id, DC_CONTACT_ID_SELF).await { emit_event!( context, - Event::ErrorSelfNotInGroup("Cannot set chat name; self not in group".into()) + EventType::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! */ @@ -2481,12 +2483,12 @@ pub async fn set_chat_name( msg.param.set(Param::Arg, &chat.name); } msg.id = send_msg(context, chat_id, &mut msg).await?; - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { chat_id, msg_id: msg.id, }); } - context.emit_event(Event::ChatModified(chat_id)); + context.emit_event(EventType::ChatModified(chat_id)); success = true; } } @@ -2519,7 +2521,9 @@ pub async fn set_chat_profile_image( if !is_contact_in_chat(context, chat_id, DC_CONTACT_ID_SELF).await { emit_event!( context, - Event::ErrorSelfNotInGroup("Cannot set chat profile image; self not in group.".into()) + EventType::ErrorSelfNotInGroup( + "Cannot set chat profile image; self not in group.".into() + ) ); bail!("Failed to set profile image"); } @@ -2558,13 +2562,13 @@ pub async fn set_chat_profile_image( msg.id = send_msg(context, chat_id, &mut msg).await?; emit_event!( context, - Event::MsgsChanged { + EventType::MsgsChanged { chat_id, msg_id: msg.id } ); } - emit_event!(context, Event::ChatModified(chat_id)); + emit_event!(context, EventType::ChatModified(chat_id)); Ok(()) } @@ -2648,7 +2652,7 @@ pub async fn forward_msgs( } } for (chat_id, msg_id) in created_chats.iter().zip(created_msgs.iter()) { - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { chat_id: *chat_id, msg_id: *msg_id, }); @@ -2774,9 +2778,9 @@ pub async fn add_device_msg_with_importance( if !msg_id.is_unset() { if important { - context.emit_event(Event::IncomingMsg { chat_id, msg_id }); + context.emit_event(EventType::IncomingMsg { chat_id, msg_id }); } else { - context.emit_event(Event::MsgsChanged { chat_id, msg_id }); + context.emit_event(EventType::MsgsChanged { chat_id, msg_id }); } } @@ -2864,7 +2868,7 @@ pub(crate) async fn add_info_msg(context: &Context, chat_id: ChatId, text: impl .get_rowid(context, "msgs", "rfc724_mid", &rfc724_mid) .await .unwrap_or_default(); - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { chat_id, msg_id: MsgId::new(row_id), }); diff --git a/src/config.rs b/src/config.rs index 6434f560b..4b9524e50 100644 --- a/src/config.rs +++ b/src/config.rs @@ -8,7 +8,7 @@ use crate::chat::ChatId; use crate::constants::DC_VERSION_STR; use crate::context::Context; use crate::dc_tools::*; -use crate::events::Event; +use crate::events::EventType; use crate::message::MsgId; use crate::mimefactory::RECOMMENDED_FILE_SIZE; use crate::stock::StockMessage; @@ -226,7 +226,7 @@ impl Context { Config::DeleteDeviceAfter => { let ret = self.sql.set_raw_config(self, key, value).await; // Force chatlist reload to delete old messages immediately. - self.emit_event(Event::MsgsChanged { + self.emit_event(EventType::MsgsChanged { msg_id: MsgId::new(0), chat_id: ChatId::new(0), }); diff --git a/src/configure/mod.rs b/src/configure/mod.rs index fbe314b4f..1f0120c99 100644 --- a/src/configure/mod.rs +++ b/src/configure/mod.rs @@ -28,7 +28,7 @@ macro_rules! progress { $progress <= 1000, "value in range 0..1000 expected with: 0=error, 1..999=progress, 1000=success" ); - $context.emit_event($crate::events::Event::ConfigureProgress($progress)); + $context.emit_event($crate::events::EventType::ConfigureProgress($progress)); }; } diff --git a/src/contact.rs b/src/contact.rs index 1fe9451fc..42acdc371 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -13,7 +13,7 @@ use crate::constants::*; use crate::context::Context; use crate::dc_tools::*; use crate::error::{bail, ensure, format_err, Result}; -use crate::events::Event; +use crate::events::EventType; use crate::key::{DcKey, SignedPublicKey}; use crate::login_param::LoginParam; use crate::message::{MessageState, MsgId}; @@ -245,7 +245,7 @@ impl Contact { let (contact_id, sth_modified) = Contact::add_or_lookup(context, name, addr, Origin::ManuallyCreated).await?; let blocked = Contact::is_blocked_load(context, contact_id).await; - context.emit_event(Event::ContactsChanged( + context.emit_event(EventType::ContactsChanged( if sth_modified == Modifier::Created { Some(contact_id) } else { @@ -273,7 +273,7 @@ impl Contact { .await .is_ok() { - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { chat_id: ChatId::new(0), msg_id: MsgId::new(0), }); @@ -533,7 +533,7 @@ impl Contact { } } if modify_cnt > 0 { - context.emit_event(Event::ContactsChanged(None)); + context.emit_event(EventType::ContactsChanged(None)); } Ok(modify_cnt) @@ -784,7 +784,7 @@ impl Contact { .await { Ok(_) => { - context.emit_event(Event::ContactsChanged(None)); + context.emit_event(EventType::ContactsChanged(None)); return Ok(()); } Err(err) => { @@ -1093,7 +1093,7 @@ async fn set_block_contact(context: &Context, contact_id: u32, new_blocking: boo paramsv![new_blocking, 100, contact_id as i32], ).await.is_ok() { Contact::mark_noticed(context, contact_id).await; - context.emit_event(Event::ContactsChanged(None)); + context.emit_event(EventType::ContactsChanged(None)); } } } @@ -1143,7 +1143,7 @@ pub(crate) async fn set_profile_image( }; if changed { contact.update_param(context).await?; - context.emit_event(Event::ContactsChanged(Some(contact_id))); + context.emit_event(EventType::ContactsChanged(Some(contact_id))); } Ok(()) } diff --git a/src/context.rs b/src/context.rs index db3f8d8c7..c527f39d6 100644 --- a/src/context.rs +++ b/src/context.rs @@ -14,7 +14,7 @@ use crate::constants::*; use crate::contact::*; use crate::dc_tools::duration_to_str; use crate::error::*; -use crate::events::{Event, EventEmitter, Events}; +use crate::events::{Event, EventEmitter, EventType, Events}; use crate::key::{DcKey, SignedPublicKey}; use crate::login_param::LoginParam; use crate::lot::Lot; @@ -59,6 +59,9 @@ pub struct InnerContext { pub(crate) scheduler: RwLock, pub(crate) ephemeral_task: RwLock>>, + /// Id for this context on the current device. + pub(crate) id: u32, + creation_time: SystemTime, } @@ -86,7 +89,7 @@ pub fn get_info() -> BTreeMap<&'static str, String> { impl Context { /// Creates new context. - pub async fn new(os_name: String, dbfile: PathBuf) -> Result { + pub async fn new(os_name: String, dbfile: PathBuf, id: u32) -> Result { // pretty_env_logger::try_init_timed().ok(); let mut blob_fname = OsString::new(); @@ -96,13 +99,14 @@ impl Context { if !blobdir.exists().await { async_std::fs::create_dir_all(&blobdir).await?; } - Context::with_blobdir(os_name, dbfile, blobdir).await + Context::with_blobdir(os_name, dbfile, blobdir, id).await } - pub async fn with_blobdir( + pub(crate) async fn with_blobdir( os_name: String, dbfile: PathBuf, blobdir: PathBuf, + id: u32, ) -> Result { ensure!( blobdir.is_dir().await, @@ -111,6 +115,7 @@ impl Context { ); let inner = InnerContext { + id, blobdir, dbfile, os_name: Some(os_name), @@ -188,8 +193,11 @@ impl Context { } /// Emits a single event. - pub fn emit_event(&self, event: Event) { - self.events.emit(event); + pub fn emit_event(&self, event: EventType) { + self.events.emit(Event { + id: self.id, + typ: event, + }); } /// Get the next queued event. @@ -517,7 +525,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("FakeOs".into(), dbfile.into()).await; + let res = Context::new("FakeOs".into(), dbfile.into(), 0).await; assert!(res.is_err()); } @@ -532,7 +540,9 @@ mod tests { async fn test_blobdir_exists() { let tmp = tempfile::tempdir().unwrap(); let dbfile = tmp.path().join("db.sqlite"); - Context::new("FakeOS".into(), dbfile.into()).await.unwrap(); + Context::new("FakeOS".into(), dbfile.into(), 0) + .await + .unwrap(); let blobdir = tmp.path().join("db.sqlite-blobs"); assert!(blobdir.is_dir()); } @@ -543,7 +553,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("FakeOS".into(), dbfile.into()).await; + let res = Context::new("FakeOS".into(), dbfile.into(), 0).await; assert!(res.is_err()); } @@ -553,7 +563,9 @@ mod tests { let subdir = tmp.path().join("subdir"); let dbfile = subdir.join("db.sqlite"); let dbfile2 = dbfile.clone(); - Context::new("FakeOS".into(), dbfile.into()).await.unwrap(); + Context::new("FakeOS".into(), dbfile.into(), 0) + .await + .unwrap(); assert!(subdir.is_dir()); assert!(dbfile2.is_file()); } @@ -563,7 +575,7 @@ mod tests { let tmp = tempfile::tempdir().unwrap(); let dbfile = tmp.path().join("db.sqlite"); let blobdir = PathBuf::new(); - let res = Context::with_blobdir("FakeOS".into(), dbfile.into(), blobdir.into()).await; + let res = Context::with_blobdir("FakeOS".into(), dbfile.into(), blobdir.into(), 0).await; assert!(res.is_err()); } @@ -572,7 +584,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("FakeOS".into(), dbfile.into(), blobdir.into()).await; + let res = Context::with_blobdir("FakeOS".into(), dbfile.into(), blobdir.into(), 0).await; assert!(res.is_err()); } diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 4b01ac1d5..8055d5892 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -12,7 +12,7 @@ use crate::context::Context; use crate::dc_tools::*; use crate::ephemeral::{stock_ephemeral_timer_changed, Timer as EphemeralTimer}; use crate::error::{bail, ensure, format_err, Result}; -use crate::events::Event; +use crate::events::EventType; use crate::headerdef::HeaderDef; use crate::job::{self, Action}; use crate::message::{self, MessageState, MessengerMessage, MsgId}; @@ -93,8 +93,8 @@ pub async fn dc_receive_imf( if let Some(create_event_to_send) = create_event_to_send { for (chat_id, msg_id) in created_db_entries { let event = match create_event_to_send { - CreateEvent::MsgsChanged => Event::MsgsChanged { msg_id, chat_id }, - CreateEvent::IncomingMsg => Event::IncomingMsg { msg_id, chat_id }, + CreateEvent::MsgsChanged => EventType::MsgsChanged { msg_id, chat_id }, + CreateEvent::IncomingMsg => EventType::IncomingMsg { msg_id, chat_id }, }; context.emit_event(event); } @@ -206,7 +206,7 @@ pub async fn dc_receive_imf( .await { Ok(()) => { - context.emit_event(Event::ChatModified(chat_id)); + context.emit_event(EventType::ChatModified(chat_id)); } Err(err) => { warn!(context, "reveive_imf cannot update profile image: {}", err); @@ -935,7 +935,7 @@ async fn save_locations( } } if send_event { - context.emit_event(Event::LocationChanged(Some(from_id))); + context.emit_event(EventType::LocationChanged(Some(from_id))); } } @@ -1239,7 +1239,7 @@ async fn create_or_lookup_group( .await .is_ok() { - context.emit_event(Event::ChatModified(chat_id)); + context.emit_event(EventType::ChatModified(chat_id)); } } } @@ -1298,7 +1298,7 @@ async fn create_or_lookup_group( } if send_EVENT_CHAT_MODIFIED { - context.emit_event(Event::ChatModified(chat_id)); + context.emit_event(EventType::ChatModified(chat_id)); } Ok((chat_id, chat_id_blocked)) } @@ -1435,7 +1435,7 @@ async fn create_or_lookup_adhoc_group( chat::add_to_chat_contacts_table(context, new_chat_id, member_id).await; } - context.emit_event(Event::ChatModified(new_chat_id)); + context.emit_event(EventType::ChatModified(new_chat_id)); Ok((new_chat_id, create_blocked)) } diff --git a/src/dc_tools.rs b/src/dc_tools.rs index 1d887edde..f937a0ef9 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -15,7 +15,7 @@ use rand::{thread_rng, Rng}; use crate::context::Context; use crate::error::{bail, Error}; -use crate::events::Event; +use crate::events::EventType; pub(crate) fn dc_exactly_one_bit_set(v: i32) -> bool { 0 != v && 0 == v & (v - 1) @@ -286,7 +286,7 @@ pub(crate) async fn dc_delete_file(context: &Context, path: impl AsRef) -> let dpath = format!("{}", path.as_ref().to_string_lossy()); match fs::remove_file(path_abs).await { Ok(_) => { - context.emit_event(Event::DeletedBlobFile(dpath)); + context.emit_event(EventType::DeletedBlobFile(dpath)); true } Err(err) => { diff --git a/src/ephemeral.rs b/src/ephemeral.rs index 0fb311ae7..1bfac1f30 100644 --- a/src/ephemeral.rs +++ b/src/ephemeral.rs @@ -63,7 +63,7 @@ use crate::constants::{ use crate::context::Context; use crate::dc_tools::time; use crate::error::{ensure, Error}; -use crate::events::Event; +use crate::events::EventType; use crate::message::{Message, MessageState, MsgId}; use crate::mimeparser::SystemMessage; use crate::sql; @@ -177,7 +177,7 @@ impl ChatId { ) .await?; - context.emit_event(Event::ChatEphemeralTimerModified { + context.emit_event(EventType::ChatEphemeralTimerModified { chat_id: self, timer, }); @@ -379,7 +379,7 @@ pub async fn schedule_ephemeral_task(context: &Context) { async_std::task::sleep(duration).await; emit_event!( context1, - Event::MsgsChanged { + EventType::MsgsChanged { chat_id: ChatId::new(0), msg_id: MsgId::new(0) } @@ -390,7 +390,7 @@ pub async fn schedule_ephemeral_task(context: &Context) { // Emit event immediately emit_event!( context, - Event::MsgsChanged { + EventType::MsgsChanged { chat_id: ChatId::new(0), msg_id: MsgId::new(0) } diff --git a/src/events.rs b/src/events.rs index bd8605725..f51929790 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,5 +1,7 @@ //! # Events specification +use std::ops::Deref; + use async_std::path::PathBuf; use async_std::sync::{channel, Receiver, Sender, TrySendError}; use strum::EnumProperty; @@ -65,7 +67,21 @@ impl EventEmitter { } } -impl Event { +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Event { + pub id: u32, + pub typ: EventType, +} + +impl Deref for Event { + type Target = EventType; + + fn deref(&self) -> &EventType { + &self.typ + } +} + +impl EventType { /// Returns the corresponding Event id. pub fn as_id(&self) -> i32 { self.get_str("id") @@ -76,7 +92,7 @@ impl Event { } #[derive(Debug, Clone, PartialEq, Eq, EnumProperty)] -pub enum Event { +pub enum EventType { /// 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. diff --git a/src/imap/mod.rs b/src/imap/mod.rs index c597c629f..ef4ea8b09 100644 --- a/src/imap/mod.rs +++ b/src/imap/mod.rs @@ -19,7 +19,7 @@ use crate::context::Context; use crate::dc_receive_imf::{ dc_receive_imf, from_field_to_contact_id, is_msgrmsg_rfc724_mid_in_list, }; -use crate::events::Event; +use crate::events::EventType; use crate::headerdef::{HeaderDef, HeaderDefMap}; use crate::job::{self, Action}; use crate::login_param::{CertificateChecks, LoginParam}; @@ -284,7 +284,7 @@ impl Imap { .await }; // IMAP connection failures are reported to users - emit_event!(context, Event::ErrorNetwork(message)); + emit_event!(context, EventType::ErrorNetwork(message)); return Err(Error::ConnectionFailed(err.to_string())); } }; @@ -307,7 +307,7 @@ impl Imap { .await; warn!(context, "{} ({})", message, err); - emit_event!(context, Event::ErrorNetwork(message.clone())); + emit_event!(context, EventType::ErrorNetwork(message.clone())); let lock = context.wrong_pw_warning_mutex.lock().await; if self.login_failed_once @@ -445,7 +445,7 @@ impl Imap { self.connected = true; emit_event!( context, - Event::ImapConnected(format!( + EventType::ImapConnected(format!( "IMAP-LOGIN as {}, capabilities: {}", lp.mail_user, caps_list, )) @@ -888,7 +888,7 @@ impl Imap { Ok(_) => { emit_event!( context, - Event::ImapMessageMoved(format!( + EventType::ImapMessageMoved(format!( "IMAP Message {} moved to {}", display_folder_id, dest_folder )) @@ -932,7 +932,7 @@ impl Imap { warn!(context, "Cannot mark {} as \"Deleted\" after copy.", uid); emit_event!( context, - Event::ImapMessageMoved(format!( + EventType::ImapMessageMoved(format!( "IMAP Message {} copied to {} (delete FAILED)", display_folder_id, dest_folder )) @@ -942,7 +942,7 @@ impl Imap { self.config.selected_folder_needs_expunge = true; emit_event!( context, - Event::ImapMessageMoved(format!( + EventType::ImapMessageMoved(format!( "IMAP Message {} copied to {} (delete successfull)", display_folder_id, dest_folder )) @@ -1142,7 +1142,7 @@ impl Imap { } else { emit_event!( context, - Event::ImapMessageDeleted(format!( + EventType::ImapMessageDeleted(format!( "IMAP Message {} marked as deleted [{}]", display_imap_id, message_id )) @@ -1316,7 +1316,7 @@ impl Imap { self.config.selected_folder_needs_expunge = true; match self.select_folder::(context, None).await { Ok(()) => { - emit_event!(context, Event::ImapFolderEmptied(folder.to_string())); + emit_event!(context, EventType::ImapFolderEmptied(folder.to_string())); } Err(err) => { error!(context, "expunge failed {}: {:?}", folder, err); diff --git a/src/imex.rs b/src/imex.rs index c4fbcfaf2..4b2f7c67e 100644 --- a/src/imex.rs +++ b/src/imex.rs @@ -16,7 +16,7 @@ use crate::context::Context; use crate::dc_tools::*; use crate::e2ee; use crate::error::*; -use crate::events::Event; +use crate::events::EventType; use crate::key::{self, DcKey, DcSecretKey, SignedPublicKey, SignedSecretKey}; use crate::message::{Message, MsgId}; use crate::mimeparser::SystemMessage; @@ -369,7 +369,7 @@ async fn imex_inner( ensure!(param.is_some(), "No Import/export dir/file given."); info!(context, "Import/export process started."); - context.emit_event(Event::ImexProgress(10)); + context.emit_event(EventType::ImexProgress(10)); ensure!(context.sql.is_open().await, "Database not opened."); @@ -393,11 +393,11 @@ async fn imex_inner( match success { Ok(()) => { info!(context, "IMEX successfully completed"); - context.emit_event(Event::ImexProgress(1000)); + context.emit_event(EventType::ImexProgress(1000)); Ok(()) } Err(err) => { - context.emit_event(Event::ImexProgress(0)); + context.emit_event(EventType::ImexProgress(0)); bail!("IMEX FAILED to complete: {}", err); } } @@ -487,7 +487,7 @@ async fn import_backup(context: &Context, backup_to_import: impl AsRef) -> if permille > 990 { permille = 990 } - context.emit_event(Event::ImexProgress(permille)); + context.emit_event(EventType::ImexProgress(permille)); if file_blob.is_empty() { continue; } @@ -563,7 +563,7 @@ async fn export_backup(context: &Context, dir: impl AsRef) -> Result<()> { dest_sql .set_raw_config_int(context, "backup_time", now as i32) .await?; - context.emit_event(Event::ImexFileWritten(dest_path_filename)); + context.emit_event(EventType::ImexFileWritten(dest_path_filename)); Ok(()) } }; @@ -602,7 +602,7 @@ async fn add_files_to_export(context: &Context, sql: &Sql) -> Result<()> { } processed_files_cnt += 1; let permille = max(min(processed_files_cnt * 1000 / total_files_cnt, 990), 10); - context.emit_event(Event::ImexProgress(permille)); + context.emit_event(EventType::ImexProgress(permille)); let name_f = entry.file_name(); let name = name_f.to_string_lossy(); @@ -769,7 +769,7 @@ where if res.is_err() { error!(context, "Cannot write key to {}", file_name.display()); } else { - context.emit_event(Event::ImexFileWritten(file_name)); + context.emit_event(EventType::ImexFileWritten(file_name)); } res } diff --git a/src/job.rs b/src/job.rs index 171cd33d0..26e078977 100644 --- a/src/job.rs +++ b/src/job.rs @@ -23,7 +23,7 @@ use crate::context::Context; use crate::dc_tools::*; use crate::ephemeral::load_imap_deletion_msgid; use crate::error::{bail, ensure, format_err, Error, Result}; -use crate::events::Event; +use crate::events::EventType; use crate::imap::*; use crate::location; use crate::login_param::LoginParam; @@ -737,7 +737,7 @@ async fn set_delivered(context: &Context, msg_id: MsgId) { ) .await .unwrap_or_default(); - context.emit_event(Event::MsgDelivered { chat_id, msg_id }); + context.emit_event(EventType::MsgDelivered { chat_id, msg_id }); } /// Constructs a job for sending a message. diff --git a/src/location.rs b/src/location.rs index dabd54f5d..c09cbd957 100644 --- a/src/location.rs +++ b/src/location.rs @@ -9,7 +9,7 @@ use crate::constants::*; use crate::context::*; use crate::dc_tools::*; use crate::error::{ensure, Error}; -use crate::events::Event; +use crate::events::EventType; use crate::job::{self, Job}; use crate::message::{Message, MsgId}; use crate::mimeparser::SystemMessage; @@ -227,7 +227,7 @@ pub async fn send_locations_to_chat(context: &Context, chat_id: ChatId, seconds: .await; chat::add_info_msg(context, chat_id, stock_str).await; } - context.emit_event(Event::ChatModified(chat_id)); + context.emit_event(EventType::ChatModified(chat_id)); if 0 != seconds { schedule_maybe_send_locations(context, false).await; job::add( @@ -301,7 +301,7 @@ pub async fn set(context: &Context, latitude: f64, longitude: f64, accuracy: f64 } } if continue_streaming { - context.emit_event(Event::LocationChanged(Some(DC_CONTACT_ID_SELF))); + context.emit_event(EventType::LocationChanged(Some(DC_CONTACT_ID_SELF))); }; schedule_maybe_send_locations(context, false).await; } @@ -381,7 +381,7 @@ pub async fn delete_all(context: &Context) -> Result<(), Error> { .sql .execute("DELETE FROM locations;", paramsv![]) .await?; - context.emit_event(Event::LocationChanged(None)); + context.emit_event(EventType::LocationChanged(None)); Ok(()) } @@ -715,7 +715,7 @@ pub(crate) async fn job_maybe_send_locations_ended( .stock_system_msg(StockMessage::MsgLocationDisabled, "", "", 0) .await; chat::add_info_msg(context, chat_id, stock_str).await; - context.emit_event(Event::ChatModified(chat_id)); + context.emit_event(EventType::ChatModified(chat_id)); } } job::Status::Finished(Ok(())) diff --git a/src/log.rs b/src/log.rs index 9b253b93d..bcc9d1d43 100644 --- a/src/log.rs +++ b/src/log.rs @@ -11,7 +11,7 @@ macro_rules! info { file = file!(), line = line!(), msg = &formatted); - emit_event!($ctx, $crate::Event::Info(full)); + emit_event!($ctx, $crate::EventType::Info(full)); }}; } @@ -26,7 +26,7 @@ macro_rules! warn { file = file!(), line = line!(), msg = &formatted); - emit_event!($ctx, $crate::Event::Warning(full)); + emit_event!($ctx, $crate::EventType::Warning(full)); }}; } @@ -37,7 +37,7 @@ macro_rules! error { }; ($ctx:expr, $msg:expr, $($args:expr),* $(,)?) => {{ let formatted = format!($msg, $($args),*); - emit_event!($ctx, $crate::Event::Error(formatted)); + emit_event!($ctx, $crate::EventType::Error(formatted)); }}; } @@ -48,7 +48,7 @@ macro_rules! error_network { }; ($ctx:expr, $msg:expr, $($args:expr),* $(,)?) => {{ let formatted = format!($msg, $($args),*); - emit_event!($ctx, $crate::Event::ErrorNetwork(formatted)); + emit_event!($ctx, $crate::EventType::ErrorNetwork(formatted)); }}; } diff --git a/src/message.rs b/src/message.rs index c553ae532..dbd6ad396 100644 --- a/src/message.rs +++ b/src/message.rs @@ -12,7 +12,7 @@ use crate::contact::*; use crate::context::*; use crate::dc_tools::*; use crate::error::{ensure, Error}; -use crate::events::Event; +use crate::events::EventType; use crate::job::{self, Action}; use crate::lot::{Lot, LotState, Meaning}; use crate::mimeparser::{FailureReport, SystemMessage}; @@ -1118,7 +1118,7 @@ pub async fn delete_msgs(context: &Context, msg_ids: &[MsgId]) { } if !msg_ids.is_empty() { - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { chat_id: ChatId::new(0), msg_id: MsgId::new(0), }); @@ -1209,7 +1209,7 @@ pub async fn markseen_msgs(context: &Context, msg_ids: Vec) -> bool { } if send_event { - context.emit_event(Event::MsgsChanged { + context.emit_event(EventType::MsgsChanged { chat_id: ChatId::new(0), msg_id: MsgId::new(0), }); @@ -1376,7 +1376,7 @@ pub async fn set_msg_failed(context: &Context, msg_id: MsgId, error: Option context.emit_event(Event::MsgFailed { + Ok(_) => context.emit_event(EventType::MsgFailed { chat_id: msg.chat_id, msg_id, }), @@ -1551,7 +1551,7 @@ pub(crate) async fn handle_ndn( .await, ) .await; - context.emit_event(Event::ChatModified(chat_id)); + context.emit_event(EventType::ChatModified(chat_id)); } } } diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 7016e743c..c51be5bb7 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -16,7 +16,7 @@ use crate::dc_tools::*; use crate::dehtml::dehtml; use crate::e2ee; use crate::error::{bail, Result}; -use crate::events::Event; +use crate::events::EventType; use crate::headerdef::{HeaderDef, HeaderDefMap}; use crate::key::Fingerprint; use crate::location; @@ -1001,7 +1001,7 @@ impl MimeMessage { if let Some((chat_id, msg_id)) = message::handle_mdn(context, from_id, original_message_id, sent_timestamp).await { - context.emit_event(Event::MsgRead { chat_id, msg_id }); + context.emit_event(EventType::MsgRead { chat_id, msg_id }); } } } diff --git a/src/securejoin.rs b/src/securejoin.rs index 200791984..5df5f65cb 100644 --- a/src/securejoin.rs +++ b/src/securejoin.rs @@ -12,7 +12,7 @@ use crate::contact::*; use crate::context::Context; use crate::e2ee::*; use crate::error::{bail, Error}; -use crate::events::Event; +use crate::events::EventType; use crate::headerdef::HeaderDef; use crate::key::{DcKey, Fingerprint, SignedPublicKey}; use crate::lot::LotState; @@ -32,7 +32,7 @@ macro_rules! joiner_progress { $progress >= 0 && $progress <= 1000, "value in range 0..1000 expected with: 0=error, 1..999=progress, 1000=success" ); - $context.emit_event($crate::events::Event::SecurejoinJoinerProgress { + $context.emit_event($crate::events::EventType::SecurejoinJoinerProgress { contact_id: $contact_id, progress: $progress, }); @@ -45,7 +45,7 @@ macro_rules! inviter_progress { $progress >= 0 && $progress <= 1000, "value in range 0..1000 expected with: 0=error, 1..999=progress, 1000=success" ); - $context.emit_event($crate::events::Event::SecurejoinInviterProgress { + $context.emit_event($crate::events::EventType::SecurejoinInviterProgress { contact_id: $contact_id, progress: $progress, }); @@ -653,7 +653,7 @@ pub(crate) async fn handle_securejoin_handshake( Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinInvited).await; info!(context, "Auth verified.",); secure_connection_established(context, contact_chat_id).await; - emit_event!(context, Event::ContactsChanged(Some(contact_id))); + emit_event!(context, EventType::ContactsChanged(Some(contact_id))); inviter_progress!(context, contact_id, 600); if join_vg { // the vg-member-added message is special: @@ -773,7 +773,7 @@ pub(crate) async fn handle_securejoin_handshake( return Ok(abort_retval); } Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinJoined).await; - emit_event!(context, Event::ContactsChanged(None)); + emit_event!(context, EventType::ContactsChanged(None)); let cg_member_added = mime_message .get(HeaderDef::ChatGroupMemberAdded) .map(|s| s.as_str()) @@ -960,7 +960,7 @@ async fn secure_connection_established(context: &Context, contact_chat_id: ChatI .stock_string_repl_str(StockMessage::ContactVerified, addr) .await; chat::add_info_msg(context, contact_chat_id, msg).await; - emit_event!(context, Event::ChatModified(contact_chat_id)); + emit_event!(context, EventType::ChatModified(contact_chat_id)); } async fn could_not_establish_secure_connection( @@ -1073,7 +1073,7 @@ pub async fn handle_degrade_event( .await; chat::add_info_msg(context, contact_chat_id, msg).await; - emit_event!(context, Event::ChatModified(contact_chat_id)); + emit_event!(context, EventType::ChatModified(contact_chat_id)); } } Ok(()) diff --git a/src/smtp/mod.rs b/src/smtp/mod.rs index 2e4ad6e57..05707ecac 100644 --- a/src/smtp/mod.rs +++ b/src/smtp/mod.rs @@ -9,7 +9,7 @@ use async_smtp::*; use crate::constants::*; use crate::context::Context; -use crate::events::Event; +use crate::events::EventType; use crate::login_param::{dc_build_tls, CertificateChecks, LoginParam}; use crate::oauth2::*; use crate::provider::get_provider_info; @@ -102,7 +102,7 @@ impl Smtp { } if lp.send_server.is_empty() || lp.send_port == 0 { - context.emit_event(Event::ErrorNetwork("SMTP bad parameters.".into())); + context.emit_event(EventType::ErrorNetwork("SMTP bad parameters.".into())); return Err(Error::BadParameters); } @@ -187,14 +187,14 @@ impl Smtp { ) .await; - emit_event!(context, Event::ErrorNetwork(message)); + emit_event!(context, EventType::ErrorNetwork(message)); return Err(Error::ConnectionFailure(err)); } self.transport = Some(trans); self.last_success = Some(SystemTime::now()); - context.emit_event(Event::SmtpConnected(format!( + context.emit_event(EventType::SmtpConnected(format!( "SMTP-LOGIN as {} ok", lp.send_user, ))); diff --git a/src/smtp/send.rs b/src/smtp/send.rs index 821636549..c4b06745a 100644 --- a/src/smtp/send.rs +++ b/src/smtp/send.rs @@ -4,7 +4,7 @@ use super::Smtp; use async_smtp::*; use crate::context::Context; -use crate::events::Event; +use crate::events::EventType; use std::time::Duration; pub type Result = std::result::Result; @@ -55,7 +55,7 @@ impl Smtp { .await .map_err(Error::SendError)?; - context.emit_event(Event::SmtpMessageSent(format!( + context.emit_event(EventType::SmtpMessageSent(format!( "Message len={} was smtp-sent to {}", message_len_bytes, recipients_display ))); diff --git a/src/test_utils.rs b/src/test_utils.rs index ec3f6069d..cccd7548a 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -27,9 +27,14 @@ impl TestContext { /// /// [Context]: crate::context::Context pub async fn new() -> Self { + use rand::Rng; + let dir = tempdir().unwrap(); let dbfile = dir.path().join("db.sqlite"); - let ctx = Context::new("FakeOS".into(), dbfile.into()).await.unwrap(); + let id = rand::thread_rng().gen(); + let ctx = Context::new("FakeOS".into(), dbfile.into(), id) + .await + .unwrap(); Self { ctx, dir } } diff --git a/tests/stress.rs b/tests/stress.rs index ee00e713f..09ab1924e 100644 --- a/tests/stress.rs +++ b/tests/stress.rs @@ -99,9 +99,14 @@ struct TestContext { } async fn create_test_context() -> TestContext { + use rand::Rng; + let dir = tempdir().unwrap(); let dbfile = dir.path().join("db.sqlite"); - let ctx = Context::new("FakeOs".into(), dbfile.into()).await.unwrap(); + let id = rand::thread_rng().gen(); + let ctx = Context::new("FakeOs".into(), dbfile.into(), id) + .await + .unwrap(); TestContext { ctx, dir } }