mirror of
https://github.com/chatmail/core.git
synced 2026-05-13 11:56:30 +03:00
fix(jsonrpc): Use Core's logic for computing VcardContact.color (#7294)
Before, the color was computed from the address, but as we've switched to fingerprint-based contact colors, this logic became stale. Now `deltachat::contact::get_color()` is used. A test would be nice to have, but as now all the logic is in Core, this isn't critical as there are Core tests at least.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use deltachat::color;
|
|
||||||
use deltachat::context::Context;
|
use deltachat::context::Context;
|
||||||
|
use deltachat::key::{DcKey, SignedPublicKey};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use typescript_type_def::TypeDef;
|
use typescript_type_def::TypeDef;
|
||||||
|
|
||||||
@@ -130,7 +130,13 @@ pub struct VcardContact {
|
|||||||
impl From<deltachat_contact_tools::VcardContact> for VcardContact {
|
impl From<deltachat_contact_tools::VcardContact> for VcardContact {
|
||||||
fn from(vc: deltachat_contact_tools::VcardContact) -> Self {
|
fn from(vc: deltachat_contact_tools::VcardContact) -> Self {
|
||||||
let display_name = vc.display_name().to_string();
|
let display_name = vc.display_name().to_string();
|
||||||
let color = color::str_to_color(&vc.addr.to_lowercase());
|
let is_self = false;
|
||||||
|
let fpr = vc.key.as_deref().and_then(|k| {
|
||||||
|
SignedPublicKey::from_base64(k)
|
||||||
|
.ok()
|
||||||
|
.map(|k| k.dc_fingerprint())
|
||||||
|
});
|
||||||
|
let color = deltachat::contact::get_color(is_self, &vc.addr, &fpr);
|
||||||
Self {
|
Self {
|
||||||
addr: vc.addr,
|
addr: vc.addr,
|
||||||
display_name,
|
display_name,
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ use crate::message::MessageState;
|
|||||||
use crate::mimeparser::AvatarAction;
|
use crate::mimeparser::AvatarAction;
|
||||||
use crate::param::{Param, Params};
|
use crate::param::{Param, Params};
|
||||||
use crate::sync::{self, Sync::*};
|
use crate::sync::{self, Sync::*};
|
||||||
use crate::tools::{SystemTime, duration_to_str, get_abs_path, time};
|
use crate::tools::{SystemTime, duration_to_str, get_abs_path, time, to_lowercase};
|
||||||
use crate::{chat, chatlist_events, ensure_and_debug_assert_ne, stock_str};
|
use crate::{chat, chatlist_events, ensure_and_debug_assert_ne, stock_str};
|
||||||
|
|
||||||
/// Time during which a contact is considered as seen recently.
|
/// Time during which a contact is considered as seen recently.
|
||||||
@@ -1574,19 +1574,10 @@ impl Contact {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a color for the contact.
|
/// Returns a color for the contact.
|
||||||
/// The color is calculated from the contact's fingerprint (for key-contacts)
|
/// See [`self::get_color`].
|
||||||
/// 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 fn get_color(&self) -> u32 {
|
||||||
if let Some(fingerprint) = self.fingerprint() {
|
get_color(self.id == ContactId::SELF, &self.addr, &self.fingerprint())
|
||||||
str_to_color(&fingerprint.hex())
|
|
||||||
} else if self.id == ContactId::SELF {
|
|
||||||
0x808080
|
|
||||||
} else {
|
|
||||||
str_to_color(&self.addr.to_lowercase())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the contact's status.
|
/// Gets the contact's status.
|
||||||
@@ -1682,6 +1673,21 @@ impl Contact {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a color for a contact having given attributes.
|
||||||
|
///
|
||||||
|
/// The color is calculated from contact's fingerprint (for key-contacts) or email address (for
|
||||||
|
/// address-contacts; should be lowercased to avoid allocation) 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(is_self: bool, addr: &str, fingerprint: &Option<Fingerprint>) -> u32 {
|
||||||
|
if let Some(fingerprint) = fingerprint {
|
||||||
|
str_to_color(&fingerprint.hex())
|
||||||
|
} else if is_self {
|
||||||
|
0x808080
|
||||||
|
} else {
|
||||||
|
str_to_color(&to_lowercase(addr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Updates the names of the chats which use the contact name.
|
// Updates the names of the chats which use the contact name.
|
||||||
//
|
//
|
||||||
// This is one of the few duplicated data, however, getting the chat list is easier this way.
|
// This is one of the few duplicated data, however, getting the chat list is easier this way.
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use crate::tools::{self, time_elapsed};
|
|||||||
/// This trait is implemented for rPGP's [SignedPublicKey] and
|
/// This trait is implemented for rPGP's [SignedPublicKey] and
|
||||||
/// [SignedSecretKey] types and makes working with them a little
|
/// [SignedSecretKey] types and makes working with them a little
|
||||||
/// easier in the deltachat world.
|
/// easier in the deltachat world.
|
||||||
pub(crate) trait DcKey: Serialize + Deserializable + Clone {
|
pub trait DcKey: Serialize + Deserializable + Clone {
|
||||||
/// Create a key from some bytes.
|
/// Create a key from some bytes.
|
||||||
fn from_slice(bytes: &[u8]) -> Result<Self> {
|
fn from_slice(bytes: &[u8]) -> Result<Self> {
|
||||||
let res = <Self as Deserializable>::from_bytes(Cursor::new(bytes));
|
let res = <Self as Deserializable>::from_bytes(Cursor::new(bytes));
|
||||||
@@ -112,7 +112,10 @@ pub(crate) trait DcKey: Serialize + Deserializable + Clone {
|
|||||||
/// The fingerprint for the key.
|
/// The fingerprint for the key.
|
||||||
fn dc_fingerprint(&self) -> Fingerprint;
|
fn dc_fingerprint(&self) -> Fingerprint;
|
||||||
|
|
||||||
|
/// Whether the key is private (or public).
|
||||||
fn is_private() -> bool;
|
fn is_private() -> bool;
|
||||||
|
|
||||||
|
/// Returns the OpenPGP Key ID.
|
||||||
fn key_id(&self) -> KeyId;
|
fn key_id(&self) -> KeyId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -753,6 +753,14 @@ pub(crate) fn buf_decompress(buf: &[u8]) -> Result<Vec<u8>> {
|
|||||||
Ok(mem::take(decompressor.get_mut()))
|
Ok(mem::take(decompressor.get_mut()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the given `&str` if already lowercased to avoid allocation, otherwise lowercases it.
|
||||||
|
pub(crate) fn to_lowercase(s: &str) -> Cow<'_, str> {
|
||||||
|
match s.chars().all(char::is_lowercase) {
|
||||||
|
true => Cow::Borrowed(s),
|
||||||
|
false => Cow::Owned(s.to_lowercase()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Increments `*t` and checks that it equals to `expected` after that.
|
/// Increments `*t` and checks that it equals to `expected` after that.
|
||||||
pub(crate) fn inc_and_check<T: PrimInt + AddAssign + std::fmt::Debug>(
|
pub(crate) fn inc_and_check<T: PrimInt + AddAssign + std::fmt::Debug>(
|
||||||
t: &mut T,
|
t: &mut T,
|
||||||
|
|||||||
Reference in New Issue
Block a user