Feature #29824

Add user initials as a Gravatar icon fallback

Added by Kit Grose about 4 years ago. Updated 9 months ago.

Status:NewStart date:
Priority:NormalDue date:
Assignee:Marius BALTEANU% Done:

0%

Category:UI
Target version:-
Resolution:

Description

This feature allows us to use user initials as their avatars if they haven't configured a Gravatar, which is a fairly common way of handling undefined avatars nowadays.

One quick way to do this is to override the fallback image in the request to Gravatar (using my name as an example) to use a service like ui-avatars.com.

initials-front-end.patch Magnifier (3.26 KB) Anonymous, 2019-01-26 12:16

gravatar.rb-title-attrib-test.patch Magnifier (2.14 KB) Anonymous, 2019-01-26 12:17

29824-initials_avatars-WIP.patch Magnifier (2.95 KB) Felix Schäfer, 2022-02-27 16:26

History

#1 Updated by Kit Grose about 4 years ago

The feature could be further improved by using a simple hash of the user's email address or account name as the background colour for the icon, so two users with the same initials would have different icon colours:

#2 Updated by Bernhard Rohloff about 4 years ago

I really like this proposal!
+1

#3 Updated by Anonymous about 4 years ago

+1 I will research the ability to implement it with front-end JavaScript solution when I have time, should be pretty simple, and also cheaper to generate own than requesting from another site :)

#4 Updated by Anonymous about 4 years ago

Something I tried with JavaScript:

function defaultGravatarInitials() {
  let messages;
  if (document.getElementsByClassName('message reply') !== null) { // DOM selection stuff bla bla bla... too tedious...
      messages = document.getElementsByClassName('message reply');
      for (let i = 0; i < messages.length; i++) {
        let grabMD5hash = messages[i].children[1].children[0].src;
        let extractedMD5 = grabMD5hash.substring(grabMD5hash.lastIndexOf("/") + 1, grabMD5hash.lastIndexOf("?"));
        let stringToHex = (parseInt(parseInt(extractedMD5, 36).toExponential().slice(2,-5), 10) & 0xFFFFFF).toString(16).toUpperCase();
        let linkToCheck = messages[i].children[1].children[0].src + "404";
        let imgBlock = messages[i].children[1].children[0];
        let userName = encodeURI(messages[i].children[1].children[2].innerText);
        imgBlock.src += ("https%3A%2F%2Fui-avatars.com%2Fapi%2F/" + userName + "/128/" + stringToHex);
      }
    }
}

If Redmine had Usernames/Names + Lastnames (depending of what user has set in their Admin panel) in ALT or TITLE tag of each generated Avatar IMG container. Then we could ditch the selections of type

messages[i].children[1].children[0]
and just grab the data from the tag of the same container which is corresponding to the class.

Disclaimer: this currently only works on the "message reply" class DIV block which is on the forum.

#5 Updated by Go MAEDA about 4 years ago

Although it is a nice feature, I think that implementing ui-avatars.com in Redmine has a privacy issue. To get an image of initial from ui-avatars.com, Redmine has to send a user's name or an initial to the external site. Some people probably think it as a leakage of private information.

For example, suppose that Mao Zedong, a historical figure in China, is using Redmine. His full name in the Chinese language is "毛泽东" and its initial is "毛泽". Many Chinese people's names are consists of two or three characters.

I think sending his initial to external sites can be considered as private information because the Redmine send 66.6% of information of his full name.

I think that Redmine must display a warning about private information leakage when a user is to set the default gravatar icon to initials of ui-avatar.com.

#6 Updated by Kit Grose about 4 years ago

I agree with the privacy concern, and would certainly much prefer this was done natively by Redmine than off to a third party service.

The implementation above in JS also doesn’t compute the foreground colour to ensure contrast is maintained, and will often produce unpleasant colours; something like the color-hash library can improve that.

#7 Updated by Anonymous about 4 years ago

While libraries are amazing, I'm a fan of implementing native solutions, unless I need to implement something very quick. I believe that libs are bad for performance, so I'll add the improved code soon, and also, in addition, alternative function with self generated solution which uses HTTP requests to check for 404 replies. :)

#8 Updated by Anonymous almost 4 years ago

Inserting the improved code for testing, if somebody has time, by all means feel free to share feedback.
Known problems:
  • I didn't yet figure out how to force stretch text along the size of the avatar block.
  • Works almost everywhere except the places where there is no ".user.active" block and on gravatars with child.

#9 Updated by Anonymous almost 4 years ago

A working patch is ready. The code now generates canvas objects with avatar initials and substitutes src attribute values with generated canvas objects.
This is also working in IE11, but most likely not in IE10, because I'm not sure I remember IE10 supporting canvas objects with 2d 3d/webgl context.

