[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 { 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}/>;
}

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

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

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

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

Loading…
Cancel
Save