-
Notifications
You must be signed in to change notification settings - Fork 30
/
UserAvatar.tsx
114 lines (91 loc) · 3.16 KB
/
UserAvatar.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import React, { useMemo } from "react";
import classNames from "classnames";
import { isEqual } from "lodash";
import { DEFAULT_PARTY_NAME, DEFAULT_PROFILE_IMAGE } from "settings";
import { User, UsernameVisibility } from "types/User";
import { WithId } from "utils/id";
import { useRecentWorldUsers } from "hooks/users";
import { useVenueUserStatuses } from "hooks/useVenueUserStatuses";
import { useVenueId } from "hooks/useVenueId";
import "./UserAvatar.scss";
export type UserAvatarSize = "small" | "medium" | "large" | "full";
export interface UserAvatarProps {
user?: WithId<User>;
containerClassName?: string;
imageClassName?: string;
showNametag?: UsernameVisibility;
showStatus?: boolean;
onClick?: () => void;
size?: UserAvatarSize;
}
// @debt the UserProfilePicture component serves a very similar purpose to this, we should unify them as much as possible
export const _UserAvatar: React.FC<UserAvatarProps> = ({
user,
containerClassName,
imageClassName,
showNametag,
onClick,
showStatus,
size,
}) => {
const venueId = useVenueId();
const { recentWorldUsers } = useRecentWorldUsers();
const {
userStatus,
venueUserStatuses,
isStatusEnabledForVenue,
} = useVenueUserStatuses(venueId, user);
const avatarSrc: string = user?.anonMode
? DEFAULT_PROFILE_IMAGE
: user?.pictureUrl ?? DEFAULT_PROFILE_IMAGE;
const userDisplayName: string = user?.anonMode
? DEFAULT_PARTY_NAME
: user?.partyName ?? DEFAULT_PARTY_NAME;
const containerClasses = classNames("UserAvatar", containerClassName, {
"UserAvatar--clickable": onClick !== undefined,
[`UserAvatar--${size}`]: size,
});
const isOnline = useMemo(
() => recentWorldUsers.find((worldUser) => worldUser.id === user?.id),
[user, recentWorldUsers]
);
const status = user?.status;
const nametagClasses = classNames("UserAvatar__nametag", {
"UserAvatar__nametag--hover": showNametag === UsernameVisibility.hover,
});
const imageClasses = classNames("UserAvatar__image", imageClassName);
const statusIndicatorClasses = classNames("UserAvatar__status-indicator", {
"UserAvatar__status-indicator--online": isOnline,
[`UserAvatar__status-indicator--${status}`]: isOnline && status,
[`UserAvatar__status-indicator--${size}`]: size,
});
const statusIndicatorStyles = useMemo(
() => ({ backgroundColor: userStatus.color }),
[userStatus.color]
);
//'isStatusEnabledForVenue' checks if the user status is enabled from the venue config.
//'showStatus' is used to render this conditionally only in some of the screens.
const hasUserStatus =
isStatusEnabledForVenue &&
showStatus &&
isOnline &&
!!venueUserStatuses.length;
return (
<div className={containerClasses}>
{showNametag && <div className={nametagClasses}>{user?.partyName}</div>}
<img
className={imageClasses}
src={avatarSrc}
alt={`${userDisplayName}'s avatar`}
onClick={onClick}
/>
{hasUserStatus && (
<span
className={statusIndicatorClasses}
style={statusIndicatorStyles}
/>
)}
</div>
);
};
export const UserAvatar = React.memo(_UserAvatar, isEqual);