@@ -30,6 +30,7 @@ use crate::debug_logging::maybe_set_logging_xdc;
3030use crate :: download:: DownloadState ;
3131use crate :: ephemeral:: { Timer as EphemeralTimer , start_chat_ephemeral_timers} ;
3232use crate :: events:: EventType ;
33+ use crate :: key:: self_fingerprint;
3334use crate :: location;
3435use crate :: log:: { LogExt , error, info, warn} ;
3536use crate :: logged_debug_assert;
@@ -2006,17 +2007,21 @@ impl Chat {
20062007 /// Sends a `SyncAction` synchronising chat contacts to other devices.
20072008 pub ( crate ) async fn sync_contacts ( & self , context : & Context ) -> Result < ( ) > {
20082009 if self . is_encrypted ( context) . await ? {
2010+ let self_fp = self_fingerprint ( context) . await ?;
20092011 let fingerprint_addrs = context
20102012 . sql
20112013 . query_map (
2012- "SELECT c.fingerprint, c.addr
2014+ "SELECT c.id, c. fingerprint, c.addr
20132015 FROM contacts c INNER JOIN chats_contacts cc
20142016 ON c.id=cc.contact_id
20152017 WHERE cc.chat_id=? AND cc.add_timestamp >= cc.remove_timestamp" ,
20162018 ( self . id , ) ,
20172019 |row| {
2018- let fingerprint = row. get ( 0 ) ?;
2019- let addr = row. get ( 1 ) ?;
2020+ if row. get :: < _ , ContactId > ( 0 ) ? == ContactId :: SELF {
2021+ return Ok ( ( self_fp. to_string ( ) , String :: new ( ) ) ) ;
2022+ }
2023+ let fingerprint = row. get ( 1 ) ?;
2024+ let addr = row. get ( 2 ) ?;
20202025 Ok ( ( fingerprint, addr) )
20212026 } ,
20222027 |addrs| addrs. collect :: < Result < Vec < _ > , _ > > ( ) . map_err ( Into :: into) ,
@@ -3395,25 +3400,26 @@ pub async fn get_past_chat_contacts(context: &Context, chat_id: ChatId) -> Resul
33953400 Ok ( list)
33963401}
33973402
3398- /// Creates a group chat with a given `name` .
3403+ /// Creates an encrypted group chat.
33993404pub async fn create_group_chat ( context : & Context , name : & str ) -> Result < ChatId > {
3400- let is_encrypted = true ;
3401- create_group_ex ( context, is_encrypted, name) . await
3405+ create_group_ex ( context, Sync , create_id ( ) , name) . await
34023406}
34033407
3404- /// Creates a new unencrypted group chat.
3408+ /// Creates an unencrypted group chat.
34053409pub async fn create_group_chat_unencrypted ( context : & Context , name : & str ) -> Result < ChatId > {
3406- let is_encrypted = false ;
3407- create_group_ex ( context, is_encrypted, name) . await
3410+ create_group_ex ( context, Sync , String :: new ( ) , name) . await
34083411}
34093412
34103413/// Creates a group chat.
34113414///
3412- /// * `is_encrypted` - If true, the chat is encrypted (with key-contacts).
3415+ /// * `sync` - Whether a multi-device synchronization message should be sent. Ignored for
3416+ /// unencrypted chats currently.
3417+ /// * `grpid` - Group ID. Iff nonempty, the chat is encrypted (with key-contacts).
34133418/// * `name` - Chat name.
34143419pub ( crate ) async fn create_group_ex (
34153420 context : & Context ,
3416- is_encrypted : bool ,
3421+ sync : sync:: Sync ,
3422+ grpid : String ,
34173423 name : & str ,
34183424) -> Result < ChatId > {
34193425 let mut chat_name = sanitize_single_line ( name) ;
@@ -3424,20 +3430,14 @@ pub(crate) async fn create_group_ex(
34243430 chat_name = "…" . to_string ( ) ;
34253431 }
34263432
3427- let grpid = if is_encrypted {
3428- create_id ( )
3429- } else {
3430- String :: new ( )
3431- } ;
3432-
34333433 let timestamp = create_smeared_timestamp ( context) ;
34343434 let row_id = context
34353435 . sql
34363436 . insert (
34373437 "INSERT INTO chats
34383438 (type, name, grpid, param, created_timestamp)
34393439 VALUES(?, ?, ?, \' U=1\' , ?);" ,
3440- ( Chattype :: Group , chat_name, grpid, timestamp) ,
3440+ ( Chattype :: Group , & chat_name, & grpid, timestamp) ,
34413441 )
34423442 . await ?;
34433443
@@ -3448,7 +3448,7 @@ pub(crate) async fn create_group_ex(
34483448 chatlist_events:: emit_chatlist_changed ( context) ;
34493449 chatlist_events:: emit_chatlist_item_changed ( context, chat_id) ;
34503450
3451- if is_encrypted {
3451+ if !grpid . is_empty ( ) {
34523452 // Add "Messages are end-to-end encrypted." message.
34533453 chat_id. add_encrypted_msg ( context, timestamp) . await ?;
34543454 }
@@ -3459,7 +3459,11 @@ pub(crate) async fn create_group_ex(
34593459 let text = stock_str:: new_group_send_first_message ( context) . await ;
34603460 add_info_msg ( context, chat_id, & text, create_smeared_timestamp ( context) ) . await ?;
34613461 }
3462-
3462+ if let ( true , true ) = ( sync. into ( ) , !grpid. is_empty ( ) ) {
3463+ let id = SyncId :: Grpid ( grpid) ;
3464+ let action = SyncAction :: CreateGroupEncrypted ( chat_name) ;
3465+ self :: sync ( context, id, action) . await . log_err ( context) . ok ( ) ;
3466+ }
34633467 Ok ( chat_id)
34643468}
34653469
@@ -4675,16 +4679,14 @@ async fn set_contacts_by_fingerprints(
46754679 "Cannot add key-contacts to unencrypted chat {id}"
46764680 ) ;
46774681 ensure ! (
4678- chat. typ == Chattype :: OutBroadcast ,
4679- "{id} is not a broadcast list " ,
4682+ matches! ( chat. typ, Chattype :: Group | Chattype :: OutBroadcast ) ,
4683+ "{id} is not a group or broadcast " ,
46804684 ) ;
46814685 let mut contacts = HashSet :: new ( ) ;
46824686 for ( fingerprint, addr) in fingerprint_addrs {
4683- let contact_addr = ContactAddress :: new ( addr) ?;
4684- let contact =
4685- Contact :: add_or_lookup_ex ( context, "" , & contact_addr, fingerprint, Origin :: Hidden )
4686- . await ?
4687- . 0 ;
4687+ let contact = Contact :: add_or_lookup_ex ( context, "" , addr, fingerprint, Origin :: Hidden )
4688+ . await ?
4689+ . 0 ;
46884690 contacts. insert ( contact) ;
46894691 }
46904692 let contacts_old = HashSet :: < ContactId > :: from_iter ( get_chat_contacts ( context, id) . await ?) ;
@@ -4723,7 +4725,7 @@ pub(crate) enum SyncId {
47234725 /// "Message-ID"-s, from oldest to latest. Used for ad-hoc groups.
47244726 Msgids ( Vec < String > ) ,
47254727
4726- // Special id for device chat.
4728+ /// Special id for device chat.
47274729 Device ,
47284730}
47294731
@@ -4737,6 +4739,8 @@ pub(crate) enum SyncAction {
47374739 SetMuted ( MuteDuration ) ,
47384740 /// Create broadcast channel with the given name.
47394741 CreateBroadcast ( String ) ,
4742+ /// Create encrypted group chat with the given name.
4743+ CreateGroupEncrypted ( String ) ,
47404744 Rename ( String ) ,
47414745 /// Set chat contacts by their addresses.
47424746 SetContacts ( Vec < String > ) ,
@@ -4802,6 +4806,9 @@ impl Context {
48024806 if let SyncAction :: CreateBroadcast ( name) = action {
48034807 create_broadcast_ex ( self , Nosync , grpid. clone ( ) , name. clone ( ) ) . await ?;
48044808 return Ok ( ( ) ) ;
4809+ } else if let SyncAction :: CreateGroupEncrypted ( name) = action {
4810+ create_group_ex ( self , Nosync , grpid. clone ( ) , name) . await ?;
4811+ return Ok ( ( ) ) ;
48054812 }
48064813 get_chat_id_by_grpid ( self , grpid)
48074814 . await ?
@@ -4823,7 +4830,7 @@ impl Context {
48234830 SyncAction :: Accept => chat_id. accept_ex ( self , Nosync ) . await ,
48244831 SyncAction :: SetVisibility ( v) => chat_id. set_visibility_ex ( self , Nosync , * v) . await ,
48254832 SyncAction :: SetMuted ( duration) => set_muted_ex ( self , Nosync , chat_id, * duration) . await ,
4826- SyncAction :: CreateBroadcast ( _) => {
4833+ SyncAction :: CreateBroadcast ( _) | SyncAction :: CreateGroupEncrypted ( .. ) => {
48274834 Err ( anyhow ! ( "sync_alter_chat({id:?}, {action:?}): Bad request." ) )
48284835 }
48294836 SyncAction :: Rename ( to) => rename_ex ( self , Nosync , chat_id, to) . await ,
0 commit comments