Fixes read receipt avatar offset (#11483)

* Fixes read receipt avatar offset

Fixes https://github.com/vector-im/element-web/issues/26059

* Fix avatar collapsing in thread list

Fixes https://github.com/vector-im/element-web/issues/26064

* Make composer pills use new avatar design

Fixes https://github.com/vector-im/element-web/issues/26067

* Update snapshots

* Update UserInfo snapshot

* Update HTMLExport snapshot

* Fixes avatar placeholder font

Fixes https://github.com/vector-im/element-web/issues/26061
This commit is contained in:
Germain 2023-08-30 12:47:35 +01:00 committed by GitHub
parent 6cc42b7e2e
commit 6aa86a858f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 132 additions and 20 deletions

View file

@ -15,12 +15,21 @@ limitations under the License.
*/
import { RoomMember, User, Room, ResizeMethod } from "matrix-js-sdk/src/matrix";
import { useIdColorHash } from "@vector-im/compound-web";
import DMRoomMap from "./utils/DMRoomMap";
import { mediaFromMxc } from "./customisations/Media";
import { isLocalRoom } from "./utils/localRoom/isLocalRoom";
import { getFirstGrapheme } from "./utils/strings";
/**
* Hardcoded from the Compound colors.
* Shade for background as defined in the compound web implementation
* https://github.com/vector-im/compound-web/blob/main/src/components/Avatar
*/
const AVATAR_BG_COLORS = ["#e9f2ff", "#faeefb", "#e3f7ed", "#ffecf0", "#ffefe4", "#e3f5f8", "#f1efff", "#e0f8d9"];
const AVATAR_TEXT_COLORS = ["#043894", "#671481", "#004933", "#7e0642", "#850000", "#004077", "#4c05b5", "#004b00"];
// Not to be used for BaseAvatar urls as that has similar default avatar fallback already
export function avatarUrlForMember(
member: RoomMember | undefined,
@ -41,6 +50,18 @@ export function avatarUrlForMember(
return url;
}
/**
* Determines the HEX color to use in the avatar pills
* @param id the user or room ID
* @returns the text color to use on the avatar
*/
export function getAvatarTextColor(id: string): string {
// eslint-disable-next-line react-hooks/rules-of-hooks
const index = useIdColorHash(id);
return AVATAR_TEXT_COLORS[index - 1];
}
export function avatarUrlForUser(
user: Pick<User, "avatarUrl">,
width: number,
@ -85,16 +106,12 @@ const colorToDataURLCache = new Map<string, string>();
export function defaultAvatarUrlForString(s: string): string {
if (!s) return ""; // XXX: should never happen but empirically does by evidence of a rageshake
const defaultColors = ["#0DBD8B", "#368bd6", "#ac3ba8"];
let total = 0;
for (let i = 0; i < s.length; ++i) {
total += s.charCodeAt(i);
}
const colorIndex = total % defaultColors.length;
// eslint-disable-next-line react-hooks/rules-of-hooks
const colorIndex = useIdColorHash(s);
// overwritten color value in custom themes
const cssVariable = `--avatar-background-colors_${colorIndex}`;
const cssValue = getComputedStyle(document.body).getPropertyValue(cssVariable);
const color = cssValue || defaultColors[colorIndex];
const color = cssValue || AVATAR_BG_COLORS[colorIndex - 1];
let dataUrl = colorToDataURLCache.get(color);
if (!dataUrl) {
// validate color as this can come from account_data

View file

@ -99,7 +99,7 @@ const BaseAvatar: React.FC<IProps> = (props) => {
const {
name,
idName,
title,
title = "",
url,
urls,
size = "40px",

View file

@ -84,6 +84,25 @@ export function getMentionDisplayText(completion: ICompletion, client: MatrixCli
return "";
}
function getCSSProperties({
url,
initialLetter,
id = "",
}: {
url: string;
initialLetter?: string;
id: string;
}): string {
const cssProperties = [`--avatar-background: url(${url})`, `--avatar-letter: '${initialLetter}'`];
const textColor = Avatar.getAvatarTextColor(id);
if (textColor) {
cssProperties.push(textColor);
}
return cssProperties.join("; ");
}
/**
* For a given completion, the attributes will change depending on the completion type
*
@ -118,7 +137,14 @@ export function getMentionAttributes(
}
attributes.set("data-mention-type", completion.type);
attributes.set("style", `--avatar-background: url(${avatarUrl}); --avatar-letter: '${initialLetter}'`);
attributes.set(
"style",
getCSSProperties({
url: avatarUrl,
initialLetter,
id: mentionedMember.userId,
}),
);
} else if (completion.type === "room") {
// logic as used in RoomPillPart.setAvatar in parts.ts
const mentionedRoom = getRoomFromCompletion(completion, client);
@ -132,7 +158,14 @@ export function getMentionAttributes(
}
attributes.set("data-mention-type", completion.type);
attributes.set("style", `--avatar-background: url(${avatarUrl}); --avatar-letter: '${initialLetter}'`);
attributes.set(
"style",
getCSSProperties({
url: avatarUrl,
initialLetter,
id: mentionedRoom?.roomId ?? aliasFromCompletion,
}),
);
} else if (completion.type === "at-room") {
// logic as used in RoomPillPart.setAvatar in parts.ts, but now we know the current room
// from the arguments passed
@ -145,7 +178,14 @@ export function getMentionAttributes(
}
attributes.set("data-mention-type", completion.type);
attributes.set("style", `--avatar-background: url(${avatarUrl}); --avatar-letter: '${initialLetter}'`);
attributes.set(
"style",
getCSSProperties({
url: avatarUrl,
initialLetter,
id: room.roomId,
}),
);
}
return attributes;