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

Revert "Member avatars without canvas" (#10057 #10057

Merged
merged 5 commits into from
Feb 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions cypress/e2e/spaces/spaces.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,10 @@ describe("Spaces", () => {

openSpaceCreateMenu().within(() => {
cy.get(".mx_SpaceCreateMenuType_private").click();
// We don't set an avatar here to get a Percy snapshot of the default avatar style for spaces
cy.get('.mx_SpaceBasicSettings_avatarContainer input[type="file"]').selectFile(
"cypress/fixtures/riot.png",
{ force: true },
);
cy.get('input[label="Address"]').should("not.exist");
cy.get('textarea[label="Description"]').type("This is a personal space to mourn Riot.im...");
cy.get('input[label="Name"]').type("This is my Riot{enter}");
Expand All @@ -166,7 +169,6 @@ describe("Spaces", () => {

cy.contains(".mx_RoomList .mx_RoomTile", "Sample Room").should("exist");
cy.contains(".mx_SpaceHierarchy_list .mx_SpaceHierarchy_roomTile", "Sample Room").should("exist");
cy.get(".mx_LeftPanel_outerWrapper").percySnapshotElement("Left panel with default avatar space");
});

it("should allow user to invite another to a space", () => {
Expand Down
9 changes: 6 additions & 3 deletions res/css/structures/_SpacePanel.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -277,11 +277,14 @@ $activeBorderColor: $primary-content;
.mx_BaseAvatar:not(.mx_UserMenu_userAvatar_BaseAvatar) .mx_BaseAvatar_initial {
color: $secondary-content;
border-radius: 8px;
background-color: $panel-actions;
font-size: $font-15px !important; /* override inline style */
font-weight: $font-semi-bold;
line-height: $font-18px;
/* override inline styles which are part of the default avatar style as these uses a monochrome style */
background-color: $panel-actions !important;
font-size: $font-15px !important;

& + .mx_BaseAvatar_image {
visibility: hidden;
}
}

.mx_SpaceTreeLevel {
Expand Down
11 changes: 10 additions & 1 deletion res/css/views/avatars/_BaseAvatar.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@ limitations under the License.

.mx_BaseAvatar {
position: relative;
display: block;
/* In at least Firefox, the case of relative positioned inline elements */
/* (such as mx_BaseAvatar) with absolute positioned children (such as */
/* mx_BaseAvatar_initial) is a dark corner full of spider webs. It will give */
/* different results during full reflow of the page vs. incremental reflow */
/* of small portions. While that's surely a browser bug, we can avoid it by */
/* using `inline-block` instead of the default `inline`. */
/* https://github.com/vector-im/element-web/issues/5594 */
/* https://bugzilla.mozilla.org/show_bug.cgi?id=1535053 */
/* https://bugzilla.mozilla.org/show_bug.cgi?id=255139 */
display: inline-block;
user-select: none;

&.mx_RoomAvatar_isSpaceRoom {
Expand Down
2 changes: 1 addition & 1 deletion res/css/views/rooms/_BasicMessageComposer.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ limitations under the License.
min-width: $font-16px; /* ensure the avatar is not compressed */
height: $font-16px;
margin-inline-end: 0.24rem;
background: var(--avatar-background);
background: var(--avatar-background), $background;
color: $avatar-initial-color;
background-repeat: no-repeat;
background-size: $font-16px;
Expand Down
64 changes: 23 additions & 41 deletions src/Avatar.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2015, 2016, 2023 The Matrix.org Foundation C.I.C.
Copyright 2015, 2016 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -24,19 +24,16 @@ import DMRoomMap from "./utils/DMRoomMap";
import { mediaFromMxc } from "./customisations/Media";
import { isLocalRoom } from "./utils/localRoom/isLocalRoom";

const DEFAULT_COLORS: Readonly<string[]> = ["#0DBD8B", "#368bd6", "#ac3ba8"];

// Not to be used for BaseAvatar urls as that has similar default avatar fallback already
export function avatarUrlForMember(
member: RoomMember | null | undefined,
member: RoomMember,
width: number,
height: number,
resizeMethod: ResizeMethod,
): string {
let url: string | undefined;
const mxcUrl = member?.getMxcAvatarUrl();
if (mxcUrl) {
url = mediaFromMxc(mxcUrl).getThumbnailOfSourceHttp(width, height, resizeMethod);
let url: string;
if (member?.getMxcAvatarUrl()) {
url = mediaFromMxc(member.getMxcAvatarUrl()).getThumbnailOfSourceHttp(width, height, resizeMethod);
}
if (!url) {
// member can be null here currently since on invites, the JS SDK
Expand All @@ -47,17 +44,6 @@ export function avatarUrlForMember(
return url;
}

export function getMemberAvatar(
member: RoomMember | null | undefined,
width: number,
height: number,
resizeMethod: ResizeMethod,
): string | undefined {
const mxcUrl = member?.getMxcAvatarUrl();
if (!mxcUrl) return undefined;
return mediaFromMxc(mxcUrl).getThumbnailOfSourceHttp(width, height, resizeMethod);
}

export function avatarUrlForUser(
user: Pick<User, "avatarUrl">,
width: number,
Expand Down Expand Up @@ -100,10 +86,18 @@ function urlForColor(color: string): string {
// hard to install a listener here, even if there were a clear event to listen to
const colorToDataURLCache = new Map<string, string>();

export function defaultAvatarUrlForString(s: string | undefined): string {
export function defaultAvatarUrlForString(s: string): string {
if (!s) return ""; // XXX: should never happen but empirically does by evidence of a rageshake

const color = getColorForString(s);
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;
// overwritten color value in custom themes
const cssVariable = `--avatar-background-colors_${colorIndex}`;
const cssValue = document.body.style.getPropertyValue(cssVariable);
const color = cssValue || defaultColors[colorIndex];
let dataUrl = colorToDataURLCache.get(color);
if (!dataUrl) {
// validate color as this can come from account_data
Expand All @@ -118,23 +112,13 @@ export function defaultAvatarUrlForString(s: string | undefined): string {
return dataUrl;
}

export function getColorForString(input: string): string {
const charSum = [...input].reduce((s, c) => s + c.charCodeAt(0), 0);
const index = charSum % DEFAULT_COLORS.length;

// overwritten color value in custom themes
const cssVariable = `--avatar-background-colors_${index}`;
const cssValue = document.body.style.getPropertyValue(cssVariable);
return cssValue || DEFAULT_COLORS[index]!;
}

/**
* returns the first (non-sigil) character of 'name',
* converted to uppercase
* @param {string} name
* @return {string} the first letter
*/
export function getInitialLetter(name: string): string | undefined {
export function getInitialLetter(name: string): string {
if (!name) {
// XXX: We should find out what causes the name to sometimes be falsy.
console.trace("`name` argument to `getInitialLetter` not supplied");
Expand All @@ -150,20 +134,19 @@ export function getInitialLetter(name: string): string | undefined {
}

// rely on the grapheme cluster splitter in lodash so that we don't break apart compound emojis
return split(name, "", 1)[0]!.toUpperCase();
return split(name, "", 1)[0].toUpperCase();
}

export function avatarUrlForRoom(
room: Room | undefined,
room: Room,
width: number,
height: number,
resizeMethod?: ResizeMethod,
): string | null {
if (!room) return null; // null-guard

const mxcUrl = room.getMxcAvatarUrl();
if (mxcUrl) {
return mediaFromMxc(mxcUrl).getThumbnailOfSourceHttp(width, height, resizeMethod);
if (room.getMxcAvatarUrl()) {
return mediaFromMxc(room.getMxcAvatarUrl()).getThumbnailOfSourceHttp(width, height, resizeMethod);
}

// space rooms cannot be DMs so skip the rest
Expand All @@ -176,9 +159,8 @@ export function avatarUrlForRoom(

// If there are only two members in the DM use the avatar of the other member
const otherMember = room.getAvatarFallbackMember();
const otherMemberMxc = otherMember?.getMxcAvatarUrl();
if (otherMemberMxc) {
return mediaFromMxc(otherMemberMxc).getThumbnailOfSourceHttp(width, height, resizeMethod);
if (otherMember?.getMxcAvatarUrl()) {
return mediaFromMxc(otherMember.getMxcAvatarUrl()).getThumbnailOfSourceHttp(width, height, resizeMethod);
}
return null;
}
Loading