Skip to content

Commit 315fc00

Browse files
committed
feat: Add EventType::CallMissed and emit it for missed calls (#7840)
Before, `CallEnded` was emitted for missed calls, or, if a call arrives already being stale, `IncomingMsg`. Having only one event type for missed calls should simplify handling them in the apps.
1 parent 5f84be7 commit 315fc00

5 files changed

Lines changed: 77 additions & 12 deletions

File tree

deltachat-ffi/src/lib.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,7 @@ pub unsafe extern "C" fn dc_event_get_id(event: *mut dc_event_t) -> libc::c_int
558558
EventType::IncomingCallAccepted { .. } => 2560,
559559
EventType::OutgoingCallAccepted { .. } => 2570,
560560
EventType::CallEnded { .. } => 2580,
561+
EventType::CallMissed { .. } => 2590,
561562
EventType::TransportsModified => 2600,
562563
#[allow(unreachable_patterns)]
563564
#[cfg(test)]
@@ -628,6 +629,7 @@ pub unsafe extern "C" fn dc_event_get_data1_int(event: *mut dc_event_t) -> libc:
628629
| EventType::IncomingCallAccepted { msg_id, .. }
629630
| EventType::OutgoingCallAccepted { msg_id, .. }
630631
| EventType::CallEnded { msg_id, .. } => msg_id.to_u32() as libc::c_int,
632+
EventType::CallMissed { msg_id, .. } => msg_id.to_u32() as libc::c_int,
631633
EventType::ChatlistItemChanged { chat_id } => {
632634
chat_id.unwrap_or_default().to_u32() as libc::c_int
633635
}
@@ -682,6 +684,7 @@ pub unsafe extern "C" fn dc_event_get_data2_int(event: *mut dc_event_t) -> libc:
682684
| EventType::IncomingCallAccepted { .. }
683685
| EventType::OutgoingCallAccepted { .. }
684686
| EventType::CallEnded { .. }
687+
| EventType::CallMissed { .. }
685688
| EventType::EventChannelOverflow { .. }
686689
| EventType::TransportsModified => 0,
687690
EventType::MsgsChanged { msg_id, .. }
@@ -796,7 +799,9 @@ pub unsafe extern "C" fn dc_event_get_data2_str(event: *mut dc_event_t) -> *mut
796799
let data2 = accept_call_info.to_c_string().unwrap_or_default();
797800
data2.into_raw()
798801
}
799-
EventType::CallEnded { .. } | EventType::EventChannelOverflow { .. } => ptr::null_mut(),
802+
EventType::CallEnded { .. }
803+
| EventType::CallMissed { .. }
804+
| EventType::EventChannelOverflow { .. } => ptr::null_mut(),
800805
EventType::ConfigureProgress { comment, .. } => {
801806
if let Some(comment) = comment {
802807
comment.to_c_string().unwrap_or_default().into_raw()

deltachat-jsonrpc/src/api/types/events.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,14 @@ pub enum EventType {
461461
chat_id: u32,
462462
},
463463

464+
/// Call missed.
465+
CallMissed {
466+
/// ID of the info message referring to the call.
467+
msg_id: u32,
468+
/// ID of the chat which the message belongs to.
469+
chat_id: u32,
470+
},
471+
464472
/// One or more transports has changed.
465473
///
466474
/// UI should update the list.
@@ -651,6 +659,10 @@ impl From<CoreEventType> for EventType {
651659
msg_id: msg_id.to_u32(),
652660
chat_id: chat_id.to_u32(),
653661
},
662+
CoreEventType::CallMissed { msg_id, chat_id } => CallMissed {
663+
msg_id: msg_id.to_u32(),
664+
chat_id: chat_id.to_u32(),
665+
},
654666
CoreEventType::TransportsModified => TransportsModified,
655667

656668
#[allow(unreachable_patterns)]

src/calls.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -328,20 +328,19 @@ impl Context {
328328
return Ok(());
329329
};
330330
if !call.is_accepted() && !call.is_ended() {
331+
let (msg_id, chat_id) = (call_id, call.msg.chat_id);
331332
if call.is_incoming() {
332333
call.mark_as_canceled(&context).await?;
333334
let missed_call_str = stock_str::missed_call(&context).await;
334335
call.update_text(&context, &missed_call_str).await?;
336+
context.emit_event(EventType::CallMissed { msg_id, chat_id });
335337
} else {
336338
call.mark_as_ended(&context).await?;
337339
let canceled_call_str = stock_str::canceled_call(&context).await;
338340
call.update_text(&context, &canceled_call_str).await?;
341+
context.emit_event(EventType::CallEnded { msg_id, chat_id });
339342
}
340343
context.emit_msgs_changed(call.msg.chat_id, call_id);
341-
context.emit_event(EventType::CallEnded {
342-
msg_id: call.msg.id,
343-
chat_id: call.msg.chat_id,
344-
});
345344
}
346345
Ok(())
347346
}
@@ -362,7 +361,10 @@ impl Context {
362361
if call.is_stale() {
363362
let missed_call_str = stock_str::missed_call(self).await;
364363
call.update_text(self, &missed_call_str).await?;
365-
self.emit_incoming_msg(call.msg.chat_id, call_id); // notify missed call
364+
// TODO: Don't notify for blocked contacts
365+
let (msg_id, chat_id) = (call_id, call.msg.chat_id);
366+
self.emit_event(EventType::CallMissed { msg_id, chat_id });
367+
self.emit_msgs_changed(chat_id, msg_id);
366368
} else {
367369
let incoming_call_str =
368370
stock_str::incoming_call(self, call.has_video_initially()).await;
@@ -454,16 +456,19 @@ impl Context {
454456
return Ok(());
455457
}
456458

459+
let (msg_id, chat_id) = (call_id, call.msg.chat_id);
457460
if !call.is_accepted() {
458461
if call.is_incoming() {
459462
if from_id == ContactId::SELF {
460463
call.mark_as_ended(self).await?;
461464
let declined_call_str = stock_str::declined_call(self).await;
462465
call.update_text(self, &declined_call_str).await?;
466+
self.emit_event(EventType::CallEnded { msg_id, chat_id });
463467
} else {
464468
call.mark_as_canceled(self).await?;
465469
let missed_call_str = stock_str::missed_call(self).await;
466470
call.update_text(self, &missed_call_str).await?;
471+
self.emit_event(EventType::CallMissed { msg_id, chat_id });
467472
}
468473
} else {
469474
// outgoing
@@ -476,17 +481,15 @@ impl Context {
476481
let declined_call_str = stock_str::declined_call(self).await;
477482
call.update_text(self, &declined_call_str).await?;
478483
}
484+
self.emit_event(EventType::CallEnded { msg_id, chat_id });
479485
}
480486
} else {
481487
call.mark_as_ended(self).await?;
482488
call.update_text_duration(self).await?;
489+
self.emit_event(EventType::CallEnded { msg_id, chat_id });
483490
}
484491

485492
self.emit_msgs_changed(call.msg.chat_id, call_id);
486-
self.emit_event(EventType::CallEnded {
487-
msg_id: call.msg.id,
488-
chat_id: call.msg.chat_id,
489-
});
490493
}
491494
_ => {}
492495
}

src/calls/calls_tests.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::config::Config;
44
use crate::constants::DC_CHAT_ID_TRASH;
55
use crate::receive_imf::receive_imf;
66
use crate::test_utils::{TestContext, TestContextManager};
7+
use crate::tools::SystemTime;
78

89
struct CallSetup {
910
pub alice: TestContext,
@@ -413,7 +414,7 @@ async fn test_caller_cancels_call() -> Result<()> {
413414
bob.recv_msg_trash(&sent3).await;
414415
assert_text(&bob, bob_call.id, "Missed call").await?;
415416
bob.evtracker
416-
.get_matching(|evt| matches!(evt, EventType::CallEnded { .. }))
417+
.get_matching(|evt| matches!(evt, EventType::CallMissed { .. }))
417418
.await;
418419
assert_eq!(call_state(&bob, bob_call.id).await?, CallState::Missed);
419420

@@ -425,13 +426,49 @@ async fn test_caller_cancels_call() -> Result<()> {
425426
bob2.recv_msg_trash(&sent3).await;
426427
assert_text(&bob2, bob2_call.id, "Missed call").await?;
427428
bob2.evtracker
428-
.get_matching(|evt| matches!(evt, EventType::CallEnded { .. }))
429+
.get_matching(|evt| matches!(evt, EventType::CallMissed { .. }))
429430
.await;
430431
assert_eq!(call_state(&bob2, bob2_call.id).await?, CallState::Missed);
431432

432433
Ok(())
433434
}
434435

436+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
437+
async fn test_stale_call() -> Result<()> {
438+
let mut tcm = TestContextManager::new();
439+
let alice = &tcm.alice().await;
440+
let bob = &tcm.bob().await;
441+
442+
let alice_chat = alice.create_chat(bob).await;
443+
alice
444+
.place_outgoing_call(alice_chat.id, PLACE_INFO.to_string(), true)
445+
.await?;
446+
let sent1 = alice.pop_sent_msg().await;
447+
448+
SystemTime::shift(Duration::from_secs(3600));
449+
let bob_call = bob.recv_msg(&sent1).await;
450+
bob.evtracker
451+
.get_matching(|evt| matches!(evt, EventType::CallMissed { .. }))
452+
.await;
453+
let EventType::MsgsChanged { msg_id, chat_id } = bob
454+
.evtracker
455+
.get_matching(|evt| matches!(evt, EventType::MsgsChanged { .. }))
456+
.await
457+
else {
458+
unreachable!();
459+
};
460+
assert_eq!(msg_id, bob_call.id);
461+
assert_eq!(chat_id, bob_call.chat_id);
462+
assert_text(bob, bob_call.id, "Missed call").await?;
463+
assert_eq!(call_state(bob, bob_call.id).await?, CallState::Missed);
464+
465+
// Test that message summary says it is a missed call.
466+
let bob_call_msg = Message::load_from_db(bob, bob_call.id).await?;
467+
let summary = bob_call_msg.get_summary(bob, None).await?;
468+
assert_eq!(summary.text, "🎥 Missed call");
469+
Ok(())
470+
}
471+
435472
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
436473
async fn test_is_stale_call() -> Result<()> {
437474
// a call started now is not stale

src/events/payload.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,14 @@ pub enum EventType {
417417
chat_id: ChatId,
418418
},
419419

420+
/// Call missed.
421+
CallMissed {
422+
/// ID of the message referring to the call.
423+
msg_id: MsgId,
424+
/// ID of the chat which the message belongs to.
425+
chat_id: ChatId,
426+
},
427+
420428
/// One or more transports has changed or another transport is primary now.
421429
///
422430
/// UI should update the list.

0 commit comments

Comments
 (0)