Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Make composer pills use new avatar design
Browse files Browse the repository at this point in the history
  • Loading branch information
Germain committed Aug 29, 2023
1 parent 2df6d87 commit 0b7d123
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 14 deletions.
2 changes: 1 addition & 1 deletion res/css/views/rooms/_BasicMessageComposer.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ limitations under the License.
height: $font-16px;
margin-inline-end: 0.24rem;
background: var(--avatar-background), $background;
color: $avatar-initial-color;
color: var(--avatar-color, $avatar-initial-color);
background-repeat: no-repeat;
background-size: $font-16px;
border-radius: $font-16px;
Expand Down
4 changes: 2 additions & 2 deletions res/css/views/rooms/wysiwyg_composer/components/_Editor.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ limitations under the License.
background-size: $font-16px;
border-radius: $font-16px;

color: $avatar-initial-color;
font-weight: normal;
color: var(--avatar-color, $avatar-initial-color);
font-weight: bold;
font-size: $font-10-4px;
}
}
Expand Down
31 changes: 24 additions & 7 deletions src/Avatar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/avatars/BaseAvatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ const BaseAvatar: React.FC<IProps> = (props) => {
const {
name,
idName,
title,
title = "",
url,
urls,
size = "40px",
Expand Down
21 changes: 18 additions & 3 deletions src/components/views/rooms/wysiwyg_composer/utils/autocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,12 @@ export function getMentionAttributes(
}

attributes.set("data-mention-type", completion.type);
attributes.set("style", `--avatar-background: url(${avatarUrl}); --avatar-letter: '${initialLetter}'`);
attributes.set(
"style",
`--avatar-background: url(${avatarUrl}); --avatar-color: ${Avatar.getAvatarTextColor(
mentionedMember.userId,
)}; --avatar-letter: '${initialLetter}'`,
);
} else if (completion.type === "room") {
// logic as used in RoomPillPart.setAvatar in parts.ts
const mentionedRoom = getRoomFromCompletion(completion, client);
Expand All @@ -132,7 +137,12 @@ export function getMentionAttributes(
}

attributes.set("data-mention-type", completion.type);
attributes.set("style", `--avatar-background: url(${avatarUrl}); --avatar-letter: '${initialLetter}'`);
attributes.set(
"style",
`--avatar-background: url(${avatarUrl}); --avatar-color: ${Avatar.getAvatarTextColor(
mentionedRoom?.roomId ?? aliasFromCompletion,
)}; --avatar-letter: '${initialLetter}'`,
);
} 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
Expand All @@ -145,7 +155,12 @@ export function getMentionAttributes(
}

attributes.set("data-mention-type", completion.type);
attributes.set("style", `--avatar-background: url(${avatarUrl}); --avatar-letter: '${initialLetter}'`);
attributes.set(
"style",
`--avatar-background: url(${avatarUrl}); --avatar-color: ${Avatar.getAvatarTextColor(
room.roomId,
)}; --avatar-letter: '${initialLetter}'`,
);
}

return attributes;
Expand Down

0 comments on commit 0b7d123

Please sign in to comment.