Moves ConversationDetails to react panels

This commit is contained in:
Josh Perez 2022-12-15 22:12:05 -05:00 committed by GitHub
parent ff3ef0179b
commit d4124abb01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 220 additions and 199 deletions

View file

@ -3,7 +3,6 @@
import React from 'react';
import type { Meta, Story } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import type { Props } from './AddUserToAnotherGroupModal';
import enMessages from '../../_locales/en/messages.json';
@ -30,12 +29,8 @@ export default {
i18n: {
defaultValue: i18n,
},
addMemberToGroup: {
defaultValue: action('addMemberToGroup'),
},
toggleAddUserToAnotherGroupModal: {
defaultValue: action('toggleAddUserToAnotherGroupModal'),
},
addMembersToGroup: { action: true },
toggleAddUserToAnotherGroupModal: { action: true },
},
} as Meta;

View file

@ -32,10 +32,13 @@ type OwnProps = {
type DispatchProps = {
toggleAddUserToAnotherGroupModal: (contactId?: string) => void;
addMemberToGroup: (
addMembersToGroup: (
conversationId: string,
contactId: string,
onComplete: () => void
contactIds: Array<string>,
opts: {
onSuccess?: () => unknown;
onFailure?: () => unknown;
}
) => void;
showToast: (toastType: ToastType, parameters?: ReplacementValuesType) => void;
};
@ -47,7 +50,7 @@ export function AddUserToAnotherGroupModal({
theme,
contact,
toggleAddUserToAnotherGroupModal,
addMemberToGroup,
addMembersToGroup,
showToast,
candidateConversations,
regionCode,
@ -203,12 +206,13 @@ export function AddUserToAnotherGroupModal({
showToast(ToastType.AddingUserToGroup, {
contact: contact.title,
});
addMemberToGroup(selectedGroupId, contact.id, () =>
showToast(ToastType.UserAddedToGroup, {
contact: contact.title,
group: selectedGroup.title,
})
);
addMembersToGroup(selectedGroupId, [contact.id], {
onSuccess: () =>
showToast(ToastType.UserAddedToGroup, {
contact: contact.title,
group: selectedGroup.title,
}),
});
toggleAddUserToAnotherGroupModal(undefined);
},
},

View file

@ -37,7 +37,6 @@ const commonProps = {
i18n,
onShowConversationDetails: action('onShowConversationDetails'),
setDisappearingMessages: action('setDisappearingMessages'),
destroyMessages: action('destroyMessages'),
onSearchInConversation: action('onSearchInConversation'),

View file

@ -93,7 +93,6 @@ export type PropsActionsType = {
onOutgoingVideoCallInConversation: (conversationId: string) => void;
onSearchInConversation: () => void;
onShowAllMedia: () => void;
onShowConversationDetails: () => void;
pushPanelForConversation: PushPanelForConversationActionType;
setDisappearingMessages: (
conversationId: string,
@ -352,7 +351,6 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
onMarkUnread,
onMoveToInbox,
onShowAllMedia,
onShowConversationDetails,
pushPanelForConversation,
setDisappearingMessages,
setMuteExpiration,
@ -475,7 +473,13 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
))}
</SubMenu>
{!isGroup || hasGV2AdminEnabled ? (
<MenuItem onClick={onShowConversationDetails}>
<MenuItem
onClick={() =>
pushPanelForConversation(id, {
type: PanelType.ConversationDetails,
})
}
>
{isGroup
? i18n('showConversationDetails')
: i18n('showConversationDetails--direct')}
@ -552,8 +556,13 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
}
private renderHeader(): ReactNode {
const { conversationTitle, groupVersion, onShowConversationDetails, type } =
this.props;
const {
conversationTitle,
id,
groupVersion,
pushPanelForConversation,
type,
} = this.props;
if (conversationTitle !== undefined) {
return (
@ -571,14 +580,16 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
switch (type) {
case 'direct':
onClick = () => {
onShowConversationDetails();
pushPanelForConversation(id, { type: PanelType.ConversationDetails });
};
break;
case 'group': {
const hasGV2AdminEnabled = groupVersion === 2;
onClick = hasGV2AdminEnabled
? () => {
onShowConversationDetails();
pushPanelForConversation(id, {
type: PanelType.ConversationDetails,
});
}
: undefined;
break;

View file

@ -41,8 +41,8 @@ const createProps = (
expireTimer?: DurationInSeconds
): Props => ({
acceptConversation: action('acceptConversation'),
addMembers: async () => {
action('addMembers');
addMembersToGroup: async () => {
action('addMembersToGroup');
},
areWeASubscriber: false,
blockConversation: action('blockConversation'),
@ -57,10 +57,12 @@ const createProps = (
hasActiveCall: false,
hasGroupLink,
getPreferredBadge: () => undefined,
getProfilesForConversation: action('getProfilesForConversation'),
groupsInCommon: [],
i18n,
isAdmin: false,
isGroup: true,
leaveGroup: action('leaveGroup'),
loadRecentMediaItems: action('loadRecentMediaItems'),
memberships: times(32, i => ({
isAdmin: i === 1,
@ -78,7 +80,6 @@ const createProps = (
member: getDefaultConversation(),
})),
setDisappearingMessages: action('setDisappearingMessages'),
showAllMedia: action('showAllMedia'),
showContactModal: action('showContactModal'),
pushPanelForConversation: action('pushPanelForConversation'),
showConversation: action('showConversation'),
@ -86,7 +87,6 @@ const createProps = (
updateGroupAttributes: async () => {
action('updateGroupAttributes')();
},
onLeave: action('onLeave'),
deleteAvatarFromDisk: action('deleteAvatarFromDisk'),
replaceAvatar: action('replaceAvatar'),
saveAvatarToDisk: action('saveAvatarToDisk'),

View file

@ -2,7 +2,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
import type { ReactNode } from 'react';
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { Button, ButtonIconType, ButtonVariant } from '../../Button';
import { Tooltip } from '../../Tooltip';
@ -63,7 +63,6 @@ enum ModalState {
}
export type StateProps = {
addMembers: (conversationIds: ReadonlyArray<string>) => Promise<void>;
areWeASubscriber: boolean;
badges?: ReadonlyArray<BadgeType>;
canEditGroupInfo: boolean;
@ -81,15 +80,6 @@ export type StateProps = {
memberships: Array<GroupV2Membership>;
pendingApprovalMemberships: ReadonlyArray<GroupV2RequestingMembership>;
pendingMemberships: ReadonlyArray<GroupV2PendingMembership>;
showAllMedia: () => void;
updateGroupAttributes: (
_: Readonly<{
avatar?: undefined | Uint8Array;
description?: string;
title?: string;
}>
) => Promise<void>;
onLeave: () => void;
theme: ThemeType;
userAvatarData: Array<AvatarDataType>;
renderChooseGroupMembersModal: (
@ -102,8 +92,18 @@ export type StateProps = {
type ActionProps = {
acceptConversation: (id: string) => void;
addMembersToGroup: (
conversationId: string,
conversationIds: ReadonlyArray<string>,
opts: {
onSuccess?: () => unknown;
onFailure?: () => unknown;
}
) => unknown;
blockConversation: (id: string) => void;
deleteAvatarFromDisk: DeleteAvatarFromDiskActionType;
getProfilesForConversation: (id: string) => unknown;
leaveGroup: (conversationId: string) => void;
loadRecentMediaItems: (id: string, limit: number) => void;
onOutgoingAudioCallInConversation: (conversationId: string) => unknown;
onOutgoingVideoCallInConversation: (conversationId: string) => unknown;
@ -117,13 +117,25 @@ type ActionProps = {
showConversation: ShowConversationType;
toggleAddUserToAnotherGroupModal: (contactId?: string) => void;
toggleSafetyNumberModal: (conversationId: string) => unknown;
updateGroupAttributes: (
conversationId: string,
_: Readonly<{
avatar?: undefined | Uint8Array;
description?: string;
title?: string;
}>,
opts: {
onSuccess?: () => unknown;
onFailure?: () => unknown;
}
) => unknown;
} & Pick<ConversationDetailsMediaListPropsType, 'showLightboxWithMedia'>;
export type Props = StateProps & ActionProps;
export function ConversationDetails({
acceptConversation,
addMembers,
addMembersToGroup,
areWeASubscriber,
badges,
blockConversation,
@ -133,16 +145,17 @@ export function ConversationDetails({
deleteAvatarFromDisk,
hasGroupLink,
getPreferredBadge,
getProfilesForConversation,
groupsInCommon,
hasActiveCall,
i18n,
isAdmin,
isGroup,
leaveGroup,
loadRecentMediaItems,
memberships,
maxGroupSize,
maxRecommendedGroupSize,
onLeave,
onOutgoingAudioCallInConversation,
onOutgoingVideoCallInConversation,
pendingApprovalMemberships,
@ -155,7 +168,6 @@ export function ConversationDetails({
searchInConversation,
setDisappearingMessages,
setMuteExpiration,
showAllMedia,
showContactModal,
showConversation,
showLightboxWithMedia,
@ -177,6 +189,10 @@ export function ConversationDetails({
throw new Error('ConversationDetails rendered without a conversation');
}
useEffect(() => {
getProfilesForConversation(conversation.id);
}, [conversation.id, getProfilesForConversation]);
const invitesCount =
pendingMemberships.length + pendingApprovalMemberships.length;
@ -214,15 +230,17 @@ export function ConversationDetails({
) => {
setEditGroupAttributesRequestState(RequestState.Active);
try {
await updateGroupAttributes(options);
setModalState(ModalState.NothingOpen);
setEditGroupAttributesRequestState(RequestState.Inactive);
} catch (err) {
setEditGroupAttributesRequestState(
RequestState.InactiveWithError
);
}
updateGroupAttributes(conversation.id, options, {
onSuccess: () => {
setModalState(ModalState.NothingOpen);
setEditGroupAttributesRequestState(RequestState.Inactive);
},
onFailure: () => {
setEditGroupAttributesRequestState(
RequestState.InactiveWithError
);
},
});
}}
onClose={() => {
setModalState(ModalState.NothingOpen);
@ -259,13 +277,15 @@ export function ConversationDetails({
makeRequest={async conversationIds => {
setAddGroupMembersRequestState(RequestState.Active);
try {
await addMembers(conversationIds);
setModalState(ModalState.NothingOpen);
setAddGroupMembersRequestState(RequestState.Inactive);
} catch (err) {
setAddGroupMembersRequestState(RequestState.InactiveWithError);
}
addMembersToGroup(conversation.id, conversationIds, {
onSuccess: () => {
setModalState(ModalState.NothingOpen);
setAddGroupMembersRequestState(RequestState.Inactive);
},
onFailure: () => {
setAddGroupMembersRequestState(RequestState.InactiveWithError);
},
});
}}
maxGroupSize={maxGroupSize}
maxRecommendedGroupSize={maxRecommendedGroupSize}
@ -545,7 +565,11 @@ export function ConversationDetails({
conversation={conversation}
i18n={i18n}
loadRecentMediaItems={loadRecentMediaItems}
showAllMedia={showAllMedia}
showAllMedia={() =>
pushPanelForConversation(conversation.id, {
type: PanelType.AllMedia,
})
}
showLightboxWithMedia={showLightboxWithMedia}
/>
@ -570,7 +594,7 @@ export function ConversationDetails({
isBlocked={Boolean(conversation.isBlocked)}
isGroup={isGroup}
left={Boolean(conversation.left)}
onLeave={onLeave}
onLeave={() => leaveGroup(conversation.id)}
/>
)}