Ensure group details screen has the latest data

This commit is contained in:
Evan Hahn
2021-04-29 13:32:38 -05:00
committed by Scott Nonnenberg
parent a5fde38c98
commit 1238cca538
13 changed files with 197 additions and 188 deletions
@@ -24,25 +24,6 @@ const conversation: ConversationType = {
id: '',
lastUpdated: 0,
markedUnread: false,
memberships: Array.from(Array(32)).map((_, i) => ({
isAdmin: i === 1,
member: getDefaultConversation({
isMe: i === 2,
}),
metadata: {
conversationId: '',
joinedAtVersion: 0,
role: 2,
},
})),
pendingMemberships: Array.from(Array(16)).map(() => ({
member: getDefaultConversation({}),
metadata: {
conversationId: '',
role: 2,
timestamp: Date.now(),
},
})),
title: 'Some Conversation',
type: 'group',
};
@@ -58,6 +39,12 @@ const createProps = (hasGroupLink = false): Props => ({
i18n,
isAdmin: false,
loadRecentMediaItems: action('loadRecentMediaItems'),
memberships: times(32, i => ({
isAdmin: i === 1,
member: getDefaultConversation({
isMe: i === 2,
}),
})),
setDisappearingMessages: action('setDisappearingMessages'),
showAllMedia: action('showAllMedia'),
showContactModal: action('showContactModal'),
@@ -91,13 +78,12 @@ story.add('as last admin', () => {
<ConversationDetails
{...props}
isAdmin
conversation={{
...conversation,
memberships: conversation.memberships?.map(membership => ({
...membership,
isAdmin: Boolean(membership.member.isMe),
})),
}}
memberships={times(32, i => ({
isAdmin: i === 2,
member: getDefaultConversation({
isMe: i === 2,
}),
}))}
/>
);
});
@@ -109,15 +95,14 @@ story.add('as only admin', () => {
<ConversationDetails
{...props}
isAdmin
conversation={{
...conversation,
memberships: conversation.memberships
?.filter(membership => membership.member.isMe)
.map(membership => ({
...membership,
isAdmin: true,
})),
}}
memberships={[
{
isAdmin: true,
member: getDefaultConversation({
isMe: true,
}),
},
]}
/>
);
});
@@ -20,7 +20,10 @@ import { ConversationDetailsActions } from './ConversationDetailsActions';
import { ConversationDetailsHeader } from './ConversationDetailsHeader';
import { ConversationDetailsIcon } from './ConversationDetailsIcon';
import { ConversationDetailsMediaList } from './ConversationDetailsMediaList';
import { ConversationDetailsMembershipList } from './ConversationDetailsMembershipList';
import {
ConversationDetailsMembershipList,
GroupV2Membership,
} from './ConversationDetailsMembershipList';
import { EditConversationAttributesModal } from './EditConversationAttributesModal';
import { RequestState } from './util';
@@ -39,6 +42,7 @@ export type StateProps = {
i18n: LocalizerType;
isAdmin: boolean;
loadRecentMediaItems: (limit: number) => void;
memberships: Array<GroupV2Membership>;
setDisappearingMessages: (seconds: number) => void;
showAllMedia: () => void;
showContactModal: (conversationId: string) => void;
@@ -70,6 +74,7 @@ export const ConversationDetails: React.ComponentType<Props> = ({
i18n,
isAdmin,
loadRecentMediaItems,
memberships,
setDisappearingMessages,
showAllMedia,
showContactModal,
@@ -101,7 +106,6 @@ export const ConversationDetails: React.ComponentType<Props> = ({
throw new Error('ConversationDetails rendered without a conversation');
}
const memberships = conversation.memberships || [];
const pendingMemberships = conversation.pendingMemberships || [];
const pendingApprovalMemberships =
conversation.pendingApprovalMemberships || [];
@@ -33,8 +33,6 @@ const createMemberships = (
).map(
(_, i): GroupV2Membership => ({
isAdmin: i % 3 === 0,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
metadata: {} as any,
member: getDefaultConversation({
isMe: i === 2,
}),
@@ -8,13 +8,11 @@ import { Avatar } from '../../Avatar';
import { ConversationDetailsIcon } from './ConversationDetailsIcon';
import { ConversationType } from '../../../state/ducks/conversations';
import { GroupV2MemberType } from '../../../model-types.d';
import { PanelRow } from './PanelRow';
import { PanelSection } from './PanelSection';
export type GroupV2Membership = {
isAdmin: boolean;
metadata: GroupV2MemberType;
member: ConversationType;
};
@@ -1,7 +1,8 @@
// Copyright 2020 Signal Messenger, LLC
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
import { times } from 'lodash';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
@@ -30,43 +31,6 @@ const conversation: ConversationType = {
id: '',
lastUpdated: 0,
markedUnread: false,
memberships: sortedGroupMembers.map(member => ({
isAdmin: false,
member,
metadata: {
conversationId: 'abc123',
joinedAtVersion: 1,
role: 1,
},
})),
pendingMemberships: Array.from(Array(4))
.map(() => ({
member: getDefaultConversation({}),
metadata: {
addedByUserId: 'abc123',
conversationId: 'xyz789',
role: 1,
timestamp: Date.now(),
},
}))
.concat(
Array.from(Array(8)).map(() => ({
member: getDefaultConversation({}),
metadata: {
addedByUserId: 'def456',
conversationId: 'xyz789',
role: 1,
timestamp: Date.now(),
},
}))
),
pendingApprovalMemberships: Array.from(Array(5)).map(() => ({
member: getDefaultConversation({}),
metadata: {
conversationId: 'xyz789',
timestamp: Date.now(),
},
})),
sortedGroupMembers,
title: 'Some Conversation',
type: 'group',
@@ -77,6 +41,23 @@ const createProps = (): PropsType => ({
conversation,
i18n,
ourConversationId: 'abc123',
pendingApprovalMemberships: times(5, () => ({
member: getDefaultConversation(),
})),
pendingMemberships: [
...times(4, () => ({
member: getDefaultConversation(),
metadata: {
addedByUserId: 'abc123',
},
})),
...times(8, () => ({
member: getDefaultConversation(),
metadata: {
addedByUserId: 'def456',
},
})),
],
revokePendingMemberships: action('revokePendingMemberships'),
});
@@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
@@ -12,26 +12,25 @@ import { ConfirmationDialog } from '../../ConfirmationDialog';
import { PanelSection } from './PanelSection';
import { PanelRow } from './PanelRow';
import { ConversationDetailsIcon } from './ConversationDetailsIcon';
import {
GroupV2PendingAdminApprovalType,
GroupV2PendingMemberType,
} from '../../../model-types.d';
export type PropsType = {
conversation?: ConversationType;
readonly conversation?: ConversationType;
readonly i18n: LocalizerType;
ourConversationId?: string;
readonly ourConversationId?: string;
readonly pendingApprovalMemberships: ReadonlyArray<GroupV2RequestingMembership>;
readonly pendingMemberships: ReadonlyArray<GroupV2PendingMembership>;
readonly approvePendingMembership: (conversationId: string) => void;
readonly revokePendingMemberships: (conversationIds: Array<string>) => void;
};
export type GroupV2PendingMembership = {
metadata: GroupV2PendingMemberType;
metadata: {
addedByUserId?: string;
};
member: ConversationType;
};
export type GroupV2RequestingMembership = {
metadata: GroupV2PendingAdminApprovalType;
member: ConversationType;
};
@@ -56,6 +55,8 @@ export const PendingInvites: React.ComponentType<PropsType> = ({
conversation,
i18n,
ourConversationId,
pendingMemberships,
pendingApprovalMemberships,
revokePendingMemberships,
}) => {
if (!conversation || !ourConversationId) {
@@ -70,10 +71,6 @@ export const PendingInvites: React.ComponentType<PropsType> = ({
setStagedMemberships,
] = React.useState<Array<StagedMembershipType> | null>(null);
const allPendingMemberships = conversation.pendingMemberships || [];
const allRequestingMemberships =
conversation.pendingApprovalMemberships || [];
return (
<div className="conversation-details-panel">
<div className="module-conversation-details__tabs">
@@ -95,7 +92,7 @@ export const PendingInvites: React.ComponentType<PropsType> = ({
tabIndex={0}
>
{i18n('PendingInvites--tab-requests', {
count: String(allRequestingMemberships.length),
count: String(pendingApprovalMemberships.length),
})}
</div>
@@ -117,7 +114,7 @@ export const PendingInvites: React.ComponentType<PropsType> = ({
tabIndex={0}
>
{i18n('PendingInvites--tab-invites', {
count: String(allPendingMemberships.length),
count: String(pendingMemberships.length),
})}
</div>
</div>
@@ -126,7 +123,7 @@ export const PendingInvites: React.ComponentType<PropsType> = ({
<MembersPendingAdminApproval
conversation={conversation}
i18n={i18n}
memberships={allRequestingMemberships}
memberships={pendingApprovalMemberships}
setStagedMemberships={setStagedMemberships}
/>
) : null}
@@ -135,7 +132,7 @@ export const PendingInvites: React.ComponentType<PropsType> = ({
conversation={conversation}
i18n={i18n}
members={conversation.sortedGroupMembers || []}
memberships={allPendingMemberships}
memberships={pendingMemberships}
ourConversationId={ourConversationId}
setStagedMemberships={setStagedMemberships}
/>
@@ -233,12 +230,12 @@ function getConfirmationMessage({
members,
ourConversationId,
stagedMemberships,
}: {
}: Readonly<{
i18n: LocalizerType;
members: Array<ConversationType>;
members: ReadonlyArray<ConversationType>;
ourConversationId: string;
stagedMemberships: Array<StagedMembershipType>;
}): string {
stagedMemberships: ReadonlyArray<StagedMembershipType>;
}>): string {
if (!stagedMemberships || !stagedMemberships.length) {
return '';
}
@@ -300,12 +297,12 @@ function MembersPendingAdminApproval({
i18n,
memberships,
setStagedMemberships,
}: {
}: Readonly<{
conversation: ConversationType;
i18n: LocalizerType;
memberships: Array<GroupV2RequestingMembership>;
memberships: ReadonlyArray<GroupV2RequestingMembership>;
setStagedMemberships: (stagedMembership: Array<StagedMembershipType>) => void;
}) {
}>) {
return (
<PanelSection>
{memberships.map(membership => (
@@ -371,14 +368,14 @@ function MembersPendingProfileKey({
memberships,
ourConversationId,
setStagedMemberships,
}: {
}: Readonly<{
conversation: ConversationType;
i18n: LocalizerType;
members: Array<ConversationType>;
memberships: Array<GroupV2PendingMembership>;
memberships: ReadonlyArray<GroupV2PendingMembership>;
ourConversationId: string;
setStagedMemberships: (stagedMembership: Array<StagedMembershipType>) => void;
}) {
}>) {
const groupedPendingMemberships = _.groupBy(
memberships,
membership => membership.metadata.addedByUserId