Support for creating New Groups

This commit is contained in:
Evan Hahn 2021-03-03 14:09:58 -06:00 committed by Josh Perez
parent 1934120e46
commit 5de4babc0d
56 changed files with 6222 additions and 526 deletions

View file

@ -8,6 +8,7 @@ import Fuse, { FuseOptions } from 'fuse.js';
import { StateType } from '../reducer';
import {
ComposerStep,
ConversationLookupType,
ConversationMessageType,
ConversationsStateType,
@ -15,10 +16,12 @@ import {
MessageLookupType,
MessagesByConversationType,
MessageType,
OneTimeModalState,
PreJoinConversationType,
} from '../ducks/conversations';
import { LocalizerType } from '../../types/Util';
import { getOwn } from '../../util/getOwn';
import { deconstructLookup } from '../../util/deconstructLookup';
import type { CallsByConversationType } from '../ducks/calling';
import { getCallsByConversation } from './calling';
import { getBubbleProps } from '../../shims/Whisper';
@ -143,9 +146,26 @@ const getComposerState = createSelector(
(state: ConversationsStateType) => state.composer
);
export const isComposing = createSelector(
export const getComposerStep = createSelector(
getComposerState,
(composerState): boolean => Boolean(composerState)
(composerState): undefined | ComposerStep => composerState?.step
);
export const hasGroupCreationError = createSelector(
getComposerState,
(composerState): boolean => {
if (composerState?.step === ComposerStep.SetGroupMetadata) {
return composerState.hasError;
}
return false;
}
);
export const isCreatingGroup = createSelector(
getComposerState,
(composerState): boolean =>
composerState?.step === ComposerStep.SetGroupMetadata &&
composerState.isCreating
);
export const getMessages = createSelector(
@ -273,6 +293,40 @@ export const getLeftPaneLists = createSelector(
_getLeftPaneLists
);
export const getMaximumGroupSizeModalState = createSelector(
getComposerState,
(composerState): OneTimeModalState => {
switch (composerState?.step) {
case ComposerStep.ChooseGroupMembers:
case ComposerStep.SetGroupMetadata:
return composerState.maximumGroupSizeModalState;
default:
assert(
false,
'Can\'t get the maximum group size modal state in this composer state; returning "never shown"'
);
return OneTimeModalState.NeverShown;
}
}
);
export const getRecommendedGroupSizeModalState = createSelector(
getComposerState,
(composerState): OneTimeModalState => {
switch (composerState?.step) {
case ComposerStep.ChooseGroupMembers:
case ComposerStep.SetGroupMetadata:
return composerState.recommendedGroupSizeModalState;
default:
assert(
false,
'Can\'t get the recommended group size modal state in this composer state; returning "never shown"'
);
return OneTimeModalState.NeverShown;
}
}
);
export const getMe = createSelector(
[getConversationLookup, getUserConversationId],
(
@ -290,6 +344,13 @@ export const getComposerContactSearchTerm = createSelector(
assert(false, 'getComposerContactSearchTerm: composer is not open');
return '';
}
if (composer.step === ComposerStep.SetGroupMetadata) {
assert(
false,
'getComposerContactSearchTerm: composer does not have a search term'
);
return '';
}
return composer.contactSearchTerm;
}
);
@ -363,6 +424,102 @@ export const getComposeContacts = createSelector(
}
);
/*
* This returns contacts for the composer when you're picking new group members. It casts
* a wider net than `getContacts`.
*/
const getGroupContacts = createSelector(
getConversationLookup,
(conversationLookup): Array<ConversationType> =>
Object.values(conversationLookup).filter(
contact =>
contact.type === 'direct' &&
!contact.isMe &&
!contact.isBlocked &&
!isConversationUnregistered(contact)
)
);
export const getCandidateGroupContacts = createSelector(
getNormalizedComposerContactSearchTerm,
getGroupContacts,
(searchTerm, contacts): Array<ConversationType> => {
if (searchTerm.length) {
return new Fuse<ConversationType>(
contacts,
COMPOSE_CONTACTS_FUSE_OPTIONS
).search(searchTerm);
}
return contacts.concat().sort((a, b) => collator.compare(a.title, b.title));
}
);
export const getCantAddContactForModal = createSelector(
getConversationLookup,
getComposerState,
(conversationLookup, composerState): undefined | ConversationType => {
if (composerState?.step !== ComposerStep.ChooseGroupMembers) {
return undefined;
}
const conversationId = composerState.cantAddContactIdForModal;
if (!conversationId) {
return undefined;
}
const result = getOwn(conversationLookup, conversationId);
assert(
result,
'getCantAddContactForModal: failed to look up conversation by ID; returning undefined'
);
return result;
}
);
const getGroupCreationComposerState = createSelector(
getComposerState,
(
composerState
): {
groupName: string;
groupAvatar: undefined | ArrayBuffer;
selectedConversationIds: Array<string>;
} => {
switch (composerState?.step) {
case ComposerStep.ChooseGroupMembers:
case ComposerStep.SetGroupMetadata:
return composerState;
default:
assert(
false,
'getSetGroupMetadataComposerState: expected step to be SetGroupMetadata'
);
return {
groupName: '',
groupAvatar: undefined,
selectedConversationIds: [],
};
}
}
);
export const getComposeGroupAvatar = createSelector(
getGroupCreationComposerState,
(composerState): undefined | ArrayBuffer => composerState.groupAvatar
);
export const getComposeGroupName = createSelector(
getGroupCreationComposerState,
(composerState): string => composerState.groupName
);
export const getComposeSelectedContacts = createSelector(
getConversationLookup,
getGroupCreationComposerState,
(conversationLookup, composerState): Array<ConversationType> =>
deconstructLookup(conversationLookup, composerState.selectedConversationIds)
);
// This is where we will put Conversation selector logic, replicating what
// is currently in models/conversation.getProps()
// What needs to happen to pull that selector logic here?
@ -666,3 +823,16 @@ export const getConversationMessagesSelector = createSelector(
};
}
);
export const getInvitedContactsForNewlyCreatedGroup = createSelector(
getConversationLookup,
getConversations,
(
conversationLookup,
{ invitedConversationIdsForNewlyCreatedGroup = [] }
): Array<ConversationType> =>
deconstructLookup(
conversationLookup,
invitedConversationIdsForNewlyCreatedGroup
)
);