render profile banner

This commit is contained in:
Ajay Bura 2026-07-22 12:41:28 +05:30
commit 7dae0fa7cc
4 changed files with 35 additions and 6 deletions

View file

@ -27,9 +27,10 @@ import { LINKIFY_OPTS } from '../../plugins/react-custom-html-parser';
type UserHeroProps = {
userId: string;
avatarUrl?: string;
bannerUrl?: string;
presence?: UserPresence;
};
export function UserHero({ userId, avatarUrl, presence }: UserHeroProps) {
export function UserHero({ userId, avatarUrl, bannerUrl, presence }: UserHeroProps) {
const [viewAvatar, setViewAvatar] = useState<string>();
const { status } = presence ?? {};
@ -40,11 +41,19 @@ export function UserHero({ userId, avatarUrl, presence }: UserHeroProps) {
className={css.UserHeroCoverContainer}
style={{
backgroundColor: colorMXID(userId),
filter: avatarUrl ? undefined : 'brightness(50%)',
filter: bannerUrl && !status ? undefined : 'brightness(50%)',
}}
>
{avatarUrl && (
<img className={css.UserHeroCover} src={avatarUrl} alt={userId} draggable="false" />
{bannerUrl && (
<img
className={classNames(
css.UserHeroCover,
avatarUrl === bannerUrl && css.UserHeroCoverBlurred
)}
src={bannerUrl}
alt={userId}
draggable="false"
/>
)}
</div>
<div className={css.UserHeroAvatarContainer}>

View file

@ -32,6 +32,7 @@ import {
usePowerLevelTags,
usePowerLevelTagsState,
} from '../../hooks/usePowerLevelTags';
import { useUserProfile } from '../../hooks/useUserProfile';
type UserRoomProfileProps = {
userId: string;
@ -74,6 +75,11 @@ export function UserRoomProfile({ userId }: UserRoomProfileProps) {
: undefined;
const presence = useUserPresence(userId);
const profile = useUserProfile(userId);
const bannerUrl = profile?.bannerUrl
? mxcToHttp(ct.session.baseUrl, profile.bannerUrl, useAuthentication).url()
: avatarUrl;
const handleMessage = () => {
closeUserRoomProfile();
@ -90,6 +96,7 @@ export function UserRoomProfile({ userId }: UserRoomProfileProps) {
<UserHero
userId={userId}
avatarUrl={avatarUrl}
bannerUrl={bannerUrl}
presence={presence && presence.lastActiveTs !== 0 ? presence : undefined}
/>
<Box direction="Column" gap="500" style={{ padding: config.space.S400 }}>

View file

@ -15,13 +15,15 @@ export const UserHero = style({
});
export const UserHeroCoverContainer = style({
height: toRem(96),
height: toRem(113),
overflow: 'hidden',
});
export const UserHeroCover = style({
height: '100%',
width: '100%',
objectFit: 'cover',
});
export const UserHeroCoverBlurred = style({
filter: 'blur(16px)',
transform: 'scale(2)',
});

View file

@ -7,6 +7,8 @@ import { useClient } from './useClient';
export type UserProfile = {
avatarUrl?: string;
displayName?: string;
bannerUrl?: string;
timezone?: string;
};
export const useUserProfile = (userId: string): UserProfile | undefined => {
const ct = useClient();
@ -18,10 +20,19 @@ export const useUserProfile = (userId: string): UserProfile | undefined => {
})
);
const [, profile] = await parseMatrixResp<GetProfileOK>(response);
const [, profile] = await parseMatrixResp<
GetProfileOK & {
'chat.commet.profile_banner'?: string;
'm.banner_url'?: string;
'm.tz'?: string;
}
>(response);
return {
avatarUrl: profile?.avatar_url || undefined,
displayName: profile?.displayname || undefined,
bannerUrl: profile?.['m.banner_url'] ?? profile?.['chat.commet.profile_banner'] ?? undefined,
timezone: profile?.['m.tz'] ?? undefined,
};
}, [ct, userId]);