mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-04-17 23:34:14 +01:00
Send remote mute requests in group calls and call links
This commit is contained in:
@@ -13,7 +13,7 @@ import { ThemeType } from '../types/Util.std.js';
|
||||
import { Theme } from '../util/theme.std.js';
|
||||
import { UserText } from './UserText.dom.js';
|
||||
import { SharedGroupNames } from './SharedGroupNames.dom.js';
|
||||
import type { ContactModalStateType } from '../state/ducks/globalModals.preload.js';
|
||||
import type { ContactModalStateType } from '../types/globalModals.std.js';
|
||||
|
||||
export type CallLinkPendingParticipantModalProps = {
|
||||
readonly i18n: LocalizerType;
|
||||
|
||||
@@ -60,6 +60,7 @@ import {
|
||||
import type { NotificationProfileType } from '../types/NotificationProfile.std.js';
|
||||
import { strictAssert } from '../util/assert.std.js';
|
||||
import type { SetLocalPreviewContainerType } from '../services/calling.preload.js';
|
||||
import type { ContactModalStateType } from '../types/globalModals.std.js';
|
||||
|
||||
const { noop } = lodash;
|
||||
|
||||
@@ -107,7 +108,7 @@ export type PropsType = {
|
||||
renderReactionPicker: (
|
||||
props: React.ComponentProps<typeof SmartReactionPicker>
|
||||
) => React.JSX.Element;
|
||||
showContactModal: (contactId: string, conversationId?: string) => void;
|
||||
showContactModal: (payload: ContactModalStateType) => void;
|
||||
startCall: (payload: StartCallType) => void;
|
||||
toggleParticipants: () => void;
|
||||
acceptCall: (_: AcceptCallType) => void;
|
||||
|
||||
@@ -21,6 +21,7 @@ import { Button } from './Button.dom.js';
|
||||
import { Modal } from './Modal.dom.js';
|
||||
import { Theme } from '../util/theme.std.js';
|
||||
import { ConfirmationDialog } from './ConfirmationDialog.dom.js';
|
||||
import type { ContactModalStateType } from '../types/globalModals.std.js';
|
||||
|
||||
const { partition } = lodash;
|
||||
|
||||
@@ -46,10 +47,7 @@ export type PropsType = {
|
||||
readonly onShareCallLinkViaSignal: () => void;
|
||||
readonly removeClient: (payload: RemoveClientType) => void;
|
||||
readonly blockClient: (payload: RemoveClientType) => void;
|
||||
readonly showContactModal: (
|
||||
contactId: string,
|
||||
conversationId?: string
|
||||
) => void;
|
||||
readonly showContactModal: (payload: ContactModalStateType) => void;
|
||||
};
|
||||
|
||||
type UnknownContactsPropsType = {
|
||||
@@ -204,7 +202,10 @@ export function CallingAdhocCallInfo({
|
||||
}
|
||||
|
||||
onClose();
|
||||
showContactModal(participant.id);
|
||||
showContactModal({
|
||||
activeCallDemuxId: participant.demuxId,
|
||||
contactId: participant.id,
|
||||
});
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
|
||||
@@ -16,12 +16,14 @@ import { sortByTitle } from '../util/sortByTitle.std.js';
|
||||
import type { ConversationType } from '../state/ducks/conversations.preload.js';
|
||||
import { isInSystemContacts } from '../util/isInSystemContacts.std.js';
|
||||
import { ModalContainerContext } from './ModalHost.dom.js';
|
||||
import type { ContactModalStateType } from '../types/globalModals.std.js';
|
||||
|
||||
type ParticipantType = ConversationType & {
|
||||
hasRemoteAudio?: boolean;
|
||||
hasRemoteVideo?: boolean;
|
||||
isHandRaised?: boolean;
|
||||
presenting?: boolean;
|
||||
demuxId?: number;
|
||||
};
|
||||
|
||||
export type PropsType = {
|
||||
@@ -30,10 +32,7 @@ export type PropsType = {
|
||||
readonly onClose: () => void;
|
||||
readonly ourServiceId: ServiceIdString | undefined;
|
||||
readonly participants: Array<ParticipantType>;
|
||||
readonly showContactModal: (
|
||||
contactId: string,
|
||||
conversationId?: string
|
||||
) => void;
|
||||
readonly showContactModal: (payload: ContactModalStateType) => void;
|
||||
};
|
||||
|
||||
export const CallingParticipantsList = React.memo(
|
||||
@@ -119,7 +118,11 @@ export const CallingParticipantsList = React.memo(
|
||||
}
|
||||
|
||||
onClose();
|
||||
showContactModal(participant.id, conversationId);
|
||||
showContactModal({
|
||||
activeCallDemuxId: participant.demuxId,
|
||||
contactId: participant.id,
|
||||
conversationId,
|
||||
});
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
import React from 'react';
|
||||
import type {
|
||||
CallQualitySurveyPropsType,
|
||||
ContactModalStateType,
|
||||
DeleteMessagesPropsType,
|
||||
EditHistoryMessagesType,
|
||||
EditNicknameAndNoteModalPropsType,
|
||||
@@ -15,7 +14,10 @@ import type {
|
||||
UserNotFoundModalStateType,
|
||||
} from '../state/ducks/globalModals.preload.js';
|
||||
import type { LocalizerType, ThemeType } from '../types/Util.std.js';
|
||||
import { UsernameOnboardingState } from '../types/globalModals.std.js';
|
||||
import {
|
||||
type ContactModalStateType,
|
||||
UsernameOnboardingState,
|
||||
} from '../types/globalModals.std.js';
|
||||
import { missingCaseError } from '../util/missingCaseError.std.js';
|
||||
|
||||
import { ButtonVariant } from './Button.dom.js';
|
||||
|
||||
@@ -53,6 +53,7 @@ import { arrow } from '../util/keyboard.dom.js';
|
||||
import { StoryProgressSegment } from './StoryProgressSegment.dom.js';
|
||||
import type { EmojiSkinTone } from './fun/data/emojis.std.js';
|
||||
import type { FunEmojiSelection } from './fun/panels/FunPanelEmojis.dom.js';
|
||||
import type { ContactModalStateType } from '../types/globalModals.std.js';
|
||||
|
||||
const log = createLogger('StoryViewer');
|
||||
|
||||
@@ -110,7 +111,7 @@ export type PropsType = {
|
||||
retryMessageSend: (messageId: string) => unknown;
|
||||
saveAttachment: SaveAttachmentActionCreatorType;
|
||||
setHasAllStoriesUnmuted: (isUnmuted: boolean) => unknown;
|
||||
showContactModal: (contactId: string, conversationId?: string) => void;
|
||||
showContactModal: (payload: ContactModalStateType) => void;
|
||||
showToast: ShowToastAction;
|
||||
emojiSkinToneDefault: EmojiSkinTone | null;
|
||||
story: StoryViewType;
|
||||
|
||||
@@ -45,6 +45,7 @@ import { useConfirmDiscard } from '../hooks/useConfirmDiscard.dom.js';
|
||||
import { AxoContextMenu } from '../axo/AxoContextMenu.dom.js';
|
||||
import type { AxoMenuBuilder } from '../axo/AxoMenuBuilder.dom.js';
|
||||
import { drop } from '../util/drop.std.js';
|
||||
import type { ContactModalStateType } from '../types/globalModals.std.js';
|
||||
|
||||
const { noop, orderBy } = lodash;
|
||||
|
||||
@@ -124,7 +125,7 @@ export type PropsType = {
|
||||
ourConversationId: string | undefined;
|
||||
preferredReactionEmoji: ReadonlyArray<string>;
|
||||
replies: ReadonlyArray<ReplyType>;
|
||||
showContactModal: (contactId: string, conversationId?: string) => void;
|
||||
showContactModal: (payload: ContactModalStateType) => void;
|
||||
emojiSkinToneDefault: EmojiSkinTone | null;
|
||||
sortedGroupMembers?: ReadonlyArray<ConversationType>;
|
||||
views: ReadonlyArray<StorySendStateType>;
|
||||
@@ -545,7 +546,7 @@ type ReplyOrReactionMessageProps = {
|
||||
reply: ReplyType;
|
||||
shouldCollapseAbove: boolean;
|
||||
shouldCollapseBelow: boolean;
|
||||
showContactModal: (contactId: string, conversationId?: string) => void;
|
||||
showContactModal: (payload: ContactModalStateType) => void;
|
||||
messageExpanded: (messageId: string, displayLimit: number) => void;
|
||||
showSpoiler: (messageId: string, data: Record<number, boolean>) => void;
|
||||
};
|
||||
|
||||
@@ -37,6 +37,7 @@ export default {
|
||||
},
|
||||
args: {
|
||||
i18n,
|
||||
activeCallDemuxId: undefined,
|
||||
areWeASubscriber: false,
|
||||
areWeAdmin: false,
|
||||
badges: [],
|
||||
@@ -51,6 +52,8 @@ export default {
|
||||
hideContactModal: action('hideContactModal'),
|
||||
isAdmin: false,
|
||||
isMember: true,
|
||||
isMuted: false,
|
||||
isRemoteMuteVisible: false,
|
||||
onOutgoingAudioCallInConversation: action(
|
||||
'onOutgoingAudioCallInConversation'
|
||||
),
|
||||
@@ -58,6 +61,7 @@ export default {
|
||||
'onOutgoingVideoCallInConversation'
|
||||
),
|
||||
removeMemberFromGroup: action('removeMemberFromGroup'),
|
||||
sendRemoteMute: action('sendRemoteMute'),
|
||||
showConversation: action('showConversation'),
|
||||
startAvatarDownload: action('startAvatarDownload'),
|
||||
theme: ThemeType.light,
|
||||
@@ -188,3 +192,19 @@ export const InAnotherCall = Template.bind({});
|
||||
InAnotherCall.args = {
|
||||
hasActiveCall: true,
|
||||
};
|
||||
|
||||
export const InCallTogether = Template.bind({});
|
||||
InCallTogether.args = {
|
||||
activeCallDemuxId: 123,
|
||||
hasActiveCall: true,
|
||||
isMuted: false,
|
||||
isRemoteMuteVisible: true,
|
||||
};
|
||||
|
||||
export const InCallTogetherMuted = Template.bind({});
|
||||
InCallTogetherMuted.args = {
|
||||
activeCallDemuxId: 123,
|
||||
hasActiveCall: true,
|
||||
isMuted: true,
|
||||
isRemoteMuteVisible: true,
|
||||
};
|
||||
|
||||
@@ -31,18 +31,20 @@ import {
|
||||
InAnotherCallTooltip,
|
||||
getTooltipContent,
|
||||
} from './InAnotherCallTooltip.dom.js';
|
||||
import type {
|
||||
ContactModalStateType,
|
||||
ToggleGroupMemberLabelInfoModalType,
|
||||
} from '../../state/ducks/globalModals.preload.js';
|
||||
import type { ToggleGroupMemberLabelInfoModalType } from '../../state/ducks/globalModals.preload.js';
|
||||
import type { ContactModalStateType } from '../../types/globalModals.std.js';
|
||||
import { GroupMemberLabel } from './ContactName.dom.js';
|
||||
import { SignalService as Proto } from '../../protobuf/index.std.js';
|
||||
import { AxoSymbol } from '../../axo/AxoSymbol.dom.js';
|
||||
import { tw } from '../../axo/tw.dom.js';
|
||||
import { strictAssert } from '../../util/assert.std.js';
|
||||
|
||||
const ACCESS_ENUM = Proto.AccessControl.AccessRequired;
|
||||
|
||||
const log = createLogger('ContactModal');
|
||||
|
||||
export type PropsDataType = {
|
||||
activeCallDemuxId?: number;
|
||||
areWeASubscriber: boolean;
|
||||
areWeAdmin: boolean;
|
||||
badges: ReadonlyArray<BadgeType>;
|
||||
@@ -55,6 +57,8 @@ export type PropsDataType = {
|
||||
readonly i18n: LocalizerType;
|
||||
isAdmin: boolean;
|
||||
isMember: boolean;
|
||||
isMuted: boolean;
|
||||
isRemoteMuteVisible: boolean;
|
||||
theme: ThemeType;
|
||||
hasActiveCall: boolean;
|
||||
isInFullScreenCall: boolean;
|
||||
@@ -67,6 +71,7 @@ type PropsActionType = {
|
||||
onOutgoingAudioCallInConversation: (conversationId: string) => unknown;
|
||||
onOutgoingVideoCallInConversation: (conversationId: string) => unknown;
|
||||
removeMemberFromGroup: (conversationId: string, contactId: string) => void;
|
||||
sendRemoteMute: (demuxId: number) => void;
|
||||
showConversation: ShowConversationType;
|
||||
startAvatarDownload: () => void;
|
||||
toggleAboutContactModal: (options: ContactModalStateType) => unknown;
|
||||
@@ -91,9 +96,11 @@ enum SubModalState {
|
||||
ToggleAdmin = 'ToggleAdmin',
|
||||
MemberRemove = 'MemberRemove',
|
||||
ConfirmingBlock = 'ConfirmingBlock',
|
||||
ConfirmingMute = 'ConfirmingMute',
|
||||
}
|
||||
|
||||
export function ContactModal({
|
||||
activeCallDemuxId,
|
||||
areWeAdmin,
|
||||
areWeASubscriber,
|
||||
badges,
|
||||
@@ -110,10 +117,13 @@ export function ContactModal({
|
||||
i18n,
|
||||
isAdmin,
|
||||
isMember,
|
||||
isMuted,
|
||||
isRemoteMuteVisible,
|
||||
onOpenEditNicknameAndNoteModal,
|
||||
onOutgoingAudioCallInConversation,
|
||||
onOutgoingVideoCallInConversation,
|
||||
removeMemberFromGroup,
|
||||
sendRemoteMute,
|
||||
showConversation,
|
||||
startAvatarDownload,
|
||||
theme,
|
||||
@@ -326,6 +336,33 @@ export function ContactModal({
|
||||
</ConfirmationDialog>
|
||||
);
|
||||
break;
|
||||
case SubModalState.ConfirmingMute:
|
||||
modalNode = (
|
||||
<ConfirmationDialog
|
||||
dialogName="ContactModal.confirmMute"
|
||||
actions={[
|
||||
{
|
||||
text: i18n('icu:ContactModal--confirm-mute-primary-button'),
|
||||
action: () => {
|
||||
strictAssert(
|
||||
activeCallDemuxId != null,
|
||||
'activeCallDemuxId must exist'
|
||||
);
|
||||
hideContactModal();
|
||||
sendRemoteMute(activeCallDemuxId);
|
||||
},
|
||||
style: 'affirmative',
|
||||
},
|
||||
]}
|
||||
i18n={i18n}
|
||||
onClose={() => setSubModalState(SubModalState.None)}
|
||||
>
|
||||
{i18n('icu:ContactModal--confirm-mute-body', {
|
||||
contact: contact.title,
|
||||
})}
|
||||
</ConfirmationDialog>
|
||||
);
|
||||
break;
|
||||
default: {
|
||||
const state: never = subModalState;
|
||||
log.warn(`unexpected ${state}!`);
|
||||
@@ -530,6 +567,19 @@ export function ContactModal({
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
{isRemoteMuteVisible && (
|
||||
<button
|
||||
type="button"
|
||||
className="ContactModal__button"
|
||||
onClick={() => setSubModalState(SubModalState.ConfirmingMute)}
|
||||
disabled={isMuted}
|
||||
>
|
||||
<AxoSymbol.Icon symbol="mic-slash" size={20} label={null} />
|
||||
<span className={tw('ms-[12px]')}>
|
||||
{i18n('icu:ContactModal--mute-audio')}
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{modalNode}
|
||||
</div>
|
||||
|
||||
@@ -20,6 +20,7 @@ import { Button, ButtonVariant } from '../Button.dom.js';
|
||||
import { assertDev } from '../../util/assert.std.js';
|
||||
import { missingCaseError } from '../../util/missingCaseError.std.js';
|
||||
import { isInSystemContacts } from '../../util/isInSystemContacts.std.js';
|
||||
import type { ContactModalStateType } from '../../types/globalModals.std.js';
|
||||
|
||||
export type ReviewPropsType = Readonly<
|
||||
| {
|
||||
@@ -61,7 +62,7 @@ export type PropsType = {
|
||||
getPreferredBadge: PreferredBadgeSelectorType;
|
||||
i18n: LocalizerType;
|
||||
onClose: () => void;
|
||||
showContactModal: (contactId: string, conversationId?: string) => unknown;
|
||||
showContactModal: (payload: ContactModalStateType) => unknown;
|
||||
removeMember: (
|
||||
conversationId: string,
|
||||
memberConversationId: string
|
||||
@@ -253,7 +254,7 @@ export function ContactSpoofingReviewDialog(
|
||||
sharedGroupNames={safe.sharedGroupNames}
|
||||
i18n={i18n}
|
||||
onClick={() => {
|
||||
showContactModal(safe.conversation.id);
|
||||
showContactModal({ contactId: safe.conversation.id });
|
||||
}}
|
||||
theme={theme}
|
||||
isSignalConnection={safe.isSignalConnection}
|
||||
@@ -350,7 +351,9 @@ export function ContactSpoofingReviewDialog(
|
||||
theme={theme}
|
||||
oldName={oldName}
|
||||
onClick={() => {
|
||||
showContactModal(conversationInfo.conversation.id);
|
||||
showContactModal({
|
||||
contactId: conversationInfo.conversation.id,
|
||||
});
|
||||
}}
|
||||
isSignalConnection={isSignalConnection}
|
||||
>
|
||||
|
||||
@@ -18,7 +18,7 @@ import { StoryViewModeType } from '../../types/Stories.std.js';
|
||||
import { Button, ButtonVariant } from '../Button.dom.js';
|
||||
import { SafetyTipsModal } from '../SafetyTipsModal.dom.js';
|
||||
import { I18n } from '../I18n.dom.js';
|
||||
import type { ContactModalStateType } from '../../state/ducks/globalModals.preload.js';
|
||||
import type { ContactModalStateType } from '../../types/globalModals.std.js';
|
||||
|
||||
export type Props = {
|
||||
about?: string;
|
||||
|
||||
@@ -127,6 +127,7 @@ import { useGroupedAndOrderedReactions } from '../../util/groupAndOrderReactions
|
||||
import type { AxoMenuBuilder } from '../../axo/AxoMenuBuilder.dom.js';
|
||||
import type { RenderAudioAttachmentProps } from '../../state/smart/renderAudioAttachment.preload.js';
|
||||
import type { MemberLabelType } from '../../types/GroupMemberLabels.std.js';
|
||||
import type { ContactModalStateType } from '../../types/globalModals.std.js';
|
||||
|
||||
const { drop, take, unescape } = lodash;
|
||||
|
||||
@@ -391,7 +392,7 @@ export type PropsActions = {
|
||||
optionIndexes: ReadonlyArray<number>;
|
||||
}) => void;
|
||||
endPoll: (messageId: string) => void;
|
||||
showContactModal: (contactId: string, conversationId?: string) => void;
|
||||
showContactModal: (payload: ContactModalStateType) => void;
|
||||
showSpoiler: (messageId: string, data: Record<number, boolean>) => void;
|
||||
|
||||
cancelAttachmentDownload: (options: { messageId: string }) => void;
|
||||
@@ -2330,7 +2331,7 @@ export class Message extends React.PureComponent<Props, State> {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
showContactModal(author.id, conversationId);
|
||||
showContactModal({ contactId: author.id, conversationId });
|
||||
}}
|
||||
phoneNumber={author.phoneNumber}
|
||||
profileName={author.profileName}
|
||||
|
||||
@@ -14,6 +14,7 @@ import type { ConversationType } from '../../state/ducks/conversations.preload.j
|
||||
import type { PreferredBadgeSelectorType } from '../../state/selectors/badges.preload.js';
|
||||
import { drop } from '../../util/drop.std.js';
|
||||
import { useReducedMotion } from '../../hooks/useReducedMotion.dom.js';
|
||||
import type { ContactModalStateType } from '../../types/globalModals.std.js';
|
||||
|
||||
const MAX_AVATARS_COUNT = 3;
|
||||
|
||||
@@ -38,7 +39,7 @@ export type TypingBubblePropsType = {
|
||||
lastItemTimestamp: number | undefined;
|
||||
getConversation: (id: string) => ConversationType;
|
||||
getPreferredBadge: PreferredBadgeSelectorType;
|
||||
showContactModal: (contactId: string, conversationId?: string) => void;
|
||||
showContactModal: (payload: ContactModalStateType) => void;
|
||||
i18n: LocalizerType;
|
||||
theme: ThemeType;
|
||||
};
|
||||
@@ -83,7 +84,7 @@ function TypingBubbleAvatar({
|
||||
shouldAnimate: boolean;
|
||||
getPreferredBadge: PreferredBadgeSelectorType;
|
||||
onContactExit: (id: string | undefined) => void;
|
||||
showContactModal: (contactId: string, conversationId?: string) => void;
|
||||
showContactModal: (payload: ContactModalStateType) => void;
|
||||
i18n: LocalizerType;
|
||||
theme: ThemeType;
|
||||
}): ReactElement | null {
|
||||
@@ -130,7 +131,7 @@ function TypingBubbleAvatar({
|
||||
onClick={event => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
showContactModal(contact.id, conversationId);
|
||||
showContactModal({ contactId: contact.id, conversationId });
|
||||
}}
|
||||
phoneNumber={contact.phoneNumber}
|
||||
profileName={contact.profileName}
|
||||
|
||||
@@ -65,7 +65,7 @@ import {
|
||||
getTooltipContent,
|
||||
} from '../InAnotherCallTooltip.dom.js';
|
||||
import { BadgeSustainerInstructionsDialog } from '../../BadgeSustainerInstructionsDialog.dom.js';
|
||||
import type { ContactModalStateType } from '../../../state/ducks/globalModals.preload.js';
|
||||
import type { ContactModalStateType } from '../../../types/globalModals.std.js';
|
||||
import type { ShowToastAction } from '../../../state/ducks/toast.preload.js';
|
||||
import { ToastType } from '../../../types/Toast.dom.js';
|
||||
|
||||
@@ -142,7 +142,7 @@ type ActionProps = {
|
||||
searchInConversation: (id: string) => unknown;
|
||||
setDisappearingMessages: (id: string, seconds: DurationInSeconds) => void;
|
||||
setMuteExpiration: (id: string, muteExpiresAt: undefined | number) => unknown;
|
||||
showContactModal: (contactId: string, conversationId?: string) => void;
|
||||
showContactModal: (payload: ContactModalStateType) => void;
|
||||
showConversation: ShowConversationType;
|
||||
toggleAboutContactModal: (options: ContactModalStateType) => void;
|
||||
toggleAddUserToAnotherGroupModal: (contactId?: string) => void;
|
||||
|
||||
@@ -16,7 +16,7 @@ import type { BadgeType } from '../../../badges/types.std.js';
|
||||
import { UserText } from '../../UserText.dom.js';
|
||||
import { isInSystemContacts } from '../../../util/isInSystemContacts.std.js';
|
||||
import { InContactsIcon } from '../../InContactsIcon.dom.js';
|
||||
import type { ContactModalStateType } from '../../../state/ducks/globalModals.preload.js';
|
||||
import type { ContactModalStateType } from '../../../types/globalModals.std.js';
|
||||
|
||||
export type Props = {
|
||||
areWeASubscriber: boolean;
|
||||
|
||||
@@ -18,6 +18,7 @@ import { PanelRow } from './PanelRow.dom.js';
|
||||
import { PanelSection } from './PanelSection.dom.js';
|
||||
import { GroupMemberLabel } from '../ContactName.dom.js';
|
||||
import { AriaClickable } from '../../../axo/AriaClickable.dom.js';
|
||||
import type { ContactModalStateType } from '../../../types/globalModals.std.js';
|
||||
|
||||
export type GroupV2Membership = {
|
||||
isAdmin: boolean;
|
||||
@@ -36,7 +37,7 @@ export type Props = {
|
||||
maxShownMemberCount?: number;
|
||||
memberships: ReadonlyArray<GroupV2Membership>;
|
||||
memberColors: Map<string, string>;
|
||||
showContactModal: (contactId: string, conversationId?: string) => void;
|
||||
showContactModal: (payload: ContactModalStateType) => void;
|
||||
showLabelEditor: () => void;
|
||||
startAddingNewMembers?: () => void;
|
||||
theme: ThemeType;
|
||||
@@ -129,7 +130,9 @@ export function ConversationDetailsMembershipList({
|
||||
return (
|
||||
<PanelRow
|
||||
key={member.id}
|
||||
onClick={() => showContactModal(member.id, conversationId)}
|
||||
onClick={() =>
|
||||
showContactModal({ contactId: member.id, conversationId })
|
||||
}
|
||||
icon={
|
||||
<Avatar
|
||||
conversationType="direct"
|
||||
|
||||
Reference in New Issue
Block a user