Changeset View
Standalone View
lib/shared/avatar-utils.js
// @flow | // @flow | ||||
import invariant from 'invariant'; | |||||
import stringHash from 'string-hash'; | import stringHash from 'string-hash'; | ||||
import { selectedThreadColors } from './thread-utils.js'; | import { selectedThreadColors } from './thread-utils.js'; | ||||
import { threadInfoSelector } from '../selectors/thread-selectors.js'; | |||||
import type { ClientEmojiAvatar, ClientAvatar } from '../types/avatar-types.js'; | import type { ClientEmojiAvatar, ClientAvatar } from '../types/avatar-types.js'; | ||||
import { type ThreadType, threadTypes } from '../types/thread-types.js'; | |||||
import { useResolvedOptionalThreadInfo } from '../utils/entity-helpers.js'; | |||||
import { useSelector } from '../utils/redux-utils.js'; | |||||
const defaultAnonymousUserEmojiAvatar: ClientEmojiAvatar = { | const defaultAnonymousUserEmojiAvatar: ClientEmojiAvatar = { | ||||
color: selectedThreadColors[4], | color: selectedThreadColors[4], | ||||
emoji: '👤', | emoji: '👤', | ||||
type: 'emoji', | type: 'emoji', | ||||
}; | }; | ||||
const defaultEmojiAvatars: $ReadOnlyArray<ClientEmojiAvatar> = [ | const defaultEmojiAvatars: $ReadOnlyArray<ClientEmojiAvatar> = [ | ||||
Show All 37 Lines | ): ClientAvatar { | ||||
if (!user?.username) { | if (!user?.username) { | ||||
return defaultAnonymousUserEmojiAvatar; | return defaultAnonymousUserEmojiAvatar; | ||||
} | } | ||||
return getDefaultAvatar(user.username); | return getDefaultAvatar(user.username); | ||||
} | } | ||||
export { getAvatarForUser }; | function useGetAvatarForThread( | ||||
thread: ?{ | |||||
+id: string, | |||||
+type: ThreadType, | |||||
+avatar?: ?ClientAvatar, | |||||
+color: string, | |||||
+parentThreadID: ?string, | |||||
... | |||||
}, | |||||
ashoat: Why aren't we just using `ThreadInfo` or `RawThreadInfo` or `ThreadInfo | RawThreadInfo` here? | |||||
): ClientAvatar { | |||||
const viewer = useSelector(state => state.currentUserInfo); | |||||
const parentThreadID = thread?.parentThreadID; | |||||
const parentThreadInfo = useSelector(state => | |||||
parentThreadID ? threadInfoSelector(state)[parentThreadID] : null, | |||||
); | |||||
const resolvedParentThreadInfo = | |||||
useResolvedOptionalThreadInfo(parentThreadInfo); | |||||
if (!thread) { | |||||
return defaultAnonymousUserEmojiAvatar; | |||||
ashoatUnsubmitted Not Done Inline ActionsWe will need to call this hook regardless of whether we want to use a thread avatar, so it makes sense that the input is optional. However, I'm not sure it makes sense to return defaultAnonymousUserEmojiAvatar... I think it makes sense for the calling component to handle the "default" behavior (Or is this meant as the general-purpose hook for getting an avatar for a thread? If so, why is the input nullable?) ashoat: We will need to call this hook regardless of whether we want to use a thread avatar, so it… | |||||
} | |||||
if (thread.avatar) { | |||||
return thread.avatar; | |||||
} | |||||
if (thread.type === threadTypes.SIDEBAR) { | |||||
ashoatUnsubmitted Not Done Inline ActionsI wonder if we should also default channels to their community's avatar. If so, we could replace this check with a thread.containingThreadID check. For sidebars, containingThreadID is the parent. For other chats, it's the containing community. ashoat: I wonder if we should also default channels to their community's avatar. If so, we could… | |||||
invariant( | |||||
resolvedParentThreadInfo, | |||||
'parentThreadInfo should be set for sidebars', | |||||
); | |||||
return resolvedParentThreadInfo.avatar | |||||
? resolvedParentThreadInfo.avatar | |||||
: getDefaultAvatar( | |||||
resolvedParentThreadInfo.id, | |||||
resolvedParentThreadInfo.color, | |||||
); | |||||
} | |||||
if (thread.type === threadTypes.PRIVATE) { | |||||
return getAvatarForUser(viewer); | |||||
ashoatUnsubmitted Not Done Inline ActionsCurious if we'll need to handle ENS avatar resolution in two places: here (for your PRIVATE thread if you're an ENS user) and the calling component (for PERSONAL 1:1 thread, if the other person is an ENS user). Ideally we can avoid having to call the ENS resolution hook twice. This should be possible to avoid if we handle PERSONAL here. ashoat: Curious if we'll need to handle ENS avatar resolution in two places: here (for your `PRIVATE`… | |||||
} | |||||
return getDefaultAvatar(thread.id, thread.color); | |||||
ashoatUnsubmitted Not Done Inline ActionsDoes PERSONAL get handled here or elsewhere? ashoat: Does `PERSONAL` get handled here or elsewhere? | |||||
} | |||||
export { getAvatarForUser, useGetAvatarForThread }; |
Why aren't we just using ThreadInfo or RawThreadInfo or ThreadInfo | RawThreadInfo here?