import React from 'react'; import styled from 'styled-components'; import { GroupPubkeyType, PubkeyType } from 'libsession_util_nodejs'; import { useNicknameOrProfileNameOrShortenedPubkey } from '../hooks/useParamSelector'; import { PubKey } from '../session/types'; import { UserUtils } from '../session/utils'; import { GroupInvite } from '../session/utils/job_runners/jobs/GroupInviteJob'; import { GroupPromote } from '../session/utils/job_runners/jobs/GroupPromoteJob'; import { useMemberInviteFailed, useMemberInviteSending, useMemberInviteSent, useMemberPromoteSending, useMemberPromotionFailed, useMemberPromotionSent, } from '../state/selectors/groups'; import { Avatar, AvatarSize, CrownIcon } from './avatar/Avatar'; import { Flex } from './basic/Flex'; import { SessionButton, SessionButtonColor, SessionButtonShape, SessionButtonType, } from './basic/SessionButton'; import { SessionRadio } from './basic/SessionRadio'; const AvatarContainer = styled.div` position: relative; `; const AvatarItem = (props: { memberPubkey: string; isAdmin: boolean }) => { const { memberPubkey, isAdmin } = props; return ( {isAdmin && } ); }; const StyledSessionMemberItem = styled.button<{ inMentions?: boolean; zombie?: boolean; selected?: boolean; disableBg?: boolean; }>` cursor: pointer; display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; flex-grow: 1; font-family: var(--font-default); padding: 0px var(--margins-sm); height: ${props => (props.inMentions ? '40px' : '50px')}; width: 100%; transition: var(--default-duration); opacity: ${props => (props.zombie ? 0.5 : 1)}; background-color: ${props => !props.disableBg && props.selected ? 'var(--conversation-tab-background-selected-color) !important' : null}; :not(:last-child) { border-bottom: 1px solid var(--border-color); } `; const StyledInfo = styled.div` display: flex; align-items: center; min-width: 0; `; const StyledName = styled.span` font-weight: bold; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; `; const StyledCheckContainer = styled.div` display: flex; align-items: center; `; type MemberListItemProps = { pubkey: string; isSelected: boolean; // this bool is used to make a zombie appear with less opacity than a normal member isZombie?: boolean; inMentions?: boolean; // set to true if we are rendering members but in the Mentions picker disableBg?: boolean; isAdmin?: boolean; // if true, we add a small crown on top of their avatar onSelect?: (pubkey: string) => void; onUnselect?: (pubkey: string) => void; dataTestId?: React.SessionDataTestId; displayGroupStatus?: boolean; groupPk?: string; }; const ResendContainer = ({ displayGroupStatus, groupPk, pubkey, }: Pick) => { if ( displayGroupStatus && groupPk && PubKey.is03Pubkey(groupPk) && PubKey.is05Pubkey(pubkey) && !UserUtils.isUsFromCache(pubkey) ) { return ( ); } return null; }; const StyledGroupStatusText = styled.span<{ isFailure: boolean }>` color: ${props => (props.isFailure ? 'var(--danger-color)' : 'var(--text-secondary-color)')}; font-size: var(--font-size-xs); margin-top: var(--margins-xs); min-width: 100px; // min-width so that the dialog does not resize when the status change to sending text-align: left; `; const GroupStatusText = ({ groupPk, pubkey }: { pubkey: PubkeyType; groupPk: GroupPubkeyType }) => { const groupInviteFailed = useMemberInviteFailed(pubkey, groupPk); const groupPromotionFailed = useMemberPromotionFailed(pubkey, groupPk); const groupPromotionSending = useMemberPromoteSending(groupPk, pubkey); const groupInviteSent = useMemberInviteSent(pubkey, groupPk); const groupPromotionSent = useMemberPromotionSent(pubkey, groupPk); const groupInviteSending = useMemberInviteSending(groupPk, pubkey); const statusText = groupPromotionFailed ? window.i18n('promotionFailed') : groupInviteFailed ? window.i18n('inviteFailed') : groupInviteSending ? window.i18n('inviteSending') : groupPromotionSending ? window.i18n('promotionSending') : groupInviteSent ? window.i18n('inviteSent') : groupPromotionSent ? window.i18n('promotionSent') : null; if (!statusText) { return null; } return ( {statusText} ); }; const GroupStatusContainer = ({ displayGroupStatus, groupPk, pubkey, }: Pick) => { if ( displayGroupStatus && groupPk && PubKey.is03Pubkey(groupPk) && PubKey.is05Pubkey(pubkey) && !UserUtils.isUsFromCache(pubkey) ) { return ; } return null; }; const ResendInviteButton = ({ groupPk, pubkey, }: { pubkey: PubkeyType; groupPk: GroupPubkeyType; }) => { return ( { void GroupInvite.addJob({ groupPk, member: pubkey }); // TODO audric: do we need to take care if that user was invited withHistory or not }} /> ); }; const ResendPromoteButton = ({ groupPk, pubkey, }: { pubkey: PubkeyType; groupPk: GroupPubkeyType; }) => { return ( { void GroupPromote.addJob({ groupPk, member: pubkey }); }} /> ); }; export const MemberListItem = ({ isSelected, pubkey, dataTestId, disableBg, displayGroupStatus, inMentions, isAdmin, isZombie, onSelect, onUnselect, groupPk, }: MemberListItemProps) => { const memberName = useNicknameOrProfileNameOrShortenedPubkey(pubkey); return ( { // eslint-disable-next-line no-unused-expressions isSelected ? onUnselect?.(pubkey) : onSelect?.(pubkey); }} style={ !inMentions && !disableBg ? { backgroundColor: 'var(--background-primary-color)', } : {} } data-testid={dataTestId} zombie={isZombie} inMentions={inMentions} selected={isSelected} disableBg={disableBg} > {memberName} {!inMentions && ( )} ); };