Now, gravatar.rb-title-attrib-test.patch is however not final, and got me a little confused. If somebody could just help me by setting the user's username or full first and last name into the title tag of all the gravatar class objects, I would be very thankful, because currently it sets user's email, and it's not cool.. and I have no idea how to conveniently retrieve the author name without altering more than half of the views of redmine :D

#10 Updated by Marius BALTEANU almost 4 years ago

  • Assignee set to Marius BALTEANU

Max Johansson wrote:

Now, gravatar.rb-title-attrib-test.patch is however not final, and got me a little confused. If somebody could just help me by setting the user's username or full first and last name into the title tag of all the gravatar class objects, I would be very thankful, because currently it sets user's email, and it's not cool.. and I have no idea how to conveniently retrieve the author name without altering more than half of the views of redmine :D

I will take a look.

#11 Updated by Anonymous almost 4 years ago

We could also optimize the consistency by not feeding the gravatar function with the avatar sizes inside the views (to request the size from gravatar.com), instead, we probably need to set gravatar links to always fetch 128px avatar, or 256px avatar, and then introduce 3 or 4 avatar sizes in CSS: like gravatar.big, gravatar.medium, gravatar.small, gravatar.tiny where we will set sizes, and then append an avatar size class to gravatar class containers of an each view instead.
Theme developers will then have the control over gravatar containers and also their size attributes in CSS.

The JS script I wrote could also then be optimized further by not having to generate initials canvas object for each individual avatar, it could just generate it for the first object of the sorted JSON array (where it stores avatar objects, belonging to the same person, console.log(buffer); for more details) and further on just replace it for all objects found under the keys. Now it has to do it for each individual avatar because it has to generate the avatar with the same size as the original which it first gets from the avatar image. It could just generate 1 size for all the objects of each key, like 256px and then just apply it to all the objects of the key. The scaling would then be done by CSS.

#12 Updated by Marius BALTEANU over 3 years ago

I really like to add this to the core, but I'm not sure how it should work because there are some options to implement it:

1. The initial proposal to show the user initials when the Gravatar service returns 404, but this mean that the options from Default Gravatar image (Monster ids, Mystery man, etc) do not make sense anymore and we should remove the setting.
2. Add option "User initials" to "Default Gravatar image" and let administrators decide what to show when the user doesn't have an image.
3. Add "User initials" as default user avatar (even when the Gravatar is disabled) with one of the above implementation.

@Bernhard Rohloff, @Go Maeda, what are your thoughts on this? I personally prefer the option 3 with 1, those default images provided by the gravatar service do not add to much value. Any other feedback is welcome.

#13 Updated by Go MAEDA over 3 years ago

I prefer option 2 for privacy reason. An admin should be able to decide whether to send characters extracted from user names to ui-avatars.com.

As I wrote in #29824#note-5, the names of people in East Asian countries such as Japan, China, and Korea consist of only a few letters. For example, my name in Japanese is "前田剛". In this case, 2/3 of the characters ("前" and "剛") that make up my name will be sent when generating an initial avatar. This may be a privacy problem.

In my opinion, Redmine must not send such information to external sites unless explicitly authorized by admin.

#14 Updated by Marius BALTEANU over 3 years ago

Go MAEDA wrote:

I prefer option 2 for privacy reason. An admin should be able to decide whether to send characters extracted from user names to ui-avatars.com.

As I wrote in #29824#note-5, the names of people in East Asian countries such as Japan, China, and Korea consist of only a few letters. For example, my name in Japanese is "前田剛". In this case, 2/3 of the characters ("前" and "剛") that make up my name will be sent when generating an initial avatar. This may be a privacy problem.

In my opinion, Redmine must not send such information to external sites unless explicitly authorized by admin.

We won't use ui-avatars.com or any other external service, it will be our own implementation using some CSS and JS.

#15 Updated by Anonymous about 3 years ago

@Marius, I also think 3 with 1 will be the best. I can confirm the patch from #29824#note-9 still kind of works ok on latest trunk, but it could be far alot faster with rendering if a script wouldn't have to care much about the sizes of gravatar images, to generate the images of the same exact size as a source ones, if sizes would be constrained in CSS instead of right away getting specific sizes returned from gravatar.com

#16 Updated by Felix Schäfer over 1 year ago

We would be interested in such a feature, would it be possible to restart the conversation for this feature for the next major release?

We have implemented something similar but as far as I know as inline svg as a background to the avatar places. This makes it a default when no gravatar or similar service is defined and doesn't require JS to work. Furthermore, the background colours for the initials avatars could be defined using CSS classes so that themes can define their own set of colours.

If this is a solution that would find consensus we can work on extracting it and providing a core patch for it.

#17 Updated by Marius BALTEANU over 1 year ago

Thanks Felix for your proposal, please see below my thoughts.

Felix Schäfer wrote:

We would be interested in such a feature, would it be possible to restart the conversation for this feature for the next major release?

