Skip to content
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
7 changes: 4 additions & 3 deletions client/components/basic/avatar/RoomAvatar.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from 'react';

import { roomTypes } from '../../../../app/utils/client';
import BaseAvatar from './BaseAvatar';
import { useRoomAvatarPath } from '../../../contexts/AvatarUrlContext';

function RoomAvatar({ room: { type, ...room }, ...rest }) {
const { url = roomTypes.getConfig(type).getAvatarPath({ username: room._id, ...room }), ...props } = rest;
function RoomAvatar({ room, ...rest }) {
const getRoomPathAvatar = useRoomAvatarPath();
const { url = getRoomPathAvatar(room), ...props } = rest;
return <BaseAvatar url={url} {...props}/>;
}

Expand Down
18 changes: 5 additions & 13 deletions client/components/basic/avatar/UserAvatar.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
import React from 'react';

import BaseAvatar from './BaseAvatar';
import { useSetting } from '../../../contexts/SettingsContext';
import { useUserAvatarPath } from '../../../contexts/AvatarUrlContext';

function UserAvatar({ url, username, etag, ...props }) {
// NOW, `username` and `etag` props are enough to determine the whole state of
// this component, but it must be as performatic as possible as it will be
// rendered many times; and some of the state can be derived at the ancestors.
// Ideally, it should be a purely visual component.
const externalProviderUrl = useSetting('Accounts_AvatarExternalProviderUrl');

let externalSource = (externalProviderUrl || '').trim().replace(/\/$/, '');
externalSource = externalSource !== '' && externalSource.replace('{username}', username);

const avatarUrl = externalSource || url || `/avatar/${ username }${ etag ? `?etag=${ etag }` : '' }`;
return <BaseAvatar url={avatarUrl} title={username} {...props}/>;
function UserAvatar({ username, etag, ...rest }) {
const getUserAvatarPath = useUserAvatarPath();
const { url = getUserAvatarPath(username, etag), ...props } = rest;
return <BaseAvatar url={url} title={username} {...props}/>;
}

export default UserAvatar;
18 changes: 18 additions & 0 deletions client/contexts/AvatarUrlContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { createContext, useContext } from 'react';

const dummy = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=';

type AvatarContextValue = {
getUserPathAvatar: (uid: string, etag?: string) => string;
getRoomPathAvatar: (...args: any) => string;
}
const AvatarUrlContextValueDefault: AvatarContextValue = {
getUserPathAvatar: () => dummy,
getRoomPathAvatar: () => dummy,
};

export const AvatarUrlContext = createContext<AvatarContextValue>(AvatarUrlContextValueDefault);

export const useRoomAvatarPath = (): (uid: string, etag?: string) => string => useContext(AvatarUrlContext).getRoomPathAvatar;

export const useUserAvatarPath = (): (...args: any) => string => useContext(AvatarUrlContext).getUserPathAvatar;
27 changes: 20 additions & 7 deletions client/providers/AvatarUrlProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import React, { FC, useMemo } from 'react';
import { Avatar } from '@rocket.chat/fuselage';
import React, { useMemo, FC } from 'react';

// import { baseURI } from '../../app/utils/client/lib/baseuri';

// const base = baseURI;
import { useSetting } from '../contexts/SettingsContext';
import { AvatarUrlContext } from '../contexts/AvatarUrlContext';
import { roomTypes } from '../../app/utils/client';

const AvatarUrlProvider: FC = ({ children }) => {
const avatarBase = useMemo(() => ({ baseUrl: '' }), []);
return <Avatar.Context.Provider children={children} value={avatarBase} />;
const cdnAvatarUrl = String(useSetting('CDN_PREFIX') || '');
const externalProviderUrl = String(useSetting('Accounts_AvatarExternalProviderUrl') || '');
const contextValue = useMemo(() => ({
getUserPathAvatar: ((): (uid: string, etag?: string) => string => {
if (externalProviderUrl) {
return (uid: string): string => externalProviderUrl.trim().replace(/\/+$/, '').replace('{username}', uid);
}
if (cdnAvatarUrl) {
return (uid: string, etag?: string): string => `${ cdnAvatarUrl }/avatar/${ uid }${ etag ? `?etag=${ etag }` : '' }`;
}
return (uid: string, etag?: string): string => `/avatar/${ uid }${ etag ? `?etag=${ etag }` : '' }`;
})(),
getRoomPathAvatar: ({ type, ...room }: any): string => roomTypes.getConfig(type || room.t).getAvatarPath({ username: room._id, ...room }),
}), [externalProviderUrl, cdnAvatarUrl]);

return <AvatarUrlContext.Provider children={children} value={contextValue} />;
};

export default AvatarUrlProvider;
9 changes: 5 additions & 4 deletions client/providers/MeteorProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import ToastMessagesProvider from './ToastMessagesProvider';
import TranslationProvider from './TranslationProvider';
import UserProvider from './UserProvider';


function MeteorProvider({ children }) {
return <ConnectionStatusProvider>
<ServerProvider>
Expand All @@ -23,17 +24,17 @@ function MeteorProvider({ children }) {
<SidebarProvider>
<ToastMessagesProvider>
<SettingsProvider>
<CustomSoundProvider>
<AvatarUrlProvider>
<AvatarUrlProvider>
<CustomSoundProvider>
<UserProvider>
<AuthorizationProvider>
<ModalProvider>
{children}
</ModalProvider>
</AuthorizationProvider>
</UserProvider>
</AvatarUrlProvider>
</CustomSoundProvider>
</CustomSoundProvider>
</AvatarUrlProvider>
</SettingsProvider>
</ToastMessagesProvider>
</SidebarProvider>
Expand Down
1 change: 1 addition & 0 deletions definition/IUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export interface IRole {

export interface IUser {
_id: string;
avatarETag: string;
createdAt: Date;
roles: string[];
type: string;
Expand Down