diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index f3238a60b..511d70b57 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -4926,8 +4926,9 @@ void dc_event_unref(dc_event_t* event); #define DC_STR_VIDEOCHAT_INVITE_MSG_BODY 83 #define DC_STR_CONFIGURATION_FAILED 84 #define DC_STR_BAD_TIME_MSG_BODY 85 +#define DC_STR_UPDATE_REMINDER_MSG_BODY 86 -#define DC_STR_COUNT 85 +#define DC_STR_COUNT 86 /* * @} diff --git a/src/constants.rs b/src/constants.rs index 7cb9130fb..58ec42715 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -108,6 +108,12 @@ pub const DC_GCL_ADD_SELF: usize = 0x02; // unchanged user avatars are resent to the recipients every some days pub const DC_RESEND_USER_AVATAR_DAYS: i64 = 14; +// warn about an outdated app after a given number of days. +// as we use the "provider-db generation date" as reference (that might not be updated very often) +// and as not all system get speedy updates, +// do not use too small value that will annoy users checking for nonexistant updates. +pub const DC_OUTDATED_WARNING_DAYS: i64 = 365; + /// virtual chat showing all messages belonging to chats flagged with chats.blocked=2 pub const DC_CHAT_ID_DEADDROP: u32 = 1; /// messages that should be deleted get this chat_id; the messages are deleted from the working thread later then. This is also needed as rfc724_mid should be preset as long as the message is not deleted on the server (otherwise it is downloaded again) diff --git a/src/dc_tools.rs b/src/dc_tools.rs index 43acff91a..0551418dc 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -15,8 +15,8 @@ use async_std::{fs, io}; use chrono::{Local, TimeZone}; use rand::{thread_rng, Rng}; -use crate::chat::add_device_msg_with_importance; -use crate::constants::Viewtype; +use crate::chat::{add_device_msg, add_device_msg_with_importance}; +use crate::constants::{Viewtype, DC_OUTDATED_WARNING_DAYS}; use crate::context::Context; use crate::error::{bail, Error}; use crate::events::EventType; @@ -158,11 +158,14 @@ pub(crate) async fn dc_create_smeared_timestamps(context: &Context, count: usize // if the system time is not plausible, once a day, add a device message. // for testing we're using time() as that is also used for message timestamps. +// moreover, add a warning if the app is outdated. pub(crate) async fn maybe_add_time_based_warnings(context: &Context) { - maybe_warn_on_bad_time(context, time(), get_provider_update_timestamp()).await; + if !maybe_warn_on_bad_time(context, time(), get_provider_update_timestamp()).await { + maybe_warn_on_outdated(context, time(), get_provider_update_timestamp()).await; + } } -async fn maybe_warn_on_bad_time(context: &Context, now: i64, known_past_timestamp: i64) { +async fn maybe_warn_on_bad_time(context: &Context, now: i64, known_past_timestamp: i64) -> bool { if now < known_past_timestamp { let mut msg = Message::new(Viewtype::Text); msg.text = Some( @@ -181,7 +184,7 @@ async fn maybe_warn_on_bad_time(context: &Context, now: i64, known_past_timestam Some( format!( "bad-time-warning-{}", - chrono::NaiveDateTime::from_timestamp(now, 0).format("%Y-%m-%d") + chrono::NaiveDateTime::from_timestamp(now, 0).format("%Y-%m-%d") // repeat every day ) .as_str(), ), @@ -190,6 +193,33 @@ async fn maybe_warn_on_bad_time(context: &Context, now: i64, known_past_timestam ) .await .ok(); + return true; + } + false +} + +async fn maybe_warn_on_outdated(context: &Context, now: i64, approx_compile_time: i64) { + if now > approx_compile_time + DC_OUTDATED_WARNING_DAYS * 24 * 60 * 60 { + let mut msg = Message::new(Viewtype::Text); + msg.text = Some( + context + .stock_str(StockMessage::UpdateReminderMsgBody) + .await + .into(), + ); + add_device_msg( + context, + Some( + format!( + "outdated-warning-{}", + chrono::NaiveDateTime::from_timestamp(now, 0).format("%Y-%m") // repeat every month + ) + .as_str(), + ), + Some(&mut msg), + ) + .await + .ok(); } } @@ -1101,4 +1131,60 @@ mod tests { let msgs = chat::get_chat_msgs(&t.ctx, device_chat_id, 0, None).await; assert_eq!(msgs.len(), 2); } + + #[async_std::test] + async fn test_maybe_warn_on_outdated() { + let t = TestContext::new().await; + let timestamp_now: i64 = time(); + + // in about 6 months, the app should not be outdated + // (if this fails, provider-db is not updated since 6 months) + maybe_warn_on_outdated( + &t.ctx, + timestamp_now + 180 * 24 * 60 * 60, + get_provider_update_timestamp(), + ) + .await; + let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap(); + assert_eq!(chats.len(), 0); + + // in 1 year, the app should be considered as outdated + maybe_warn_on_outdated( + &t.ctx, + timestamp_now + 365 * 24 * 60 * 60, + get_provider_update_timestamp(), + ) + .await; + let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap(); + assert_eq!(chats.len(), 1); + let device_chat_id = chats.get_chat_id(0); + let msgs = chat::get_chat_msgs(&t.ctx, device_chat_id, 0, None).await; + assert_eq!(msgs.len(), 1); + + // do not repeat the warning every day ... + maybe_warn_on_outdated( + &t.ctx, + timestamp_now + (365 + 1) * 24 * 60 * 60, + get_provider_update_timestamp(), + ) + .await; + let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap(); + assert_eq!(chats.len(), 1); + let device_chat_id = chats.get_chat_id(0); + let msgs = chat::get_chat_msgs(&t.ctx, device_chat_id, 0, None).await; + assert_eq!(msgs.len(), 1); + + // ... but every month + maybe_warn_on_outdated( + &t.ctx, + timestamp_now + (365 + 31) * 24 * 60 * 60, + get_provider_update_timestamp(), + ) + .await; + let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap(); + assert_eq!(chats.len(), 1); + let device_chat_id = chats.get_chat_id(0); + let msgs = chat::get_chat_msgs(&t.ctx, device_chat_id, 0, None).await; + assert_eq!(msgs.len(), 2); + } } diff --git a/src/stock.rs b/src/stock.rs index dcb3ddac7..9c4366c77 100644 --- a/src/stock.rs +++ b/src/stock.rs @@ -225,6 +225,12 @@ pub enum StockMessage { Adjust your clock ⏰🔧 to ensure your messages are received correctly." ))] BadTimeMsgBody = 85, + + #[strum(props(fallback = "⚠️ Your Delta Chat version might be outdated.\n\n\ + This may cause problems because your chat partners use newer versions - \ + and you are missing the latest features 😳\n\ + Please check https://get.delta.chat or your app store for updates."))] + UpdateReminderMsgBody = 86, } /*