[IMPROVE] React Avatar Provider (#19321)
parent
dea45516db
commit
e416a32338
@ -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; |
||||||
|
Loading…
Reference in new issue