Skip to content

Commit c499dab

Browse files
committed
feat: Add Contact::get_or_gen_color. Use it in CFFI and JSON-RPC to avoid gray self-color (#7374)
`Contact::get_color()` returns gray if own keypair doesn't exist yet and we don't want any UIs displaying it. Keypair generation can't be done in `get_color()` or `get_by_id_optional()` to avoid breaking Core tests on key import. Also this makes the API clearer, pure getters shouldn't modify any visible state.
1 parent e70307a commit c499dab

File tree

4 files changed

+39
-9
lines changed

4 files changed

+39
-9
lines changed

deltachat-ffi/src/lib.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4240,7 +4240,17 @@ pub unsafe extern "C" fn dc_contact_get_color(contact: *mut dc_contact_t) -> u32
42404240
return 0;
42414241
}
42424242
let ffi_contact = &*contact;
4243-
ffi_contact.contact.get_color()
4243+
let ctx = &*ffi_contact.context;
4244+
block_on(async move {
4245+
ffi_contact
4246+
.contact
4247+
// We don't want any UIs displaying gray self-color.
4248+
.get_or_gen_color(ctx)
4249+
.await
4250+
.context("Contact::get_color()")
4251+
.log_err(ctx)
4252+
.unwrap_or(0)
4253+
})
42444254
}
42454255

42464256
#[no_mangle]

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ impl Account {
3232
let addr = ctx.get_config(Config::Addr).await?;
3333
let profile_image = ctx.get_config(Config::Selfavatar).await?;
3434
let color = color_int_to_hex_string(
35-
Contact::get_by_id(ctx, ContactId::SELF).await?.get_color(),
35+
Contact::get_by_id(ctx, ContactId::SELF)
36+
.await?
37+
.get_or_gen_color(ctx)
38+
.await?,
3639
);
3740
let private_tag = ctx.get_config(Config::PrivateTag).await?;
3841
Ok(Account::Configured {

src/contact.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1573,11 +1573,24 @@ impl Contact {
15731573
}
15741574

15751575
/// Returns a color for the contact.
1576-
/// See [`self::get_color`].
1576+
/// For self-contact this returns gray if own keypair doesn't exist yet.
1577+
/// See also [`self::get_color`].
15771578
pub fn get_color(&self) -> u32 {
15781579
get_color(self.id == ContactId::SELF, &self.addr, &self.fingerprint())
15791580
}
15801581

1582+
/// Returns a color for the contact.
1583+
/// Ensures that the color isn't gray. For self-contact this generates own keypair if it doesn't
1584+
/// exist yet.
1585+
/// See also [`self::get_color`].
1586+
pub async fn get_or_gen_color(&self, context: &Context) -> Result<u32> {
1587+
let mut fpr = self.fingerprint();
1588+
if fpr.is_none() && self.id == ContactId::SELF {
1589+
fpr = Some(load_self_public_key(context).await?.dc_fingerprint());
1590+
}
1591+
Ok(get_color(self.id == ContactId::SELF, &self.addr, &fpr))
1592+
}
1593+
15811594
/// Gets the contact's status.
15821595
///
15831596
/// Status is the last signature received in a message from this contact.

src/contact/contact_tests.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use super::*;
44
use crate::chat::{Chat, get_chat_contacts, send_text_msg};
55
use crate::chatlist::Chatlist;
66
use crate::receive_imf::receive_imf;
7-
use crate::securejoin::get_securejoin_qr;
87
use crate::test_utils::{self, TestContext, TestContextManager, TimeShiftFalsePositiveNote};
98

109
#[test]
@@ -775,16 +774,21 @@ async fn test_contact_get_color() -> Result<()> {
775774
}
776775

777776
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
778-
async fn test_self_color_vs_key() -> Result<()> {
777+
async fn test_self_color() -> Result<()> {
779778
let mut tcm = TestContextManager::new();
780779
let t = &tcm.unconfigured().await;
781780
t.configure_addr("[email protected]").await;
782781
assert!(t.is_configured().await?);
783-
let color = Contact::get_by_id(t, ContactId::SELF).await?.get_color();
782+
let self_contact = Contact::get_by_id(t, ContactId::SELF).await?;
783+
let color = self_contact.get_color();
784784
assert_eq!(color, 0x808080);
785-
get_securejoin_qr(t, None).await?;
786-
let color1 = Contact::get_by_id(t, ContactId::SELF).await?.get_color();
787-
assert_ne!(color1, color);
785+
let color = self_contact.get_or_gen_color(t).await?;
786+
assert_ne!(color, 0x808080);
787+
let color1 = self_contact.get_or_gen_color(t).await?;
788+
assert_eq!(color1, color);
789+
790+
let bob = &tcm.bob().await;
791+
assert_eq!(bob.add_or_lookup_contact(t).await.get_color(), color);
788792
Ok(())
789793
}
790794

0 commit comments

Comments
 (0)