add multi-device sync (#2669)

* add basic multi-device-sync functions

* generate json

* add context.parse_sync_items()

* add context.execute_sync_items()

* piggyback sync-commands message, add body for human-readable part

* avoid double json renderings

* mimeparser parses incoming .json sync-files

* do not piggyback sync-files

* execute sync items

* return status of send_sync_msg()

* send sync messages as multipart/report

* add a per-item-timestamp and also allow adding other per-item-fields in the future

* if the self-chat does not exist, create it blocked/hidden

* create tokens closer to real qr-code needs

* respect bcc_self setting, add test for that

* sync qr code tokens after promoting groups

* send sync-messages only if an experimental switch is set

* trigger send_sync_msg() after sending messages and after creating/redraw/revive qr-code

* add DC_STR_* constants to deltachat.h

* adapt to refactored qr module as of #2729

* tweak test

* use SendSyncMsgs config name instead of SendExperimentalSyncMsgs - we can remove or rename the config nevertheless, but have the option to keep it without renaming

* tweak docs

* remove currently unused effective timestamp calculation

* clarify when send_sync_msg() is called

* make sure, sync-messages are encrypted and are sent by SELF

* tweak docs, fix typos
This commit is contained in:
bjoern
2021-10-25 12:40:32 +02:00
committed by GitHub
parent bb97d842df
commit 65f09c238b
16 changed files with 719 additions and 16 deletions

View File

@@ -171,6 +171,17 @@ impl ChatId {
/// This should be used when **a user action** creates a chat 1:1, it ensures the chat
/// exists and is unblocked and scales the [`Contact`]'s origin.
pub async fn create_for_contact(context: &Context, contact_id: u32) -> Result<Self> {
ChatId::create_for_contact_with_blocked(context, contact_id, Blocked::Not).await
}
/// Same as `create_for_contact()` with an additional `create_blocked` parameter
/// that is used in case the chat does not exist.
/// If the chat exists already, `create_blocked` is ignored.
pub(crate) async fn create_for_contact_with_blocked(
context: &Context,
contact_id: u32,
create_blocked: Blocked,
) -> Result<Self> {
let chat_id = match ChatIdBlocked::lookup_by_contact(context, contact_id).await? {
Some(chat) => {
if chat.blocked != Blocked::Not {
@@ -182,7 +193,10 @@ impl ChatId {
if Contact::real_exists_by_id(context, contact_id).await?
|| contact_id == DC_CONTACT_ID_SELF
{
let chat_id = ChatId::get_for_contact(context, contact_id).await?;
let chat_id =
ChatIdBlocked::get_for_contact(context, contact_id, create_blocked)
.await
.map(|chat| chat.id)?;
Contact::scaleup_origin_by_id(context, contact_id, Origin::CreateChat).await?;
chat_id
} else {
@@ -1191,6 +1205,10 @@ impl Chat {
msg.param.set_int(Param::AttachGroupImage, 1);
self.param.remove(Param::Unpromoted);
self.update_param(context).await?;
// send_sync_msg() is called (usually) a moment later at Job::send_msg_to_smtp()
// when the group-creation message is actually sent though SMTP -
// this makes sure, the other devices are aware of grpid that is used in the sync-message.
context.sync_qr_code_tokens(Some(self.id)).await?;
}
// reset encrypt error state eg. for forwarding
@@ -2383,6 +2401,8 @@ pub(crate) async fn add_contact_to_chat_ex(
if from_handshake && chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 1 {
chat.param.remove(Param::Unpromoted);
chat.update_param(context).await?;
context.sync_qr_code_tokens(Some(chat_id)).await?;
context.send_sync_msg().await?;
}
let self_addr = context
.get_config(Config::ConfiguredAddr)