cleanup props passing of avatar and name with a custom hook

This commit is contained in:
Audric Ackermann 2021-11-23 16:18:27 +11:00
parent 5ba7f20162
commit 894349e710
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4
19 changed files with 128 additions and 279 deletions

View File

@ -5,6 +5,7 @@ import { AvatarPlaceHolder, ClosedGroupAvatar } from './AvatarPlaceHolder';
import { useEncryptedFileFetch } from '../hooks/useEncryptedFileFetch';
import _ from 'underscore';
import { useMembersAvatars } from '../hooks/useMembersAvatars';
import { useAvatarPath, useConversationUsername } from '../hooks/useParamSelector';
export enum AvatarSize {
XS = 28,
@ -16,8 +17,8 @@ export enum AvatarSize {
}
type Props = {
avatarPath?: string | null;
name?: string; // display name, profileName or pubkey, whatever is set first
forcedAvatarPath?: string | null;
forcedName?: string;
pubkey?: string;
size: AvatarSize;
base64Data?: string; // if this is not empty, it will be used to render the avatar with base64 encoded data
@ -26,8 +27,8 @@ type Props = {
};
const Identicon = (props: Props) => {
const { size, name, pubkey } = props;
const userName = name || '0';
const { size, forcedName, pubkey } = props;
const userName = forcedName || '0';
return (
<AvatarPlaceHolder
@ -40,14 +41,12 @@ const Identicon = (props: Props) => {
);
};
const NoImage = (props: {
name?: string;
pubkey?: string;
size: AvatarSize;
isClosedGroup: boolean;
onAvatarClick?: () => void;
}) => {
const { name, size, pubkey, isClosedGroup } = props;
const NoImage = (
props: Pick<Props, 'forcedName' | 'size' | 'pubkey' | 'onAvatarClick'> & {
isClosedGroup: boolean;
}
) => {
const { forcedName, size, pubkey, isClosedGroup } = props;
// if no image but we have conversations set for the group, renders group members avatars
if (pubkey && isClosedGroup) {
return (
@ -55,7 +54,7 @@ const NoImage = (props: {
);
}
return <Identicon size={size} name={name} pubkey={pubkey} />;
return <Identicon size={size} forcedName={forcedName} pubkey={pubkey} />;
};
const AvatarImage = (props: {
@ -88,17 +87,21 @@ const AvatarImage = (props: {
};
const AvatarInner = (props: Props) => {
const { avatarPath, base64Data, size, pubkey, name, dataTestId } = props;
const { base64Data, size, pubkey, forcedAvatarPath, forcedName, dataTestId } = props;
const [imageBroken, setImageBroken] = useState(false);
const closedGroupMembers = useMembersAvatars(pubkey);
const avatarPath = useAvatarPath(pubkey);
const name = useConversationUsername(pubkey);
// contentType is not important
const { urlToLoad } = useEncryptedFileFetch(avatarPath || '', '');
const { urlToLoad } = useEncryptedFileFetch(forcedAvatarPath || avatarPath || '', '');
const handleImageError = () => {
window.log.warn(
'Avatar: Image failed to load; failing over to placeholder',
urlToLoad,
avatarPath
forcedAvatarPath || avatarPath
);
setImageBroken(true);
};
@ -127,7 +130,7 @@ const AvatarInner = (props: Props) => {
avatarPath={urlToLoad}
base64Data={base64Data}
imageBroken={imageBroken}
name={name}
name={forcedName || name}
handleImageError={handleImageError}
/>
) : (

View File

@ -11,8 +11,6 @@ type Props = {
function getClosedGroupAvatarsSize(size: AvatarSize): AvatarSize {
// Always use the size directly under the one requested
switch (size) {
case AvatarSize.XS:
return AvatarSize.XS;
case AvatarSize.S:
return AvatarSize.XS;
case AvatarSize.M:
@ -33,25 +31,13 @@ export const ClosedGroupAvatar = (props: Props) => {
const memberAvatars = useMembersAvatars(closedGroupId);
const avatarsDiameter = getClosedGroupAvatarsSize(size);
const firstMember = memberAvatars?.[0];
const secondMember = memberAvatars?.[1];
const firstMemberId = memberAvatars?.[0];
const secondMemberID = memberAvatars?.[1];
return (
<div className="module-avatar__icon-closed">
<Avatar
avatarPath={firstMember?.avatarPath}
name={firstMember?.name}
size={avatarsDiameter}
pubkey={firstMember?.id}
onAvatarClick={onAvatarClick}
/>
<Avatar
avatarPath={secondMember?.avatarPath}
name={secondMember?.name}
size={avatarsDiameter}
pubkey={secondMember?.id}
onAvatarClick={onAvatarClick}
/>
<Avatar size={avatarsDiameter} pubkey={firstMemberId} onAvatarClick={onAvatarClick} />
<Avatar size={avatarsDiameter} pubkey={secondMemberID} onAvatarClick={onAvatarClick} />
</div>
);
};

View File

@ -3,55 +3,43 @@ import classNames from 'classnames';
import { Avatar, AvatarSize } from './Avatar';
import { Emojify } from './conversation/Emojify';
import { useConversationUsername, useIsMe } from '../hooks/useParamSelector';
interface Props {
type Props = {
pubkey: string;
isMe?: boolean;
name?: string;
profileName?: string;
avatarPath?: string;
onClick?: () => void;
}
};
export class ContactListItem extends React.Component<Props> {
public renderAvatar() {
const { avatarPath, name, pubkey, profileName } = this.props;
const AvatarItem = (props: { pubkey: string }) => {
const { pubkey } = props;
const userName = name || profileName || pubkey;
return <Avatar size={AvatarSize.S} pubkey={pubkey} />;
};
return <Avatar avatarPath={avatarPath} name={userName} size={AvatarSize.S} pubkey={pubkey} />;
}
export const ContactListItem = (props: Props) => {
const { onClick, pubkey } = props;
public render() {
const { name, onClick, isMe, pubkey, profileName } = this.props;
const name = useConversationUsername(pubkey);
const isMe = useIsMe(pubkey);
const title = name ? name : pubkey;
const displayName = isMe ? window.i18n('me') : title;
const title = name ? name : pubkey;
const displayName = isMe ? window.i18n('me') : title;
const profileElement =
!isMe && profileName && !name ? (
<span className="module-contact-list-item__text__profile-name">
~
<Emojify text={profileName} key={`emojify-list-item-${pubkey}`} />
</span>
) : null;
return (
<div
role="button"
onClick={onClick}
className={classNames(
'module-contact-list-item',
onClick ? 'module-contact-list-item--with-click-handler' : null
)}
>
{this.renderAvatar()}
<div className="module-contact-list-item__text">
<div className="module-contact-list-item__text__name">
<Emojify text={displayName} /> {profileElement}
</div>
return (
<div
role="button"
onClick={onClick}
className={classNames(
'module-contact-list-item',
onClick ? 'module-contact-list-item--with-click-handler' : null
)}
>
<AvatarItem pubkey={pubkey} />
<div className="module-contact-list-item__text">
<div className="module-contact-list-item__text__name">
<Emojify text={displayName} />
</div>
</div>
);
}
}
</div>
);
};

View File

@ -26,6 +26,7 @@ import { SectionType } from '../state/ducks/section';
import { getFocusedSection } from '../state/selectors/section';
import { ConversationNotificationSettingType } from '../models/conversation';
import { updateUserDetailsModal } from '../state/ducks/modalDialog';
import { useAvatarPath, useConversationUsername, useIsMe } from '../hooks/useParamSelector';
// tslint:disable-next-line: no-empty-interface
export interface ConversationListItemProps extends ReduxConversationType {}
@ -52,11 +53,8 @@ const Portal = ({ children }: { children: any }) => {
const HeaderItem = (props: {
unreadCount: number;
isMe: boolean;
mentionedUs: boolean;
activeAt?: number;
name?: string;
profileName?: string;
conversationId: string;
isPinned: boolean;
currentNotificationSetting: ConversationNotificationSettingType;
@ -65,11 +63,8 @@ const HeaderItem = (props: {
unreadCount,
mentionedUs,
activeAt,
isMe,
isPinned,
conversationId,
profileName,
name,
currentNotificationSetting,
} = props;
@ -116,12 +111,7 @@ const HeaderItem = (props: {
unreadCount > 0 ? 'module-conversation-list-item__header__name--with-unread' : null
)}
>
<UserItem
isMe={isMe}
conversationId={conversationId}
name={name}
profileName={profileName}
/>
<UserItem conversationId={conversationId} />
</div>
<StyledConversationListItemIconWrapper>
@ -143,21 +133,18 @@ const HeaderItem = (props: {
);
};
const UserItem = (props: {
name?: string;
profileName?: string;
isMe: boolean;
conversationId: string;
}) => {
const { name, conversationId, profileName, isMe } = props;
const UserItem = (props: { conversationId: string }) => {
const { conversationId } = props;
const shortenedPubkey = PubKey.shorten(conversationId);
const isMe = useIsMe(conversationId);
const username = useConversationUsername(conversationId);
const displayedPubkey = profileName ? shortenedPubkey : conversationId;
const displayName = isMe ? window.i18n('noteToSelf') : profileName;
const displayedPubkey = username ? shortenedPubkey : conversationId;
const displayName = isMe ? window.i18n('noteToSelf') : username;
let shouldShowPubkey = false;
if ((!name || name.length === 0) && (!displayName || displayName.length === 0)) {
if ((!username || username.length === 0) && (!displayName || displayName.length === 0)) {
shouldShowPubkey = true;
}
@ -165,7 +152,7 @@ const UserItem = (props: {
<div className="module-conversation__user">
<ContactName
pubkey={displayedPubkey}
name={name}
name={username}
profileName={displayName}
module="module-conversation__user"
boldProfileName={true}
@ -212,22 +199,15 @@ const MessageItem = (props: {
);
};
const AvatarItem = (props: {
avatarPath: string | null;
conversationId: string;
name?: string;
profileName?: string;
isPrivate: boolean;
}) => {
const { avatarPath, name, isPrivate, conversationId, profileName } = props;
const userName = name || profileName || conversationId;
const AvatarItem = (props: { conversationId: string; isPrivate: boolean }) => {
const { isPrivate, conversationId } = props;
const userName = useConversationUsername(conversationId);
const avatarPath = useAvatarPath(conversationId);
const dispatch = useDispatch();
return (
<div className="module-conversation-list-item__avatar-container">
<Avatar
avatarPath={avatarPath}
name={userName}
size={AvatarSize.S}
pubkey={conversationId}
onAvatarClick={() => {
@ -235,7 +215,7 @@ const AvatarItem = (props: {
dispatch(
updateUserDetailsModal({
conversationId: conversationId,
userName,
userName: userName || '',
authorAvatarPath: avatarPath,
})
);
@ -256,9 +236,7 @@ const ConversationListItem = (props: Props) => {
style,
mentionedUs,
isMe,
name,
isPinned,
profileName,
isTyping,
lastMessage,
hasNickname,
@ -309,23 +287,14 @@ const ConversationListItem = (props: Props) => {
isBlocked ? 'module-conversation-list-item--is-blocked' : null
)}
>
<AvatarItem
conversationId={conversationId}
avatarPath={avatarPath || null}
profileName={profileName}
name={name}
isPrivate={isPrivate || false}
/>
<AvatarItem conversationId={conversationId} isPrivate={isPrivate || false} />
<div className="module-conversation-list-item__content">
<HeaderItem
mentionedUs={!!mentionedUs}
unreadCount={unreadCount || 0}
activeAt={activeAt}
isMe={!!isMe}
isPinned={!!isPinned}
conversationId={conversationId}
name={name}
profileName={profileName}
currentNotificationSetting={currentNotificationSetting || 'all'}
/>
<MessageItem
@ -349,8 +318,6 @@ const ConversationListItem = (props: Props) => {
type={type}
currentNotificationSetting={currentNotificationSetting || 'all'}
avatarPath={avatarPath || null}
name={name}
profileName={profileName}
/>
</Portal>
</div>

View File

@ -162,26 +162,20 @@ const ExpirationLength = (props: { expirationSettingName?: string }) => {
};
const AvatarHeader = (props: {
avatarPath: string | null;
name?: string;
pubkey: string;
profileName?: string;
showBackButton: boolean;
onAvatarClick?: (pubkey: string) => void;
}) => {
const { avatarPath, name, pubkey, profileName } = props;
const userName = name || profileName || pubkey;
const { pubkey, onAvatarClick, showBackButton } = props;
return (
<span className="module-conversation-header__avatar">
<Avatar
avatarPath={avatarPath}
name={userName}
size={AvatarSize.S}
onAvatarClick={() => {
// do not allow right panel to appear if another button is shown on the SessionConversation
if (props.onAvatarClick && !props.showBackButton) {
props.onAvatarClick(pubkey);
if (onAvatarClick && !showBackButton) {
onAvatarClick(pubkey);
}
}}
pubkey={pubkey}
@ -393,9 +387,6 @@ export const ConversationHeaderWithDetails = () => {
}}
pubkey={conversationKey}
showBackButton={isMessageDetailOpened}
avatarPath={avatarPath}
name={name}
profileName={profileName}
/>
</>
)}

View File

@ -13,11 +13,10 @@ import {
} from '../../state/selectors/conversations';
import { deleteMessagesById } from '../../interactions/conversations/unsendingInteractions';
const AvatarItem = (props: { contact: ContactPropsMessageDetail }) => {
const { avatarPath, pubkey, name, profileName } = props.contact;
const userName = name || profileName || pubkey;
const AvatarItem = (props: { pubkey: string | undefined }) => {
const { pubkey } = props;
return <Avatar avatarPath={avatarPath} name={userName} size={AvatarSize.S} pubkey={pubkey} />;
return <Avatar size={AvatarSize.S} pubkey={pubkey} />;
};
const DeleteButtonItem = (props: { messageId: string; convoId: string; isDeletable: boolean }) => {
@ -68,7 +67,7 @@ const ContactItem = (props: { contact: ContactPropsMessageDetail }) => {
return (
<div key={contact.pubkey} className="module-message-detail__contact">
<AvatarItem contact={contact} />
<AvatarItem pubkey={contact.pubkey} />
<div className="module-message-detail__contact__text">
<div className="module-message-detail__contact__name">
<ContactName

View File

@ -62,13 +62,7 @@ export const MessageAvatar = (props: Props) => {
return (
<div className="module-message__author-avatar" key={`msg-avatar-${authorPhoneNumber}`}>
<Avatar
avatarPath={authorAvatarPath}
name={userName}
size={AvatarSize.S}
onAvatarClick={onMessageAvatarClick}
pubkey={authorPhoneNumber}
/>
<Avatar size={AvatarSize.S} onAvatarClick={onMessageAvatarClick} pubkey={authorPhoneNumber} />
{isPublic && isSenderAdmin && (
<div className="module-avatar__icon--crown-wrapper">
<div className="module-avatar__icon--crown" />

View File

@ -246,7 +246,12 @@ export class EditProfileDialog extends React.Component<{}, State> {
const userName = profileName || this.convo.id;
return (
<Avatar avatarPath={avatar} name={userName} size={AvatarSize.XL} pubkey={this.convo.id} />
<Avatar
forcedAvatarPath={avatar}
forcedName={userName}
size={AvatarSize.XL}
pubkey={this.convo.id}
/>
);
}

View File

@ -191,7 +191,7 @@ export class UpdateGroupNameDialog extends React.Component<Props, State> {
return (
<div className="avatar-center">
<div className="avatar-center-inner">
<Avatar avatarPath={this.state.avatar || ''} size={AvatarSize.XL} pubkey={pubkey} />
<Avatar forcedAvatarPath={this.state.avatar || ''} size={AvatarSize.XL} pubkey={pubkey} />
<div
className="image-upload-section"
role="button"

View File

@ -25,7 +25,6 @@ export const UserDetailsDialog = (props: Props) => {
const convo = getConversationController().get(props.conversationId);
const size = isEnlargedImageShown ? AvatarSize.HUGE : AvatarSize.XL;
const userName = props.userName || props.conversationId;
const [_, copyToClipboard] = useCopyToClipboard();
@ -57,8 +56,6 @@ export const UserDetailsDialog = (props: Props) => {
<div className="avatar-center">
<div className="avatar-center-inner">
<Avatar
avatarPath={props.authorAvatarPath}
name={userName}
size={size}
onAvatarClick={() => {
setIsEnlargedImageShown(!isEnlargedImageShown);

View File

@ -50,11 +50,11 @@ import { DraggableCallContainer } from './calling/DraggableCallContainer';
import { IncomingCallDialog } from './calling/IncomingCallDialog';
import { CallInFullScreenContainer } from './calling/CallInFullScreenContainer';
const Section = (props: { type: SectionType; avatarPath?: string | null }) => {
const Section = (props: { type: SectionType }) => {
const ourNumber = useSelector(getOurNumber);
const unreadMessageCount = useSelector(getUnreadMessageCount);
const dispatch = useDispatch();
const { type, avatarPath } = props;
const { type } = props;
const focusedSection = useSelector(getFocusedSection);
const isSelected = focusedSection === props.type;
@ -85,16 +85,10 @@ const Section = (props: { type: SectionType; avatarPath?: string | null }) => {
};
if (type === SectionType.Profile) {
const conversation = getConversationController().get(ourNumber);
const profile = conversation?.getLokiProfile();
const userName = (profile && profile.displayName) || ourNumber;
return (
<Avatar
avatarPath={avatarPath}
size={AvatarSize.XS}
onAvatarClick={handleClick}
name={userName}
pubkey={ourNumber}
dataTestId="leftpane-primary-avatar"
/>
@ -287,12 +281,7 @@ export const ActionsPanel = () => {
return () => clearTimeout(timeout);
}, []);
useInterval(
() => {
cleanUpOldDecryptedMedias();
},
startCleanUpMedia ? cleanUpMediasInterval : null
);
useInterval(cleanUpOldDecryptedMedias, startCleanUpMedia ? cleanUpMediasInterval : null);
if (!ourPrimaryConversation) {
window?.log?.warn('ActionsPanel: ourPrimaryConversation is not set');
@ -328,7 +317,7 @@ export const ActionsPanel = () => {
className="module-left-pane__sections-container"
data-testid="leftpane-section-container"
>
<Section type={SectionType.Profile} avatarPath={ourPrimaryConversation.avatarPath} />
<Section type={SectionType.Profile} />
<Section type={SectionType.Message} />
<Section type={SectionType.Contact} />
<Section type={SectionType.Settings} />

View File

@ -23,37 +23,17 @@ type Props = {
isSelected: boolean;
// this bool is used to make a zombie appear with less opacity than a normal member
isZombie?: boolean;
onSelect?: any;
onUnselect?: any;
onSelect?: (selectedMember: ContactType) => void;
onUnselect?: (selectedMember: ContactType) => void;
};
const AvatarItem = (props: { memberPubkey?: string }) => {
return <Avatar size={AvatarSize.XS} pubkey={props.memberPubkey} />;
};
export const SessionMemberListItem = (props: Props) => {
const { isSelected, member, isZombie, onSelect, onUnselect } = props;
const renderAvatar = () => {
const { authorAvatarPath, authorName, authorPhoneNumber, authorProfileName } = member;
const userName = authorName || authorProfileName || authorPhoneNumber;
return (
<Avatar
avatarPath={authorAvatarPath}
name={userName}
size={AvatarSize.XS}
pubkey={authorPhoneNumber}
/>
);
};
const selectMember = () => {
onSelect?.(member);
};
const unselectMember = () => {
onUnselect?.(member);
};
const handleSelectionAction = () => {
isSelected ? unselectMember() : selectMember();
};
const name = member.authorProfileName || PubKey.shorten(member.authorPhoneNumber);
return (
@ -64,11 +44,15 @@ export const SessionMemberListItem = (props: Props) => {
isSelected && 'selected',
isZombie && 'zombie'
)}
onClick={handleSelectionAction}
onClick={() => {
isSelected ? onUnselect?.(member) : onSelect?.(member);
}}
role="button"
>
<div className="session-member-item__info">
<span className="session-member-item__avatar">{renderAvatar()}</span>
<span className="session-member-item__avatar">
<AvatarItem memberPubkey={member.id} />
</span>
<span className="session-member-item__name">{name}</span>
</div>
<span className={classNames('session-member-item__checkmark', isSelected && 'selected')}>

View File

@ -9,7 +9,6 @@ import { getHasOngoingCall, getHasOngoingCallWith } from '../../../state/selecto
import { openConversationWithMessages } from '../../../state/ducks/conversations';
import { Avatar, AvatarSize } from '../../Avatar';
import { useVideoCallEventsListener } from '../../../hooks/useVideoEventListener';
import { useAvatarPath, useConversationUsername } from '../../../hooks/useParamSelector';
import { VideoLoadingSpinner } from './InConversationCallContainer';
export const DraggableCallWindow = styled.div`
@ -77,8 +76,6 @@ export const DraggableCallContainer = () => {
'DraggableCallContainer',
false
);
const ongoingCallUsername = useConversationUsername(ongoingCallPubkey);
const avatarPath = useAvatarPath(ongoingCallPubkey);
const videoRefRemote = useRef<HTMLVideoElement>(null);
function onWindowResize() {
@ -140,12 +137,7 @@ export const DraggableCallContainer = () => {
/>
{remoteStreamVideoIsMuted && (
<CenteredAvatarInDraggable>
<Avatar
size={AvatarSize.XL}
avatarPath={avatarPath}
name={ongoingCallUsername}
pubkey={ongoingCallPubkey}
/>
<Avatar size={AvatarSize.XL} pubkey={ongoingCallPubkey} />
</CenteredAvatarInDraggable>
)}
</DraggableCallWindowInner>

View File

@ -6,7 +6,6 @@ import _ from 'underscore';
import { UserUtils } from '../../../session/utils';
import {
getCallIsInFullScreen,
getHasOngoingCallWith,
getHasOngoingCallWithFocusedConvo,
getHasOngoingCallWithFocusedConvoIsOffering,
getHasOngoingCallWithFocusedConvosIsConnecting,
@ -16,11 +15,6 @@ import { StyledVideoElement } from './DraggableCallContainer';
import { Avatar, AvatarSize } from '../../Avatar';
import { useVideoCallEventsListener } from '../../../hooks/useVideoEventListener';
import {
useAvatarPath,
useOurAvatarPath,
useOurConversationUsername,
} from '../../../hooks/useParamSelector';
import { useModuloWithTripleDots } from '../../../hooks/useModuloWithTripleDots';
import { CallWindowControls } from './CallButtons';
import { SessionSpinner } from '../SessionSpinner';
@ -118,23 +112,15 @@ export const VideoLoadingSpinner = (props: { fullWidth: boolean }) => {
// tslint:disable-next-line: max-func-body-length
export const InConversationCallContainer = () => {
const ongoingCallProps = useSelector(getHasOngoingCallWith);
const isInFullScreen = useSelector(getCallIsInFullScreen);
const ongoingCallPubkey = useSelector(getHasOngoingCallWithPubkey);
const ongoingCallWithFocused = useSelector(getHasOngoingCallWithFocusedConvo);
const ongoingCallUsername = ongoingCallProps?.profileName || ongoingCallProps?.name;
const videoRefRemote = useRef<HTMLVideoElement>(null);
const videoRefLocal = useRef<HTMLVideoElement>(null);
const ourPubkey = UserUtils.getOurPubKeyStrFromCache();
const remoteAvatarPath = useAvatarPath(ongoingCallPubkey);
const ourAvatarPath = useOurAvatarPath();
const ourUsername = useOurConversationUsername();
const {
currentConnectedAudioInputs,
currentConnectedCameras,
@ -190,12 +176,7 @@ export const InConversationCallContainer = () => {
/>
{remoteStreamVideoIsMuted && (
<CenteredAvatarInConversation>
<Avatar
size={AvatarSize.XL}
avatarPath={remoteAvatarPath}
name={ongoingCallUsername}
pubkey={ongoingCallPubkey}
/>
<Avatar size={AvatarSize.XL} pubkey={ongoingCallPubkey} />
</CenteredAvatarInConversation>
)}
</VideoContainer>
@ -208,12 +189,7 @@ export const InConversationCallContainer = () => {
/>
{localStreamVideoIsMuted && (
<CenteredAvatarInConversation>
<Avatar
size={AvatarSize.XL}
avatarPath={ourAvatarPath}
name={ourUsername}
pubkey={ourPubkey}
/>
<Avatar size={AvatarSize.XL} pubkey={ourPubkey} />
</CenteredAvatarInConversation>
)}
</VideoContainer>

View File

@ -3,7 +3,7 @@ import { useSelector } from 'react-redux';
import styled from 'styled-components';
import _ from 'underscore';
import { useAvatarPath, useConversationUsername } from '../../../hooks/useParamSelector';
import { useConversationUsername } from '../../../hooks/useParamSelector';
import { ed25519Str } from '../../../session/onions/onionPath';
import { CallManager } from '../../../session/utils';
import { getHasIncomingCall, getHasIncomingCallFrom } from '../../../state/selectors/call';
@ -70,7 +70,6 @@ export const IncomingCallDialog = () => {
}
};
const from = useConversationUsername(incomingCallFromPubkey);
const incomingAvatar = useAvatarPath(incomingCallFromPubkey);
if (!hasIncomingCall) {
return null;
}
@ -79,12 +78,7 @@ export const IncomingCallDialog = () => {
return (
<SessionWrapperModal title={window.i18n('incomingCallFrom', from)}>
<IncomingCallAvatatContainer>
<Avatar
size={AvatarSize.XL}
avatarPath={incomingAvatar}
name={from}
pubkey={incomingCallFromPubkey}
/>
<Avatar size={AvatarSize.XL} pubkey={incomingCallFromPubkey} />
</IncomingCallAvatatContainer>
<div className="session-modal__button-group">
<SessionButton

View File

@ -113,19 +113,9 @@ const HeaderItem = () => {
if (!selectedConversation) {
return null;
}
const {
avatarPath,
id,
isGroup,
isKickedFromGroup,
profileName,
isBlocked,
left,
name,
} = selectedConversation;
const { id, isGroup, isKickedFromGroup, isBlocked, left } = selectedConversation;
const showInviteContacts = isGroup && !isKickedFromGroup && !isBlocked && !left;
const userName = name || profileName || id;
return (
<div className="group-settings-header">
@ -137,7 +127,7 @@ const HeaderItem = () => {
dispatch(closeRightPanel());
}}
/>
<Avatar avatarPath={avatarPath || ''} name={userName} size={AvatarSize.XL} pubkey={id} />
<Avatar size={AvatarSize.XL} pubkey={id} />
<div className="invite-friends-container">
{showInviteContacts && (
<SessionIconButton

View File

@ -1,6 +1,7 @@
import React from 'react';
import { animation, Menu } from 'react-contexify';
import _ from 'underscore';
import { useAvatarPath, useConversationUsername } from '../../../hooks/useParamSelector';
import {
ConversationNotificationSettingType,
ConversationTypeEnum,
@ -34,8 +35,6 @@ export type PropsContextConversationItem = {
left: boolean;
theme?: any;
currentNotificationSetting: ConversationNotificationSettingType;
name: string | undefined;
profileName: string | undefined;
avatarPath: string | null;
};
@ -52,13 +51,12 @@ const ConversationListItemContextMenu = (props: PropsContextConversationItem) =>
isKickedFromGroup,
currentNotificationSetting,
isPrivate,
name,
profileName,
avatarPath,
} = props;
const isGroup = type === 'group';
const userName = name || profileName || conversationId;
const userName = useConversationUsername(conversationId);
const avatarPath = useAvatarPath(conversationId);
return (
<Menu id={triggerId} animation={animation.fade}>
@ -80,7 +78,7 @@ const ConversationListItemContextMenu = (props: PropsContextConversationItem) =>
{getInviteContactMenuItem(isGroup, isPublic, conversationId)}
{getDeleteContactMenuItem(isGroup, isPublic, left, isKickedFromGroup, conversationId)}
{getLeaveGroupMenuItem(isKickedFromGroup, left, isGroup, isPublic, conversationId)}
{getShowUserDetailsMenuItem(isPrivate, conversationId, avatarPath, userName)}
{getShowUserDetailsMenuItem(isPrivate, conversationId, avatarPath, userName || '')}
</Menu>
);
};

View File

@ -3,16 +3,10 @@ import * as _ from 'lodash';
import { useSelector } from 'react-redux';
import { StateType } from '../state/reducer';
export type ConversationAvatar = {
avatarPath?: string;
id: string; // member's pubkey
name: string;
};
export function useMembersAvatars(closedGroupPubkey: string | undefined) {
const ourPrimary = UserUtils.getOurPubKeyStrFromCache();
return useSelector((state: StateType): Array<ConversationAvatar> | undefined => {
return useSelector((state: StateType): Array<string> | undefined => {
if (!closedGroupPubkey) {
return undefined;
}
@ -37,16 +31,7 @@ export function useMembersAvatars(closedGroupPubkey: string | undefined) {
usAtTheEndMaxTwo
.map(m => state.conversations.conversationLookup[m])
.map(m => {
if (!m) {
return undefined;
}
const userName = m.name || m.profileName || m.id;
return {
avatarPath: m.avatarPath || undefined,
id: m.id,
name: userName,
};
return m?.id || undefined;
})
);

View File

@ -5,9 +5,9 @@ import { StateType } from '../state/reducer';
export function useAvatarPath(pubkey: string | undefined) {
return useSelector((state: StateType) => {
if (!pubkey) {
return undefined;
return null;
}
return state.conversations.conversationLookup[pubkey]?.avatarPath;
return state.conversations.conversationLookup[pubkey]?.avatarPath || null;
});
}
@ -15,12 +15,19 @@ export function useOurAvatarPath() {
return useAvatarPath(UserUtils.getOurPubKeyStrFromCache());
}
export function useConversationUsername(pubkey: string | undefined) {
/**
*
* @returns convo.profileName || convo.name || convo.id or undefined if the convo is not found
*/
export function useConversationUsername(pubkey?: string) {
return useSelector((state: StateType) => {
if (!pubkey) {
return undefined;
}
const convo = state.conversations.conversationLookup[pubkey];
if (!convo) {
return pubkey;
}
return convo?.profileName || convo?.name || convo.id;
});
}
@ -28,3 +35,7 @@ export function useConversationUsername(pubkey: string | undefined) {
export function useOurConversationUsername() {
return useConversationUsername(UserUtils.getOurPubKeyStrFromCache());
}
export function useIsMe(pubkey?: string) {
return pubkey && pubkey === UserUtils.getOurPubKeyStrFromCache();
}