mirror of
https://github.com/chatmail/core.git
synced 2026-04-28 10:56:29 +03:00
api!: Contact::get_color(): Preserve address-based color hue for SELF
4010c60e7b "feat: use key fingerprints for color generation" changes
colors for contacts including SELF. Even if an avatar is set, the self-color is visible in
e.g. replies to outgoing messages.
This adds `Config::Selfcolor` and sets it in a migration. This doesn't preserve the old
address-based color accurately because the old code generating colors is already dropped, so this
only preserves the color angle (hue).
This commit is contained in:
@@ -4311,7 +4311,8 @@ pub unsafe extern "C" fn dc_contact_get_color(contact: *mut dc_contact_t) -> u32
|
||||
return 0;
|
||||
}
|
||||
let ffi_contact = &*contact;
|
||||
ffi_contact.contact.get_color()
|
||||
let ctx = &*ffi_contact.context;
|
||||
block_on(ffi_contact.contact.get_color(ctx)).unwrap_or_log_default(ctx, "Failed get_color")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
||||
@@ -32,7 +32,10 @@ impl Account {
|
||||
let addr = ctx.get_config(Config::Addr).await?;
|
||||
let profile_image = ctx.get_config(Config::Selfavatar).await?;
|
||||
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_color(ctx)
|
||||
.await?,
|
||||
);
|
||||
let private_tag = ctx.get_config(Config::PrivateTag).await?;
|
||||
Ok(Account::Configured {
|
||||
|
||||
@@ -97,7 +97,7 @@ impl ContactObject {
|
||||
|
||||
Ok(ContactObject {
|
||||
address: contact.get_addr().to_owned(),
|
||||
color: color_int_to_hex_string(contact.get_color()),
|
||||
color: color_int_to_hex_string(contact.get_color(context).await?),
|
||||
auth_name: contact.get_authname().to_owned(),
|
||||
status: contact.get_status().to_owned(),
|
||||
display_name: contact.get_display_name().to_owned(),
|
||||
|
||||
@@ -162,7 +162,9 @@ impl MessageObject {
|
||||
message_id: quote.get_id().to_u32(),
|
||||
chat_id: quote.get_chat_id().to_u32(),
|
||||
author_display_name: quote_author.get_display_name().to_owned(),
|
||||
author_display_color: color_int_to_hex_string(quote_author.get_color()),
|
||||
author_display_color: color_int_to_hex_string(
|
||||
quote_author.get_color(context).await?,
|
||||
),
|
||||
override_sender_name: quote.get_override_sender_name(),
|
||||
image: if quote.get_viewtype() == Viewtype::Image
|
||||
|| quote.get_viewtype() == Viewtype::Gif
|
||||
@@ -581,7 +583,7 @@ impl MessageSearchResult {
|
||||
id: msg_id.to_u32(),
|
||||
author_profile_image: profile_image,
|
||||
author_name,
|
||||
author_color: color_int_to_hex_string(sender.get_color()),
|
||||
author_color: color_int_to_hex_string(sender.get_color(context).await?),
|
||||
author_id: sender.id.to_u32(),
|
||||
chat_id: chat.id.to_u32(),
|
||||
chat_name: chat.get_name().to_owned(),
|
||||
|
||||
@@ -1807,7 +1807,7 @@ impl Chat {
|
||||
let contacts = get_chat_contacts(context, self.id).await?;
|
||||
if let Some(contact_id) = contacts.first() {
|
||||
if let Ok(contact) = Contact::get_by_id(context, *contact_id).await {
|
||||
color = contact.get_color();
|
||||
color = contact.get_color(context).await?;
|
||||
}
|
||||
}
|
||||
} else if !self.grpid.is_empty() {
|
||||
|
||||
@@ -136,6 +136,9 @@ pub enum Config {
|
||||
/// Own name to use in the `From:` field when sending messages.
|
||||
Displayname,
|
||||
|
||||
/// Own color to use in the avatar placeholder and replies to outgoing messages.
|
||||
Selfcolor,
|
||||
|
||||
/// Own status to display, sent in message footer.
|
||||
Selfstatus,
|
||||
|
||||
@@ -474,6 +477,7 @@ impl Config {
|
||||
| Self::MvboxMove
|
||||
| Self::ShowEmails
|
||||
| Self::Selfavatar
|
||||
| Self::Selfcolor
|
||||
| Self::Selfstatus,
|
||||
)
|
||||
}
|
||||
@@ -833,7 +837,7 @@ impl Context {
|
||||
}
|
||||
if matches!(
|
||||
key,
|
||||
Config::Displayname | Config::Selfavatar | Config::PrivateTag
|
||||
Config::Displayname | Config::Selfavatar | Config::Selfcolor | Config::PrivateTag
|
||||
) {
|
||||
self.emit_event(EventType::AccountsItemChanged);
|
||||
}
|
||||
|
||||
@@ -245,6 +245,7 @@ async fn test_sync() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
test_config_str(&alice0, &alice1, Config::Displayname, "Alice Sync").await?;
|
||||
test_config_str(&alice0, &alice1, Config::Selfcolor, "255").await?;
|
||||
test_config_str(&alice0, &alice1, Config::Selfstatus, "My status").await?;
|
||||
|
||||
assert!(alice0.get_config(Config::Selfavatar).await?.is_none());
|
||||
|
||||
@@ -1579,11 +1579,17 @@ impl Contact {
|
||||
/// or email address (for address-contacts) and can be used
|
||||
/// for an fallback avatar with white initials
|
||||
/// as well as for headlines in bubbles of group chats.
|
||||
pub fn get_color(&self) -> u32 {
|
||||
pub async fn get_color(&self, context: &Context) -> Result<u32> {
|
||||
if self.id == ContactId::SELF {
|
||||
if let Some(v) = context.get_config_opt_parsed(Config::Selfcolor).await? {
|
||||
return Ok(v);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(fingerprint) = self.fingerprint() {
|
||||
str_to_color(&fingerprint.hex())
|
||||
Ok(str_to_color(&fingerprint.hex()))
|
||||
} else {
|
||||
str_to_color(&self.addr.to_lowercase())
|
||||
Ok(str_to_color(&self.addr.to_lowercase()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -758,17 +758,26 @@ async fn test_lookup_id_by_addr() {
|
||||
async fn test_contact_get_color() -> Result<()> {
|
||||
let t = TestContext::new().await;
|
||||
let contact_id = Contact::create(&t, "name", "name@example.net").await?;
|
||||
let color1 = Contact::get_by_id(&t, contact_id).await?.get_color();
|
||||
let color1 = Contact::get_by_id(&t, contact_id)
|
||||
.await?
|
||||
.get_color(&t)
|
||||
.await?;
|
||||
assert_eq!(color1, 0x4947dc);
|
||||
|
||||
let t = TestContext::new().await;
|
||||
let contact_id = Contact::create(&t, "prename name", "name@example.net").await?;
|
||||
let color2 = Contact::get_by_id(&t, contact_id).await?.get_color();
|
||||
let color2 = Contact::get_by_id(&t, contact_id)
|
||||
.await?
|
||||
.get_color(&t)
|
||||
.await?;
|
||||
assert_eq!(color2, color1);
|
||||
|
||||
let t = TestContext::new().await;
|
||||
let contact_id = Contact::create(&t, "Name", "nAme@exAmple.NET").await?;
|
||||
let color3 = Contact::get_by_id(&t, contact_id).await?.get_color();
|
||||
let color3 = Contact::get_by_id(&t, contact_id)
|
||||
.await?
|
||||
.get_color(&t)
|
||||
.await?;
|
||||
assert_eq!(color3, color1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -277,6 +277,7 @@ async fn test_get_info_completeness() {
|
||||
"mail_security",
|
||||
"notify_about_wrong_pw",
|
||||
"self_reporting_id",
|
||||
"selfcolor",
|
||||
"selfstatus",
|
||||
"send_server",
|
||||
"send_user",
|
||||
|
||||
@@ -161,7 +161,7 @@ async fn self_info(context: &Context) -> Result<(Option<Vec<u8>>, String, String
|
||||
None => contact.get_addr().to_string(),
|
||||
};
|
||||
let addr = contact.get_addr().to_string();
|
||||
let color = color_int_to_hex_string(contact.get_color());
|
||||
let color = color_int_to_hex_string(contact.get_color(context).await?);
|
||||
Ok((avatar, displayname, addr, color))
|
||||
}
|
||||
|
||||
|
||||
@@ -1261,6 +1261,30 @@ CREATE INDEX gossip_timestamp_index ON gossip_timestamp (chat_id, fingerprint);
|
||||
.await?;
|
||||
}
|
||||
|
||||
inc_and_check(&mut migration_version, 134)?;
|
||||
if dbversion < migration_version {
|
||||
let trans_fn = |t: &mut rusqlite::Transaction| {
|
||||
let Some(addr): Option<String> = t
|
||||
.query_row(
|
||||
"SELECT value FROM config WHERE keyname='configured_addr'",
|
||||
(),
|
||||
|row| row.get(0),
|
||||
)
|
||||
.optional()?
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
let color = crate::color::str_to_color(&addr.to_lowercase());
|
||||
t.execute(
|
||||
"INSERT OR IGNORE INTO config (keyname, value) VALUES ('selfcolor', ?)",
|
||||
(color,),
|
||||
)?;
|
||||
Ok(())
|
||||
};
|
||||
sql.execute_migration_transaction(trans_fn, migration_version)
|
||||
.await?;
|
||||
}
|
||||
|
||||
let new_version = sql
|
||||
.get_raw_config_int(VERSION_CFG)
|
||||
.await?
|
||||
|
||||
@@ -112,7 +112,7 @@ pub(crate) async fn intercept_get_updates(
|
||||
hash_map::Entry::Vacant(e) => {
|
||||
let contact = Contact::get_by_id(context, location.contact_id).await?;
|
||||
let name = contact.get_display_name().to_string();
|
||||
let color = color_int_to_hex_string(contact.get_color());
|
||||
let color = color_int_to_hex_string(contact.get_color(context).await?);
|
||||
e.insert((name, color)).clone()
|
||||
}
|
||||
hash_map::Entry::Occupied(e) => e.get().clone(),
|
||||
|
||||
Reference in New Issue
Block a user