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 3 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