I'm in favour of restarting the conversation and I still think that it good be a nice addition for the core. Also, it should simplify our CSS if we don't have anymore a layout without avatars.

We have implemented something similar but as far as I know as inline svg as a background to the avatar places. This makes it a default when no gravatar or similar service is defined and doesn't require JS to work. Furthermore, the background colours for the initials avatars could be defined using CSS classes so that themes can define their own set of colours.

Sounds good to me and I really like a solution without JS.

If this is a solution that would find consensus we can work on extracting it and providing a core patch for it.

Yes, extracting and posting here the patch for sure will help us moving this forward.

#18 Updated by Bernhard Rohloff over 1 year ago

Felix Schäfer wrote:

We would be interested in such a feature, would it be possible to restart the conversation for this feature for the next major release?

I think it would be awesome if we could ship this feature within the 5.0.0 release.

#19 Updated by Marius BALTEANU 10 months ago

Felix Schäfer wrote:

We would be interested in such a feature, would it be possible to restart the conversation for this feature for the next major release?

We have implemented something similar but as far as I know as inline svg as a background to the avatar places. This makes it a default when no gravatar or similar service is defined and doesn't require JS to work. Furthermore, the background colours for the initials avatars could be defined using CSS classes so that themes can define their own set of colours.

If this is a solution that would find consensus we can work on extracting it and providing a core patch for it.

Felix, is your offer still available? Redmine 5.0.0 is a good candidate for this change.

#20 Updated by Felix Schäfer 10 months ago

Marius BALTEANU wrote:

Felix, is your offer still available? Redmine 5.0.0 is a good candidate for this change.

Yes, sorry I did not follow up on your previous request.

I won't have time to look into this before the second half of February at the earliest though. I'm not sure what the timeline for 5.0.0 is, maybe waiting for this would push the release back too much?

#21 Updated by Marius BALTEANU 10 months ago

Felix Schäfer wrote:

Marius BALTEANU wrote:

Felix, is your offer still available? Redmine 5.0.0 is a good candidate for this change.

Yes, sorry I did not follow up on your previous request.

I won't have time to look into this before the second half of February at the earliest though. I'm not sure what the timeline for 5.0.0 is, maybe waiting for this would push the release back too much?

Thanks Felix for your quick response. For sure we won't wait for this feature in order to release 5.0.0, but most probably we will do this in March.

#22 Updated by Felix Schäfer 9 months ago

I'm sorry for the delay, I have been ill for the last two weeks.

Unfortunately the solution we currently use on Planio doesn't translate well as is depending on the requirements we have before getting this in core. I have reworked it to allow for the background colours of the initials avatars to be set via CSS.

I have attached a basic patch to show how this would work in principle. There would be a new option (or it could replace the "no gravatar" option) for avatars in the settings (not implemented in the patch. When this setting is active, an SVG image with up to 2 letters would be generated inline as a background for all avatars and a class set that would allow to set the background color of the avatar in CSS. Those colours would be overridable by themes.

2 problems I see with the current patch:
  • the case where there is no gravatar for the user and only the background image is rendered shifts the rendered layout, sadly my CSS knowledge does not suffice to fix this
  • the background colour will probably show through transparent gravatars, I have no idea either how to avoid that.
The other way to achieve the same result but has different trade-offs would be to implement a URL where the SVG would be rendered and to pass the SVG as a fallback in the gravatar URL. This has some advantages:
  • no issues with gravatars with transparent parts and the background color for the initials avatar as the initials avatar would be inserted only if there is no gravatar configured for the user
  • probably no issues with the layout as the image would be added as a normal image and not as a background image
There are however some disadvantages:
  • included svg images cannot be styled with CSS, i.e. the URL for the initials SVG would need to either include the initials and a code for the color, or the initials SVG URL would need to be user/principal-specific
  • the colours could therefore not be customised from theme CSS and another way would need to be found to set custom colours for themes if this is a goal
  • this would leak either the initials and color code or the user/principal-URL to the gravatar service.

Any thoughts?

#23 Updated by Marius BALTEANU 9 months ago

Thanks Felix!

I tried your patch with some local changes and it looks great, it's a good starting point.

As you said, the main issue with this approach is only for users that have a picture with transparent background and I don't know how to easility fix this. What I'm thinking as options:
1. Call the gravatar service with default=404 and show the initials avatar only if the request returns 404 using the onerror attribute and some javascript. The downside of this approach is the 404 request in browser which may confuse some users.

2. Call the gravatar service from the backend and render the initials avatar only when the request returns 404. This approach is very clean from my point of view, but requires to cache the gravatar image for a specific time in order to not introduce performance issues.

The fallback in the gravatar URL is not an option for private instances because the gravatar service won't be able to get the image.

On more thought is to show the initials avatar only when gravatar is disabled from administration and have more time to properly implement this with gravatar.

Also available in: Atom PDF