diff --git a/src/dc_chat.c b/src/dc_chat.c index 4d1eb85a..a8aa5c5d 100644 --- a/src/dc_chat.c +++ b/src/dc_chat.c @@ -259,6 +259,46 @@ cleanup: } +/** + * Get a color for the chat. + * For 1:1 chats, the color is calculated from the contact's email address. + * Otherwise, the chat name is used. + * The color can be used for an fallback avatar with white initials + * as well as for headlines in bubbles of group chats. + * + * @memberof dc_chat_t + * @param chat The chat object. + * @return Color as 0x00rrggbb with rr=red, gg=green, bb=blue + * each in the range 0-255. + */ +uint32_t dc_chat_get_color(const dc_chat_t* chat) +{ + uint32_t color = 0; + dc_array_t* contacts = NULL; + dc_contact_t* contact = NULL; + + if (chat==NULL || chat->magic!=DC_CHAT_MAGIC) { + goto cleanup; + } + + if(chat->type==DC_CHAT_TYPE_SINGLE) { + contacts = dc_get_chat_contacts(chat->context, chat->id); + if (contacts->count >= 1) { + contact = dc_get_contact(chat->context, contacts->array[0]); + color = dc_str_to_color(contact->addr); + } + } + else { + color = dc_str_to_color(chat->name); + } + +cleanup: + dc_array_unref(contacts); + dc_contact_unref(contact); + return color; +} + + /** * Get archived state. * diff --git a/src/dc_contact.c b/src/dc_contact.c index 3c664256..2de6ea90 100644 --- a/src/dc_contact.c +++ b/src/dc_contact.c @@ -217,7 +217,7 @@ char* dc_contact_get_first_name(const dc_contact_t* contact) * using dc_set_config(context, "selfavatar", image). * * @memberof dc_contact_t - * @param chat The contact object. + * @param contact The contact object. * @return Path and file if the profile image, if any. * NULL otherwise. * Must be free()'d after usage. @@ -245,6 +245,27 @@ cleanup: } +/** + * Get a color for the contact. + * The color is calculated from the contact's email address + * and can be used for an fallback avatar with white initials + * as well as for headlines in bubbles of group chats. + * + * @memberof dc_contact_t + * @param chat The contact object. + * @return Color as 0x00rrggbb with rr=red, gg=green, bb=blue + * each in the range 0-255. + */ +uint32_t dc_contact_get_color(const dc_contact_t* contact) +{ + if (contact==NULL || contact->magic!=DC_CONTACT_MAGIC) { + return 0x000000; + } + + return dc_str_to_color(contact->addr); +} + + /** * Check if a contact is blocked. * diff --git a/src/dc_tools.c b/src/dc_tools.c index 177c7735..4dd1fed3 100644 --- a/src/dc_tools.c +++ b/src/dc_tools.c @@ -604,6 +604,32 @@ clist* dc_str_to_clist(const char* str, const char* delimiter) } +int dc_str_to_color(const char* str) +{ + static uint32_t colors[] = { + 0xe56555, + 0xf28c48, + 0x8e85ee, + 0x76c84d, + 0x5bb6cc, + 0x549cdd, + 0xd25c99, + 0xb37800 + }; + + int checksum = 0; + int str_len = strlen(str); + for (int i = 0; i < str_len; i++) { + checksum += (i+1)*str[i]; + checksum %= 0x00FFFFFF; + } + + int color_index = checksum % (sizeof(colors)/sizeof(uint32_t)); + + return colors[color_index]; +} + + /******************************************************************************* * clist tools ******************************************************************************/ diff --git a/src/dc_tools.h b/src/dc_tools.h index 446850e7..581d0b79 100644 --- a/src/dc_tools.h +++ b/src/dc_tools.h @@ -44,6 +44,7 @@ void dc_free_splitted_lines (carray* lines); char* dc_insert_breaks (const char*, int break_every, const char* break_chars); /* insert a break every n characters, the return must be free()'d */ char* dc_str_from_clist (const clist*, const char* delimiter); clist* dc_str_to_clist (const char*, const char* delimiter); +int dc_str_to_color (const char*); // from libetpan/src/data-types/base64.h (which cannot be included without adding libetpan/src/... to the include-search-paths, which would result in double-file-name-errors, so, for now, we use this hack) char* encode_base64 (const char * in, int len); diff --git a/src/deltachat.h b/src/deltachat.h index 2806794d..11defc60 100644 --- a/src/deltachat.h +++ b/src/deltachat.h @@ -464,6 +464,7 @@ int dc_chat_get_type (const dc_chat_t*); char* dc_chat_get_name (const dc_chat_t*); char* dc_chat_get_subtitle (const dc_chat_t*); char* dc_chat_get_profile_image (const dc_chat_t*); +uint32_t dc_chat_get_color (const dc_chat_t*); int dc_chat_get_archived (const dc_chat_t*); int dc_chat_is_unpromoted (const dc_chat_t*); int dc_chat_is_self_talk (const dc_chat_t*); @@ -571,6 +572,7 @@ char* dc_contact_get_display_name (const dc_contact_t*); char* dc_contact_get_name_n_addr (const dc_contact_t*); char* dc_contact_get_first_name (const dc_contact_t*); char* dc_contact_get_profile_image (const dc_contact_t*); +uint32_t dc_contact_get_color (const dc_contact_t*); int dc_contact_is_blocked (const dc_contact_t*); int dc_contact_is_verified (dc_contact_t*);