mirror of
https://github.com/chatmail/core.git
synced 2026-05-02 21:06:31 +03:00
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.
This commit is contained in:
@@ -4240,7 +4240,17 @@ pub unsafe extern "C" fn dc_contact_get_color(contact: *mut dc_contact_t) -> u32
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
let ffi_contact = &*contact;
|
let ffi_contact = &*contact;
|
||||||
ffi_contact.contact.get_color()
|
let ctx = &*ffi_contact.context;
|
||||||
|
block_on(async move {
|
||||||
|
ffi_contact
|
||||||
|
.contact
|
||||||
|
// We don't want any UIs displaying gray self-color.
|
||||||
|
.get_or_gen_color(ctx)
|
||||||
|
.await
|
||||||
|
.context("Contact::get_color()")
|
||||||
|
.log_err(ctx)
|
||||||
|
.unwrap_or(0)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|||||||
@@ -32,7 +32,10 @@ impl Account {
|
|||||||
let addr = ctx.get_config(Config::Addr).await?;
|
let addr = ctx.get_config(Config::Addr).await?;
|
||||||
let profile_image = ctx.get_config(Config::Selfavatar).await?;
|
let profile_image = ctx.get_config(Config::Selfavatar).await?;
|
||||||
let color = color_int_to_hex_string(
|
let color = color_int_to_hex_string(
|
||||||
Contact::get_by_id(ctx, ContactId::SELF).await?.get_color(),
|
Contact::get_by_id(ctx, ContactId::SELF)
|
||||||
|
.await?
|
||||||
|
.get_or_gen_color(ctx)
|
||||||
|
.await?,
|
||||||
);
|
);
|
||||||
let private_tag = ctx.get_config(Config::PrivateTag).await?;
|
let private_tag = ctx.get_config(Config::PrivateTag).await?;
|
||||||
Ok(Account::Configured {
|
Ok(Account::Configured {
|
||||||
|
|||||||
@@ -1573,11 +1573,24 @@ impl Contact {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a color for the contact.
|
/// Returns a color for the contact.
|
||||||
/// See [`self::get_color`].
|
/// For self-contact this returns gray if own keypair doesn't exist yet.
|
||||||
|
/// See also [`self::get_color`].
|
||||||
pub fn get_color(&self) -> u32 {
|
pub fn get_color(&self) -> u32 {
|
||||||
get_color(self.id == ContactId::SELF, &self.addr, &self.fingerprint())
|
get_color(self.id == ContactId::SELF, &self.addr, &self.fingerprint())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a color for the contact.
|
||||||
|
/// Ensures that the color isn't gray. For self-contact this generates own keypair if it doesn't
|
||||||
|
/// exist yet.
|
||||||
|
/// See also [`self::get_color`].
|
||||||
|
pub async fn get_or_gen_color(&self, context: &Context) -> Result<u32> {
|
||||||
|
let mut fpr = self.fingerprint();
|
||||||
|
if fpr.is_none() && self.id == ContactId::SELF {
|
||||||
|
fpr = Some(load_self_public_key(context).await?.dc_fingerprint());
|
||||||
|
}
|
||||||
|
Ok(get_color(self.id == ContactId::SELF, &self.addr, &fpr))
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the contact's status.
|
/// Gets the contact's status.
|
||||||
///
|
///
|
||||||
/// Status is the last signature received in a message from this contact.
|
/// Status is the last signature received in a message from this contact.
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ use super::*;
|
|||||||
use crate::chat::{Chat, get_chat_contacts, send_text_msg};
|
use crate::chat::{Chat, get_chat_contacts, send_text_msg};
|
||||||
use crate::chatlist::Chatlist;
|
use crate::chatlist::Chatlist;
|
||||||
use crate::receive_imf::receive_imf;
|
use crate::receive_imf::receive_imf;
|
||||||
use crate::securejoin::get_securejoin_qr;
|
|
||||||
use crate::test_utils::{self, TestContext, TestContextManager, TimeShiftFalsePositiveNote};
|
use crate::test_utils::{self, TestContext, TestContextManager, TimeShiftFalsePositiveNote};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -775,16 +774,21 @@ async fn test_contact_get_color() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_self_color_vs_key() -> Result<()> {
|
async fn test_self_color() -> Result<()> {
|
||||||
let mut tcm = TestContextManager::new();
|
let mut tcm = TestContextManager::new();
|
||||||
let t = &tcm.unconfigured().await;
|
let t = &tcm.unconfigured().await;
|
||||||
t.configure_addr("alice@example.org").await;
|
t.configure_addr("alice@example.org").await;
|
||||||
assert!(t.is_configured().await?);
|
assert!(t.is_configured().await?);
|
||||||
let color = Contact::get_by_id(t, ContactId::SELF).await?.get_color();
|
let self_contact = Contact::get_by_id(t, ContactId::SELF).await?;
|
||||||
|
let color = self_contact.get_color();
|
||||||
assert_eq!(color, 0x808080);
|
assert_eq!(color, 0x808080);
|
||||||
get_securejoin_qr(t, None).await?;
|
let color = self_contact.get_or_gen_color(t).await?;
|
||||||
let color1 = Contact::get_by_id(t, ContactId::SELF).await?.get_color();
|
assert_ne!(color, 0x808080);
|
||||||
assert_ne!(color1, color);
|
let color1 = self_contact.get_or_gen_color(t).await?;
|
||||||
|
assert_eq!(color1, color);
|
||||||
|
|
||||||
|
let bob = &tcm.bob().await;
|
||||||
|
assert_eq!(bob.add_or_lookup_contact(t).await.get_color(), color);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user