[IMPROVE] React Avatar Provider (#19321)

pull/19297/head^2
Guilherme Gazzo 5 years ago committed by GitHub
parent dea45516db
commit e416a32338
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      client/components/basic/avatar/RoomAvatar.js
  2. 18
      client/components/basic/avatar/UserAvatar.js
  3. 18
      client/contexts/AvatarUrlContext.ts
  4. 27
      client/providers/AvatarUrlProvider.tsx
  5. 9
      client/providers/MeteorProvider.js
  6. 1
      definition/IUser.ts

@ -1,10 +1,11 @@
import React from 'react'; import React from 'react';
import { roomTypes } from '../../../../app/utils/client';
import BaseAvatar from './BaseAvatar'; import BaseAvatar from './BaseAvatar';
import { useRoomAvatarPath } from '../../../contexts/AvatarUrlContext';
function RoomAvatar({ room: { type, ...room }, ...rest }) { function RoomAvatar({ room, ...rest }) {
const { url = roomTypes.getConfig(type).getAvatarPath({ username: room._id, ...room }), ...props } = rest; const getRoomPathAvatar = useRoomAvatarPath();
const { url = getRoomPathAvatar(room), ...props } = rest;
return <BaseAvatar url={url} {...props}/>; return <BaseAvatar url={url} {...props}/>;
} }

@ -1,20 +1,12 @@
import React from 'react'; import React from 'react';
import BaseAvatar from './BaseAvatar'; import BaseAvatar from './BaseAvatar';
import { useSetting } from '../../../contexts/SettingsContext'; import { useUserAvatarPath } from '../../../contexts/AvatarUrlContext';
function UserAvatar({ url, username, etag, ...props }) { function UserAvatar({ username, etag, ...rest }) {
// NOW, `username` and `etag` props are enough to determine the whole state of const getUserAvatarPath = useUserAvatarPath();
// this component, but it must be as performatic as possible as it will be const { url = getUserAvatarPath(username, etag), ...props } = rest;
// rendered many times; and some of the state can be derived at the ancestors. return <BaseAvatar url={url} title={username} {...props}/>;
// 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}/>;
} }
export default UserAvatar; export default UserAvatar;

@ -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;

@ -1,13 +1,26 @@
import React, { FC, useMemo } from 'react'; import React, { useMemo, FC } from 'react';
import { Avatar } from '@rocket.chat/fuselage';
// import { baseURI } from '../../app/utils/client/lib/baseuri'; import { useSetting } from '../contexts/SettingsContext';
import { AvatarUrlContext } from '../contexts/AvatarUrlContext';
// const base = baseURI; import { roomTypes } from '../../app/utils/client';
const AvatarUrlProvider: FC = ({ children }) => { const AvatarUrlProvider: FC = ({ children }) => {
const avatarBase = useMemo(() => ({ baseUrl: '' }), []); const cdnAvatarUrl = String(useSetting('CDN_PREFIX') || '');
return <Avatar.Context.Provider children={children} value={avatarBase} />; 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; export default AvatarUrlProvider;

@ -14,6 +14,7 @@ import ToastMessagesProvider from './ToastMessagesProvider';
import TranslationProvider from './TranslationProvider'; import TranslationProvider from './TranslationProvider';
import UserProvider from './UserProvider'; import UserProvider from './UserProvider';
function MeteorProvider({ children }) { function MeteorProvider({ children }) {
return <ConnectionStatusProvider> return <ConnectionStatusProvider>
<ServerProvider> <ServerProvider>
@ -23,8 +24,8 @@ function MeteorProvider({ children }) {
<SidebarProvider> <SidebarProvider>
<ToastMessagesProvider> <ToastMessagesProvider>
<SettingsProvider> <SettingsProvider>
<CustomSoundProvider> <AvatarUrlProvider>
<AvatarUrlProvider> <CustomSoundProvider>
<UserProvider> <UserProvider>
<AuthorizationProvider> <AuthorizationProvider>
<ModalProvider> <ModalProvider>
@ -32,8 +33,8 @@ function MeteorProvider({ children }) {
</ModalProvider> </ModalProvider>
</AuthorizationProvider> </AuthorizationProvider>
</UserProvider> </UserProvider>
</AvatarUrlProvider> </CustomSoundProvider>
</CustomSoundProvider> </AvatarUrlProvider>
</SettingsProvider> </SettingsProvider>
</ToastMessagesProvider> </ToastMessagesProvider>
</SidebarProvider> </SidebarProvider>

@ -84,6 +84,7 @@ export interface IRole {
export interface IUser { export interface IUser {
_id: string; _id: string;
avatarETag: string;
createdAt: Date; createdAt: Date;
roles: string[]; roles: string[];
type: string; type: string;

Loading…
Cancel
Save