From dec23725e5b362115d5f7d347bf73c00e3c9fd2e Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Wed, 21 Dec 2022 16:07:02 -0800 Subject: [PATCH] Use ReadonlyArrays in conversation model and redux --- ts/SignalProtocolStore.ts | 2 +- ts/components/Avatar.tsx | 2 +- ts/components/CompositionInput.tsx | 6 +- .../CustomizingPreferredReactionsModal.tsx | 6 +- ts/components/ForwardMessageModal.tsx | 6 +- ts/components/Lightbox.tsx | 2 +- ts/components/ProfileEditor.tsx | 2 +- ts/components/SharedGroupNames.tsx | 2 +- ts/components/StoryViewer.tsx | 4 +- ts/components/StoryViewsNRepliesModal.tsx | 8 +-- .../conversation/ConversationHero.tsx | 2 +- .../conversation/GroupV2Change.stories.tsx | 4 +- ts/components/conversation/GroupV2Change.tsx | 8 +-- ts/components/conversation/ImageGrid.tsx | 2 +- ts/components/conversation/Message.tsx | 4 +- ts/components/conversation/ReactionPicker.tsx | 2 +- .../AddGroupMembersModal.tsx | 2 +- .../ConversationDetails.tsx | 6 +- .../ConversationDetailsGroups.tsx | 2 +- .../ConversationDetailsHeader.tsx | 2 +- .../ConversationDetailsMediaList.tsx | 2 +- .../ConversationDetailsMembershipList.tsx | 2 +- .../EditConversationAttributesModal.tsx | 2 +- .../conversation-details/PendingInvites.tsx | 10 ++-- .../media-gallery/AttachmentSection.tsx | 2 +- .../media-gallery/groupMediaItemsByDate.ts | 4 +- .../conversationList/GroupListItem.tsx | 2 +- ts/components/emoji/EmojiPicker.tsx | 2 +- ts/groups.ts | 20 +++---- .../toggleSelectedContactForGroupAddition.ts | 4 +- ts/models/conversations.ts | 8 +-- ts/quill/memberRepository.ts | 11 ++-- ts/quill/mentions/completion.tsx | 6 +- ts/sql/Interface.ts | 2 +- ts/sql/Server.ts | 16 ++--- ts/sql/migrations/42-stale-reactions.ts | 2 +- ts/sql/util.ts | 18 +++--- ts/state/ducks/conversations.ts | 59 ++++++++++--------- ts/state/ducks/items.ts | 2 +- ts/state/ducks/lightbox.ts | 6 +- ts/state/selectors/conversations.ts | 8 +-- ts/state/selectors/lightbox.ts | 3 +- ts/state/smart/Lightbox.tsx | 2 +- ts/state/smart/ReactionPicker.tsx | 2 +- ts/state/smart/StoryViewer.tsx | 2 +- .../quill/mentions/completion_test.tsx | 2 +- ts/textsecure/SendMessage.ts | 4 +- ts/types/Attachment.ts | 6 +- ts/types/Avatar.ts | 4 +- ts/types/Storage.d.ts | 22 +++---- ts/util/getAvatarData.ts | 2 +- ts/util/getGroupMemberships.ts | 12 ++-- ts/util/getRecipients.ts | 2 +- ts/util/maybeForwardMessage.ts | 4 +- ts/util/sendToGroup.ts | 6 +- 55 files changed, 173 insertions(+), 162 deletions(-) diff --git a/ts/SignalProtocolStore.ts b/ts/SignalProtocolStore.ts index eab446b13d60..3f9f0bcc81b4 100644 --- a/ts/SignalProtocolStore.ts +++ b/ts/SignalProtocolStore.ts @@ -1105,7 +1105,7 @@ export class SignalProtocolStore extends EventEmitter { async getOpenDevices( ourUuid: UUID, - identifiers: Array, + identifiers: ReadonlyArray, { zone = GLOBAL_ZONE }: SessionTransactionOptions = {} ): Promise<{ devices: Array; diff --git a/ts/components/Avatar.tsx b/ts/components/Avatar.tsx index e8cae179e64f..0c305629574b 100644 --- a/ts/components/Avatar.tsx +++ b/ts/components/Avatar.tsx @@ -49,7 +49,7 @@ export type Props = { noteToSelf?: boolean; phoneNumber?: string; profileName?: string; - sharedGroupNames: Array; + sharedGroupNames: ReadonlyArray; size: AvatarSize; title: string; unblurredAvatarPath?: string; diff --git a/ts/components/CompositionInput.tsx b/ts/components/CompositionInput.tsx index 06252d0e577e..244f02d4da09 100644 --- a/ts/components/CompositionInput.tsx +++ b/ts/components/CompositionInput.tsx @@ -79,7 +79,7 @@ export type Props = Readonly<{ moduleClassName?: string; theme: ThemeType; placeholder?: string; - sortedGroupMembers?: Array; + sortedGroupMembers?: ReadonlyArray; scrollerRef?: React.RefObject; onDirtyChange?(dirty: boolean): unknown; onEditorStateChange?( @@ -488,7 +488,9 @@ export function CompositionInput(props: Props): React.ReactElement { [] ); - const removeStaleMentions = (currentMembers: Array) => { + const removeStaleMentions = ( + currentMembers: ReadonlyArray + ) => { const quill = quillRef.current; if (quill === undefined) { diff --git a/ts/components/CustomizingPreferredReactionsModal.tsx b/ts/components/CustomizingPreferredReactionsModal.tsx index 562307c98c0e..3409052f9eea 100644 --- a/ts/components/CustomizingPreferredReactionsModal.tsx +++ b/ts/components/CustomizingPreferredReactionsModal.tsx @@ -20,12 +20,12 @@ import { offsetDistanceModifier } from '../util/popperUtil'; import { handleOutsideClick } from '../util/handleOutsideClick'; type PropsType = { - draftPreferredReactions: Array; + draftPreferredReactions: ReadonlyArray; hadSaveError: boolean; i18n: LocalizerType; isSaving: boolean; - originalPreferredReactions: Array; - recentEmojis: Array; + originalPreferredReactions: ReadonlyArray; + recentEmojis: ReadonlyArray; selectedDraftEmojiIndex: undefined | number; skinTone: number; diff --git a/ts/components/ForwardMessageModal.tsx b/ts/components/ForwardMessageModal.tsx index 0cddf991938f..0c8122687f53 100644 --- a/ts/components/ForwardMessageModal.tsx +++ b/ts/components/ForwardMessageModal.tsx @@ -40,12 +40,12 @@ import { } from '../util/shouldNeverBeCalled'; export type DataPropsType = { - attachments?: Array; + attachments?: ReadonlyArray; candidateConversations: ReadonlyArray; doForwardMessage: ( selectedContacts: Array, messageBody?: string, - attachments?: Array, + attachments?: ReadonlyArray, linkPreview?: LinkPreviewType ) => void; getPreferredBadge: PreferredBadgeSelectorType; @@ -102,7 +102,7 @@ export function ForwardMessageModal({ filterAndSortConversationsByRecent(candidateConversations, '', regionCode) ); const [attachmentsToForward, setAttachmentsToForward] = useState< - Array + ReadonlyArray >(attachments || []); const [isEditingMessage, setIsEditingMessage] = useState(false); const [messageBodyText, setMessageBodyText] = useState(messageBody || ''); diff --git a/ts/components/Lightbox.tsx b/ts/components/Lightbox.tsx index 929e8f845110..fc4454e6aaac 100644 --- a/ts/components/Lightbox.tsx +++ b/ts/components/Lightbox.tsx @@ -29,7 +29,7 @@ export type PropsType = { getConversation?: (id: string) => ConversationType; i18n: LocalizerType; isViewOnce?: boolean; - media: Array; + media: ReadonlyArray; saveAttachment: SaveAttachmentActionCreatorType; selectedIndex?: number; toggleForwardMessageModal: (messageId: string) => unknown; diff --git a/ts/components/ProfileEditor.tsx b/ts/components/ProfileEditor.tsx index b783444c48ed..78e63c1aaa37 100644 --- a/ts/components/ProfileEditor.tsx +++ b/ts/components/ProfileEditor.tsx @@ -69,7 +69,7 @@ export type PropsDataType = { firstName: string; i18n: LocalizerType; isUsernameFlagEnabled: boolean; - userAvatarData: Array; + userAvatarData: ReadonlyArray; username?: string; usernameEditState: UsernameEditState; } & Pick; diff --git a/ts/components/SharedGroupNames.tsx b/ts/components/SharedGroupNames.tsx index 1474506601b2..4cef3169d8ca 100644 --- a/ts/components/SharedGroupNames.tsx +++ b/ts/components/SharedGroupNames.tsx @@ -11,7 +11,7 @@ import type { LocalizerType } from '../types/Util'; type PropsType = { i18n: LocalizerType; nameClassName?: string; - sharedGroupNames: Array; + sharedGroupNames: ReadonlyArray; }; export function SharedGroupNames({ diff --git a/ts/components/StoryViewer.tsx b/ts/components/StoryViewer.tsx index 1a8cfd254acb..ff5f64de727c 100644 --- a/ts/components/StoryViewer.tsx +++ b/ts/components/StoryViewer.tsx @@ -96,9 +96,9 @@ export type PropsType = { story: StoryViewType ) => unknown; onUseEmoji: (_: EmojiPickDataType) => unknown; - preferredReactionEmoji: Array; + preferredReactionEmoji: ReadonlyArray; queueStoryDownload: (storyId: string) => unknown; - recentEmojis?: Array; + recentEmojis?: ReadonlyArray; renderEmojiPicker: (props: RenderEmojiPickerProps) => JSX.Element; replyState?: ReplyStateType; retryMessageSend: (messageId: string) => unknown; diff --git a/ts/components/StoryViewsNRepliesModal.tsx b/ts/components/StoryViewsNRepliesModal.tsx index e6150ad5af73..6e10c175131a 100644 --- a/ts/components/StoryViewsNRepliesModal.tsx +++ b/ts/components/StoryViewsNRepliesModal.tsx @@ -98,14 +98,14 @@ export type PropsType = { onSetSkinTone: (tone: number) => unknown; onTextTooLong: () => unknown; onUseEmoji: (_: EmojiPickDataType) => unknown; - preferredReactionEmoji: Array; - recentEmojis?: Array; + preferredReactionEmoji: ReadonlyArray; + recentEmojis?: ReadonlyArray; renderEmojiPicker: (props: RenderEmojiPickerProps) => JSX.Element; replies: ReadonlyArray; skinTone?: number; - sortedGroupMembers?: Array; + sortedGroupMembers?: ReadonlyArray; storyPreviewAttachment?: AttachmentType; - views: Array; + views: ReadonlyArray; viewTarget: StoryViewTargetType; onChangeViewTarget: (target: StoryViewTargetType) => unknown; deleteGroupStoryReply: (id: string) => void; diff --git a/ts/components/conversation/ConversationHero.tsx b/ts/components/conversation/ConversationHero.tsx index 46ed8d523737..0b3f9abfce7e 100644 --- a/ts/components/conversation/ConversationHero.tsx +++ b/ts/components/conversation/ConversationHero.tsx @@ -29,7 +29,7 @@ export type Props = { membersCount?: number; name?: string; phoneNumber?: string; - sharedGroupNames?: Array; + sharedGroupNames?: ReadonlyArray; unblurAvatar: (conversationId: string) => void; unblurredAvatarPath?: string; updateSharedGroups: (conversationId: string) => unknown; diff --git a/ts/components/conversation/GroupV2Change.stories.tsx b/ts/components/conversation/GroupV2Change.stories.tsx index 3803cb9656dd..605f438aa520 100644 --- a/ts/components/conversation/GroupV2Change.stories.tsx +++ b/ts/components/conversation/GroupV2Change.stories.tsx @@ -43,11 +43,11 @@ const renderChange = ( groupName, areWeAdmin = true, }: { - groupMemberships?: Array<{ + groupMemberships?: ReadonlyArray<{ uuid: UUIDStringType; isAdmin: boolean; }>; - groupBannedMemberships?: Array; + groupBannedMemberships?: ReadonlyArray; groupName?: string; areWeAdmin?: boolean; } = {} diff --git a/ts/components/conversation/GroupV2Change.tsx b/ts/components/conversation/GroupV2Change.tsx index 670ec4eb42f7..beb9b2f38234 100644 --- a/ts/components/conversation/GroupV2Change.tsx +++ b/ts/components/conversation/GroupV2Change.tsx @@ -25,11 +25,11 @@ import { ConfirmationDialog } from '../ConfirmationDialog'; export type PropsDataType = { areWeAdmin: boolean; conversationId: string; - groupMemberships?: Array<{ + groupMemberships?: ReadonlyArray<{ uuid: UUIDStringType; isAdmin: boolean; }>; - groupBannedMemberships?: Array; + groupBannedMemberships?: ReadonlyArray; groupName?: string; ourACI?: UUIDStringType; ourPNI?: UUIDStringType; @@ -155,11 +155,11 @@ function GroupV2Detail({ conversationId: string; detail: GroupV2ChangeDetailType; isLastText: boolean; - groupMemberships?: Array<{ + groupMemberships?: ReadonlyArray<{ uuid: UUIDStringType; isAdmin: boolean; }>; - groupBannedMemberships?: Array; + groupBannedMemberships?: ReadonlyArray; groupName?: string; i18n: LocalizerType; fromId?: UUIDStringType; diff --git a/ts/components/conversation/ImageGrid.tsx b/ts/components/conversation/ImageGrid.tsx index f80f5a25abdf..538b0029febc 100644 --- a/ts/components/conversation/ImageGrid.tsx +++ b/ts/components/conversation/ImageGrid.tsx @@ -21,7 +21,7 @@ import type { LocalizerType, ThemeType } from '../../types/Util'; export type DirectionType = 'incoming' | 'outgoing'; export type Props = { - attachments: Array; + attachments: ReadonlyArray; bottomOverlay?: boolean; direction: DirectionType; isSticker?: boolean; diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index 1f10f852afb4..d99401631a5d 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -223,7 +223,7 @@ export type PropsData = { >; reducedMotion?: boolean; conversationType: ConversationTypeType; - attachments?: Array; + attachments?: ReadonlyArray; giftBadge?: GiftBadgeType; payment?: AnyPaymentEvent; quote?: { @@ -255,7 +255,7 @@ export type PropsData = { storyId?: string; text: string; }; - previews: Array; + previews: ReadonlyArray; isTapToView?: boolean; isTapToViewExpired?: boolean; diff --git a/ts/components/conversation/ReactionPicker.tsx b/ts/components/conversation/ReactionPicker.tsx index bdd613ca71a4..cdd6457bc70a 100644 --- a/ts/components/conversation/ReactionPicker.tsx +++ b/ts/components/conversation/ReactionPicker.tsx @@ -28,7 +28,7 @@ export type OwnProps = { onPick: (emoji: string) => unknown; onSetSkinTone: (tone: number) => unknown; openCustomizePreferredReactionsModal?: () => unknown; - preferredReactionEmoji: Array; + preferredReactionEmoji: ReadonlyArray; renderEmojiPicker: (props: RenderEmojiPickerProps) => React.ReactElement; }; diff --git a/ts/components/conversation/conversation-details/AddGroupMembersModal.tsx b/ts/components/conversation/conversation-details/AddGroupMembersModal.tsx index 87048c7c6b66..6fffa94d9ff7 100644 --- a/ts/components/conversation/conversation-details/AddGroupMembersModal.tsx +++ b/ts/components/conversation/conversation-details/AddGroupMembersModal.tsx @@ -48,7 +48,7 @@ type StateType = { maximumGroupSizeModalState: OneTimeModalState; recommendedGroupSizeModalState: OneTimeModalState; searchTerm: string; - selectedConversationIds: Array; + selectedConversationIds: ReadonlyArray; stage: Stage; }; diff --git a/ts/components/conversation/conversation-details/ConversationDetails.tsx b/ts/components/conversation/conversation-details/ConversationDetails.tsx index 6a02b188276e..350159340c5a 100644 --- a/ts/components/conversation/conversation-details/ConversationDetails.tsx +++ b/ts/components/conversation/conversation-details/ConversationDetails.tsx @@ -74,14 +74,14 @@ export type StateProps = { i18n: LocalizerType; isAdmin: boolean; isGroup: boolean; - groupsInCommon: Array; + groupsInCommon: ReadonlyArray; maxGroupSize: number; maxRecommendedGroupSize: number; - memberships: Array; + memberships: ReadonlyArray; pendingApprovalMemberships: ReadonlyArray; pendingMemberships: ReadonlyArray; theme: ThemeType; - userAvatarData: Array; + userAvatarData: ReadonlyArray; renderChooseGroupMembersModal: ( props: SmartChooseGroupMembersModalPropsType ) => JSX.Element; diff --git a/ts/components/conversation/conversation-details/ConversationDetailsGroups.tsx b/ts/components/conversation/conversation-details/ConversationDetailsGroups.tsx index 57818f5cd440..8a9ea7894551 100644 --- a/ts/components/conversation/conversation-details/ConversationDetailsGroups.tsx +++ b/ts/components/conversation/conversation-details/ConversationDetailsGroups.tsx @@ -15,7 +15,7 @@ import { PanelSection } from './PanelSection'; type Props = { contactId: string; i18n: LocalizerType; - groupsInCommon: Array; + groupsInCommon: ReadonlyArray; toggleAddUserToAnotherGroupModal: (contactId?: string) => void; showConversation: ShowConversationType; }; diff --git a/ts/components/conversation/conversation-details/ConversationDetailsHeader.tsx b/ts/components/conversation/conversation-details/ConversationDetailsHeader.tsx index 78d0cac5ada4..e224e94a11c8 100644 --- a/ts/components/conversation/conversation-details/ConversationDetailsHeader.tsx +++ b/ts/components/conversation/conversation-details/ConversationDetailsHeader.tsx @@ -24,7 +24,7 @@ export type Props = { i18n: LocalizerType; isGroup: boolean; isMe: boolean; - memberships: Array; + memberships: ReadonlyArray; startEditing: (isGroupTitle: boolean) => void; theme: ThemeType; }; diff --git a/ts/components/conversation/conversation-details/ConversationDetailsMediaList.tsx b/ts/components/conversation/conversation-details/ConversationDetailsMediaList.tsx index 6ac35d81d787..fd3ba6e2b1b2 100644 --- a/ts/components/conversation/conversation-details/ConversationDetailsMediaList.tsx +++ b/ts/components/conversation/conversation-details/ConversationDetailsMediaList.tsx @@ -19,7 +19,7 @@ export type Props = { showAllMedia: () => void; showLightboxWithMedia: ( selectedAttachmentPath: string | undefined, - media: Array + media: ReadonlyArray ) => void; }; diff --git a/ts/components/conversation/conversation-details/ConversationDetailsMembershipList.tsx b/ts/components/conversation/conversation-details/ConversationDetailsMembershipList.tsx index 068616a01c67..55f022e92d03 100644 --- a/ts/components/conversation/conversation-details/ConversationDetailsMembershipList.tsx +++ b/ts/components/conversation/conversation-details/ConversationDetailsMembershipList.tsx @@ -25,7 +25,7 @@ export type Props = { getPreferredBadge: PreferredBadgeSelectorType; i18n: LocalizerType; maxShownMemberCount?: number; - memberships: Array; + memberships: ReadonlyArray; showContactModal: (contactId: string, conversationId?: string) => void; startAddingNewMembers?: () => void; theme: ThemeType; diff --git a/ts/components/conversation/conversation-details/EditConversationAttributesModal.tsx b/ts/components/conversation/conversation-details/EditConversationAttributesModal.tsx index b2bb8a53b9d0..f5b8d0e5943b 100644 --- a/ts/components/conversation/conversation-details/EditConversationAttributesModal.tsx +++ b/ts/components/conversation/conversation-details/EditConversationAttributesModal.tsx @@ -41,7 +41,7 @@ type PropsType = { deleteAvatarFromDisk: DeleteAvatarFromDiskActionType; replaceAvatar: ReplaceAvatarActionType; saveAvatarToDisk: SaveAvatarToDiskActionType; - userAvatarData: Array; + userAvatarData: ReadonlyArray; }; export function EditConversationAttributesModal({ diff --git a/ts/components/conversation/conversation-details/PendingInvites.tsx b/ts/components/conversation/conversation-details/PendingInvites.tsx index 26526d7f504f..2e5b07fe4687 100644 --- a/ts/components/conversation/conversation-details/PendingInvites.tsx +++ b/ts/components/conversation/conversation-details/PendingInvites.tsx @@ -34,7 +34,7 @@ type PropsActionType = { ) => void; readonly revokePendingMembershipsFromGroupV2: ( conversationId: string, - memberIds: Array + memberIds: ReadonlyArray ) => void; }; @@ -193,14 +193,14 @@ function MembershipActionConfirmation({ ) => void; conversation: ConversationType; i18n: LocalizerType; - members: Array; + members: ReadonlyArray; onClose: () => void; ourUuid: string; revokePendingMembershipsFromGroupV2: ( conversationId: string, - memberIds: Array + memberIds: ReadonlyArray ) => void; - stagedMemberships: Array; + stagedMemberships: ReadonlyArray; }) { const revokeStagedMemberships = () => { if (!stagedMemberships) { @@ -424,7 +424,7 @@ function MembersPendingProfileKey({ conversation: ConversationType; getPreferredBadge: PreferredBadgeSelectorType; i18n: LocalizerType; - members: Array; + members: ReadonlyArray; memberships: ReadonlyArray; ourUuid: string; setStagedMemberships: (stagedMembership: Array) => void; diff --git a/ts/components/conversation/media-gallery/AttachmentSection.tsx b/ts/components/conversation/media-gallery/AttachmentSection.tsx index 3a13a59d4a9f..643d5537a6da 100644 --- a/ts/components/conversation/media-gallery/AttachmentSection.tsx +++ b/ts/components/conversation/media-gallery/AttachmentSection.tsx @@ -14,7 +14,7 @@ import { missingCaseError } from '../../../util/missingCaseError'; export type Props = { header?: string; i18n: LocalizerType; - mediaItems: Array; + mediaItems: ReadonlyArray; onItemClick: (event: ItemClickEvent) => unknown; type: 'media' | 'documents'; }; diff --git a/ts/components/conversation/media-gallery/groupMediaItemsByDate.ts b/ts/components/conversation/media-gallery/groupMediaItemsByDate.ts index 523c349dceef..ec56d02e5bed 100644 --- a/ts/components/conversation/media-gallery/groupMediaItemsByDate.ts +++ b/ts/components/conversation/media-gallery/groupMediaItemsByDate.ts @@ -15,7 +15,7 @@ type YearMonthSectionType = 'yearMonth'; type GenericSection = { type: T; - mediaItems: Array; + mediaItems: ReadonlyArray; }; type StaticSection = GenericSection; type YearMonthSection = GenericSection & { @@ -25,7 +25,7 @@ type YearMonthSection = GenericSection & { export type Section = StaticSection | YearMonthSection; export const groupMediaItemsByDate = ( timestamp: number, - mediaItems: Array + mediaItems: ReadonlyArray ): Array
=> { const referenceDateTime = moment.utc(timestamp); diff --git a/ts/components/conversationList/GroupListItem.tsx b/ts/components/conversationList/GroupListItem.tsx index ab521e079f5b..260c3048155b 100644 --- a/ts/components/conversationList/GroupListItem.tsx +++ b/ts/components/conversationList/GroupListItem.tsx @@ -19,7 +19,7 @@ export type GroupListItemConversationType = Pick< > & { disabledReason: DisabledReason | undefined; membersCount: number; - memberships: Array<{ + memberships: ReadonlyArray<{ uuid: UUIDStringType; isAdmin: boolean; }>; diff --git a/ts/components/emoji/EmojiPicker.tsx b/ts/components/emoji/EmojiPicker.tsx index fb1529c51fcf..cd9d6d252cd0 100644 --- a/ts/components/emoji/EmojiPicker.tsx +++ b/ts/components/emoji/EmojiPicker.tsx @@ -36,7 +36,7 @@ export type OwnProps = { readonly doSend?: () => unknown; readonly skinTone?: number; readonly onSetSkinTone?: (tone: number) => unknown; - readonly recentEmojis?: Array; + readonly recentEmojis?: ReadonlyArray; readonly onClickSettings?: () => unknown; readonly onClose?: () => unknown; }; diff --git a/ts/groups.ts b/ts/groups.ts index d7cab332a439..3c8dd1963b9b 100644 --- a/ts/groups.ts +++ b/ts/groups.ts @@ -1193,7 +1193,7 @@ export function buildDeletePendingMemberChange({ uuids, group, }: { - uuids: Array; + uuids: ReadonlyArray; group: ConversationAttributesType; }): Proto.GroupChange.Actions { const actions = new Proto.GroupChange.Actions(); @@ -1452,7 +1452,7 @@ export async function modifyGroupV2({ conversation: ConversationModel; usingCredentialsFrom: ReadonlyArray; createGroupChange: () => Promise; - extraConversationsForSend?: Array; + extraConversationsForSend?: ReadonlyArray; inviteLinkPassword?: string; name: string; }): Promise { @@ -1554,7 +1554,7 @@ export async function modifyGroupV2({ type: conversationQueueJobEnum.enum.GroupUpdate, conversationId: conversation.id, groupChangeBase64, - recipients: groupV2Info.members, + recipients: groupV2Info.members.slice(), revision: groupV2Info.revision, }); }); @@ -1733,8 +1733,8 @@ export async function createGroupV2( name: string; avatar: undefined | Uint8Array; expireTimer: undefined | DurationInSeconds; - conversationIds: Array; - avatars?: Array; + conversationIds: ReadonlyArray; + avatars?: ReadonlyArray; refreshedCredentials?: boolean; }> ): Promise { @@ -1953,7 +1953,7 @@ export async function createGroupV2( await conversationJobQueue.add({ type: conversationQueueJobEnum.enum.GroupUpdate, conversationId: conversation.id, - recipients: groupV2Info.members, + recipients: groupV2Info.members.slice(), revision: groupV2Info.revision, }); @@ -2438,7 +2438,7 @@ export async function initiateMigrationToGroupV2( await conversationJobQueue.add({ type: conversationQueueJobEnum.enum.GroupUpdate, conversationId: conversation.id, - recipients: groupV2Info.members, + recipients: groupV2Info.members.slice(), revision: groupV2Info.revision, }); } @@ -2466,7 +2466,7 @@ export async function waitThenRespondToGroupV2Migration( } export function buildMigrationBubble( - previousGroupV1MembersIds: Array, + previousGroupV1MembersIds: ReadonlyArray, newAttributes: ConversationAttributesType ): GroupChangeMessageType { const ourACI = window.storage.user.getCheckedUuid(UUIDKind.ACI); @@ -3880,7 +3880,7 @@ async function integrateGroupChanges({ }: { group: ConversationAttributesType; newRevision: number | undefined; - changes: Array; + changes: ReadonlyArray; }): Promise { const logId = idForLogging(group.groupId); let attributes = group; @@ -4715,7 +4715,7 @@ function extractDiffs({ return result; } -function profileKeysToMembers(items: Array) { +function profileKeysToMembers(items: ReadonlyArray) { return items.map(item => ({ profileKey: Bytes.toBase64(item.profileKey), uuid: item.uuid, diff --git a/ts/groups/toggleSelectedContactForGroupAddition.ts b/ts/groups/toggleSelectedContactForGroupAddition.ts index 4c9e497e7707..d338e8176372 100644 --- a/ts/groups/toggleSelectedContactForGroupAddition.ts +++ b/ts/groups/toggleSelectedContactForGroupAddition.ts @@ -17,12 +17,12 @@ export function toggleSelectedContactForGroupAddition( maximumGroupSizeModalState: OneTimeModalState; numberOfContactsAlreadyInGroup: number; recommendedGroupSizeModalState: OneTimeModalState; - selectedConversationIds: Array; + selectedConversationIds: ReadonlyArray; }> ): { maximumGroupSizeModalState: OneTimeModalState; recommendedGroupSizeModalState: OneTimeModalState; - selectedConversationIds: Array; + selectedConversationIds: ReadonlyArray; } { const { maxGroupSize, diff --git a/ts/models/conversations.ts b/ts/models/conversations.ts index 63124c46e060..9de2fd7f1d0f 100644 --- a/ts/models/conversations.ts +++ b/ts/models/conversations.ts @@ -741,7 +741,7 @@ export class ConversationModel extends window.Backbone }: { usingCredentialsFrom: ReadonlyArray; createGroupChange: () => Promise; - extraConversationsForSend?: Array; + extraConversationsForSend?: ReadonlyArray; inviteLinkPassword?: string; name: string; }): Promise { @@ -1159,9 +1159,9 @@ export class ConversationModel extends window.Backbone { groupChange?: Uint8Array } & ( | { includePendingMembers?: boolean; - extraConversationsForSend?: Array; + extraConversationsForSend?: ReadonlyArray; } - | { members: Array } + | { members: ReadonlyArray } ) > = {} ): GroupV2InfoType | undefined { @@ -3712,7 +3712,7 @@ export class ConversationModel extends window.Backbone isStoryReply = false, }: { includePendingMembers?: boolean; - extraConversationsForSend?: Array; + extraConversationsForSend?: ReadonlyArray; isStoryReply?: boolean; } = {}): Array { return getRecipients(this.attributes, { diff --git a/ts/quill/memberRepository.ts b/ts/quill/memberRepository.ts index ee2b586740b7..3e91a4f7c343 100644 --- a/ts/quill/memberRepository.ts +++ b/ts/quill/memberRepository.ts @@ -45,14 +45,14 @@ export class MemberRepository { FUSE_OPTIONS ); - constructor(private members: Array = []) {} + constructor(private members: ReadonlyArray = []) {} - updateMembers(members: Array): void { + updateMembers(members: ReadonlyArray): void { this.members = members; this.isFuseReady = false; } - getMembers(omit?: ConversationType): Array { + getMembers(omit?: ConversationType): ReadonlyArray { if (omit) { return this.members.filter(({ id }) => id !== omit.id); } @@ -72,7 +72,10 @@ export class MemberRepository { : undefined; } - search(pattern: string, omit?: ConversationType): Array { + search( + pattern: string, + omit?: ConversationType + ): ReadonlyArray { if (!this.isFuseReady) { this.fuse.setCollection(this.members); this.isFuseReady = true; diff --git a/ts/quill/mentions/completion.tsx b/ts/quill/mentions/completion.tsx index 61e3a65e3be6..8e8666d70d1e 100644 --- a/ts/quill/mentions/completion.tsx +++ b/ts/quill/mentions/completion.tsx @@ -31,7 +31,7 @@ export type MentionCompletionOptions = { const MENTION_REGEX = /(?:^|\W)@([-+\w]*)$/; export class MentionCompletion { - results: Array; + results: ReadonlyArray; index: number; @@ -105,7 +105,7 @@ export class MentionCompletion { this.clearResults(); } - possiblyShowMemberResults(): Array { + possiblyShowMemberResults(): ReadonlyArray { const range = this.quill.getSelection(); if (range) { @@ -120,7 +120,7 @@ export class MentionCompletion { if (leftTokenTextMatch) { const [, leftTokenText] = leftTokenTextMatch; - let results: Array = []; + let results: ReadonlyArray = []; const memberRepository = this.options.memberRepositoryRef.current; diff --git a/ts/sql/Interface.ts b/ts/sql/Interface.ts index 1e99a29f04fe..a798c3fa11f5 100644 --- a/ts/sql/Interface.ts +++ b/ts/sql/Interface.ts @@ -471,7 +471,7 @@ export type DataInterface = { options: { forceSave?: boolean; ourUuid: UUIDStringType } ) => Promise; removeMessage: (id: string) => Promise; - removeMessages: (ids: Array) => Promise; + removeMessages: (ids: ReadonlyArray) => Promise; getTotalUnreadForConversation: ( conversationId: string, options: { diff --git a/ts/sql/Server.ts b/ts/sql/Server.ts index 5e6ec57733f6..7ec457b196ce 100644 --- a/ts/sql/Server.ts +++ b/ts/sql/Server.ts @@ -1509,7 +1509,7 @@ async function updateConversations( })(); } -function removeConversationsSync(ids: Array): void { +function removeConversationsSync(ids: ReadonlyArray): void { const db = getInstance(); // Our node interface doesn't seem to allow you to replace one single ? with an array @@ -2046,7 +2046,7 @@ async function removeMessage(id: string): Promise { db.prepare('DELETE FROM messages WHERE id = $id;').run({ id }); } -function removeMessagesSync(ids: Array): void { +function removeMessagesSync(ids: ReadonlyArray): void { const db = getInstance(); db.prepare( @@ -2057,7 +2057,7 @@ function removeMessagesSync(ids: Array): void { ).run(ids); } -async function removeMessages(ids: Array): Promise { +async function removeMessages(ids: ReadonlyArray): Promise { batchMultiVarQuery(getInstance(), ids, removeMessagesSync); } @@ -2091,7 +2091,7 @@ async function getMessagesById( return batchMultiVarQuery( db, messageIds, - (batch: Array): Array => { + (batch: ReadonlyArray): Array => { const query = db.prepare( `SELECT json FROM messages WHERE id IN (${Array(batch.length) .fill('?') @@ -2325,7 +2325,7 @@ async function getUnreadReactionsAndMarkRead({ }); const idsToUpdate = unreadMessages.map(item => item.rowid); - batchMultiVarQuery(db, idsToUpdate, (ids: Array): void => { + batchMultiVarQuery(db, idsToUpdate, (ids: ReadonlyArray): void => { db.prepare( ` UPDATE reactions SET @@ -3408,7 +3408,7 @@ async function getAllUnprocessedAndIncrementAttempts(): Promise< })(); } -function removeUnprocessedsSync(ids: Array): void { +function removeUnprocessedsSync(ids: ReadonlyArray): void { const db = getInstance(); db.prepare( @@ -4680,7 +4680,7 @@ function modifyStoryDistributionMembersSync( }); } - batchMultiVarQuery(db, toRemove, (uuids: Array) => { + batchMultiVarQuery(db, toRemove, (uuids: ReadonlyArray) => { db.prepare( ` DELETE FROM storyDistributionMembers @@ -5166,7 +5166,7 @@ async function getKnownMessageAttachments( const messages = batchMultiVarQuery( db, rowids, - (batch: Array): Array => { + (batch: ReadonlyArray): Array => { const query = db.prepare( `SELECT json FROM messages WHERE rowid IN (${Array(batch.length) .fill('?') diff --git a/ts/sql/migrations/42-stale-reactions.ts b/ts/sql/migrations/42-stale-reactions.ts index ca9818377bc4..f8c7cc38a77d 100644 --- a/ts/sql/migrations/42-stale-reactions.ts +++ b/ts/sql/migrations/42-stale-reactions.ts @@ -57,7 +57,7 @@ export default function updateToSchemaVersion42( } }); - function deleteReactions(rowids: Array) { + function deleteReactions(rowids: ReadonlyArray) { db.prepare( ` DELETE FROM reactions diff --git a/ts/sql/util.ts b/ts/sql/util.ts index 6b443a7d6106..8b905e7aefc2 100644 --- a/ts/sql/util.ts +++ b/ts/sql/util.ts @@ -5,7 +5,7 @@ import type { Database } from '@signalapp/better-sqlite3'; import { isNumber, last } from 'lodash'; export type EmptyQuery = []; -export type ArrayQuery = Array>; +export type ArrayQuery = Array>; export type Query = { [key: string]: null | number | bigint | string | Uint8Array; }; @@ -72,21 +72,21 @@ export function getSQLCipherVersion(db: Database): string | undefined { export function batchMultiVarQuery( db: Database, - values: Array, - query: (batch: Array) => void + values: ReadonlyArray, + query: (batch: ReadonlyArray) => void ): []; export function batchMultiVarQuery( db: Database, - values: Array, - query: (batch: Array) => Array + values: ReadonlyArray, + query: (batch: ReadonlyArray) => Array ): Array; export function batchMultiVarQuery( db: Database, - values: Array, + values: ReadonlyArray, query: - | ((batch: Array) => void) - | ((batch: Array) => Array) + | ((batch: ReadonlyArray) => void) + | ((batch: ReadonlyArray) => Array) ): Array { if (values.length > MAX_VARIABLE_COUNT) { const result: Array = []; @@ -187,7 +187,7 @@ export function removeById( throw new Error('removeById: No ids to delete!'); } - const removeByIdsSync = (ids: Array): void => { + const removeByIdsSync = (ids: ReadonlyArray): void => { db.prepare( ` DELETE FROM ${table} diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 3cea204ea2e8..0da7c4669fe7 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -170,7 +170,7 @@ export type ConversationType = { about?: string; aboutText?: string; aboutEmoji?: string; - avatars?: Array; + avatars?: ReadonlyArray; avatarPath?: string; avatarHash?: string; profileAvatarPath?: string; @@ -215,24 +215,24 @@ export type ConversationType = { announcementsOnly?: boolean; announcementsOnlyReady?: boolean; expireTimer?: DurationInSeconds; - memberships?: Array<{ + memberships?: ReadonlyArray<{ uuid: UUIDStringType; isAdmin: boolean; }>; - pendingMemberships?: Array<{ + pendingMemberships?: ReadonlyArray<{ uuid: UUIDStringType; addedByUserId?: UUIDStringType; }>; - pendingApprovalMemberships?: Array<{ + pendingApprovalMemberships?: ReadonlyArray<{ uuid: UUIDStringType; }>; - bannedMemberships?: Array; + bannedMemberships?: ReadonlyArray; muteExpiresAt?: number; dontNotifyForMentionsIfMuted?: boolean; isMe: boolean; lastUpdated?: number; // This is used by the CompositionInput for @mentions - sortedGroupMembers?: Array; + sortedGroupMembers?: ReadonlyArray; title: string; titleNoDefault?: string; searchableTitle?: string; @@ -240,7 +240,7 @@ export type ConversationType = { isSelected?: boolean; isFetchingUUID?: boolean; typingContactId?: string; - recentMediaItems?: Array; + recentMediaItems?: ReadonlyArray; profileSharing?: boolean; shouldShowDraft?: boolean; @@ -248,7 +248,7 @@ export type ConversationType = { draftBodyRanges?: DraftBodyRangesType; draftPreview?: string; - sharedGroupNames: Array; + sharedGroupNames: ReadonlyArray; groupDescription?: string; groupVersion?: 1 | 2; groupId?: string; @@ -260,7 +260,7 @@ export type ConversationType = { profileKey?: string; voiceNotePlaybackRate?: number; - badges: Array< + badges: ReadonlyArray< | { id: string; } @@ -312,7 +312,7 @@ export type MessageLookupType = { export type ConversationMessageType = { isNearBottom?: boolean; messageChangeCounter: number; - messageIds: Array; + messageIds: ReadonlyArray; messageLoadingState?: undefined | TimelineMessageLoadingState; metrics: MessageMetricsType; scrollToMessageId?: string; @@ -340,8 +340,8 @@ type ComposerGroupCreationState = { groupExpireTimer: DurationInSeconds; maximumGroupSizeModalState: OneTimeModalState; recommendedGroupSizeModalState: OneTimeModalState; - selectedConversationIds: Array; - userAvatarData: Array; + selectedConversationIds: ReadonlyArray; + userAvatarData: ReadonlyArray; }; type DistributionVerificationData = { @@ -397,7 +397,7 @@ type ContactSpoofingReviewStateType = export type ConversationsStateType = { preJoinConversation?: PreJoinConversationType; - invitedUuidsForNewlyCreatedGroup?: Array; + invitedUuidsForNewlyCreatedGroup?: ReadonlyArray; conversationLookup: ConversationLookupType; conversationsByE164: ConversationLookupType; conversationsByUuid: ConversationLookupType; @@ -407,8 +407,9 @@ export type ConversationsStateType = { selectedMessage: string | undefined; selectedMessageCounter: number; selectedMessageSource: SelectedMessageSource | undefined; - selectedConversationPanels: Array; + selectedConversationPanels: ReadonlyArray; selectedMessageForDetails?: MessageAttributesType; + showArchived: boolean; composer?: ComposerStateType; contactSpoofingReview?: ContactSpoofingReviewStateType; @@ -600,7 +601,7 @@ type CreateGroupPendingActionType = { type CreateGroupFulfilledActionType = { type: 'CREATE_GROUP_FULFILLED'; payload: { - invitedUuids: Array; + invitedUuids: ReadonlyArray; }; }; type CreateGroupRejectedActionType = { @@ -655,7 +656,7 @@ export type MessagesAddedActionType = { isActive: boolean; isJustSent: boolean; isNewMessage: boolean; - messages: Array; + messages: ReadonlyArray; }; }; @@ -682,7 +683,7 @@ export type MessagesResetActionType = { type: 'MESSAGES_RESET'; payload: { conversationId: string; - messages: Array; + messages: ReadonlyArray; metrics: MessageMetricsType; scrollToMessageId?: string; // The set of provided messages should be trusted, even if it conflicts with metrics, @@ -776,7 +777,7 @@ type SetRecentMediaItemsActionType = { type: 'SET_RECENT_MEDIA_ITEMS'; payload: { id: string; - recentMediaItems: Array; + recentMediaItems: ReadonlyArray; }; }; type ToggleComposeEditingAvatarActionType = { @@ -812,7 +813,7 @@ type ReplaceAvatarsActionType = { type: typeof REPLACE_AVATARS; payload: { conversationId: string; - avatars: Array; + avatars: ReadonlyArray; }; }; @@ -1230,7 +1231,7 @@ function filterAvatarData( return avatars.filter(avatarData => !isSameAvatarData(data, avatarData)); } -function getNextAvatarId(avatars: Array): number { +function getNextAvatarId(avatars: ReadonlyArray): number { return Math.max(...avatars.map(x => Number(x.id))) + 1; } @@ -1238,10 +1239,10 @@ async function getAvatarsAndUpdateConversation( conversations: ConversationsStateType, conversationId: string, getNextAvatarsData: ( - avatars: Array, + avatars: ReadonlyArray, nextId: number - ) => Array -): Promise> { + ) => ReadonlyArray +): Promise> { const conversation = window.ConversationController.get(conversationId); if (!conversation) { throw new Error('getAvatarsAndUpdateConversation: No conversation found'); @@ -2415,7 +2416,7 @@ function messagesAdded({ isActive: boolean; isJustSent: boolean; isNewMessage: boolean; - messages: Array; + messages: ReadonlyArray; }): MessagesAddedActionType { return { type: 'MESSAGES_ADDED', @@ -2469,7 +2470,7 @@ function reviewMessageRequestNameCollision( export type MessageResetOptionsType = Readonly<{ conversationId: string; - messages: Array; + messages: ReadonlyArray; metrics: MessageMetricsType; scrollToMessageId?: string; unboundedFetch?: boolean; @@ -2705,7 +2706,7 @@ function approvePendingMembershipFromGroupV2( function revokePendingMembershipsFromGroupV2( conversationId: string, - memberIds: Array + memberIds: ReadonlyArray ): ThunkAction { return async dispatch => { const conversation = window.ConversationController.get(conversationId); @@ -3340,7 +3341,7 @@ function leaveGroup( } function toggleGroupsForStorySend( - conversationIds: Array + conversationIds: ReadonlyArray ): ThunkAction, RootStateType, unknown, NoopActionType> { return async dispatch => { await Promise.all( @@ -4018,7 +4019,7 @@ export function reducer( ...omit(state, 'contactSpoofingReview'), selectedConversationId, selectedConversationPanels: [], - messagesLookup: omit(state.messagesLookup, messageIds), + messagesLookup: omit(state.messagesLookup, [...messageIds]), messagesByConversation: omit(state.messagesByConversation, [id]), }; } @@ -4930,7 +4931,7 @@ export function reducer( } if (action.type === 'SHOW_CHOOSE_GROUP_MEMBERS') { - let selectedConversationIds: Array; + let selectedConversationIds: ReadonlyArray; let recommendedGroupSizeModalState: OneTimeModalState; let maximumGroupSizeModalState: OneTimeModalState; let groupName: string; diff --git a/ts/state/ducks/items.ts b/ts/state/ducks/items.ts index 8ac80d2cf051..56abbd728f28 100644 --- a/ts/state/ducks/items.ts +++ b/ts/state/ducks/items.ts @@ -37,7 +37,7 @@ export type ItemsStateType = { readonly preferredLeftPaneWidth?: number; - readonly preferredReactionEmoji?: Array; + readonly preferredReactionEmoji?: ReadonlyArray; readonly areWeASubscriber?: boolean; }; diff --git a/ts/state/ducks/lightbox.ts b/ts/state/ducks/lightbox.ts index ee52cc2e5898..365f964da11c 100644 --- a/ts/state/ducks/lightbox.ts +++ b/ts/state/ducks/lightbox.ts @@ -32,7 +32,7 @@ export type LightboxStateType = | { isShowingLightbox: true; isViewOnce: boolean; - media: Array; + media: ReadonlyArray; selectedAttachmentPath: string | undefined; }; @@ -47,7 +47,7 @@ type ShowLightboxActionType = { type: typeof SHOW_LIGHTBOX; payload: { isViewOnce: boolean; - media: Array; + media: ReadonlyArray; selectedAttachmentPath: string | undefined; }; }; @@ -89,7 +89,7 @@ function closeLightbox(): ThunkAction< function showLightboxWithMedia( selectedAttachmentPath: string | undefined, - media: Array + media: ReadonlyArray ): ShowLightboxActionType { return { type: SHOW_LIGHTBOX, diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index e4bedbfee4c2..f7cef573d776 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -279,7 +279,7 @@ export const _getLeftPaneLists = ( lookup: ConversationLookupType, comparator: (left: ConversationType, right: ConversationType) => number, selectedConversation?: string, - pinnedConversationIds?: Array + pinnedConversationIds?: ReadonlyArray ): { conversations: Array; archivedConversations: Array; @@ -603,7 +603,7 @@ export const getFilteredComposeContacts = createSelector( getRegionCode, ( searchTerm: string, - contacts: Array, + contacts: ReadonlyArray, regionCode: string | undefined ): Array => { return filterAndSortConversationsByRecent(contacts, searchTerm, regionCode); @@ -616,7 +616,7 @@ export const getFilteredComposeGroups = createSelector( getRegionCode, ( searchTerm: string, - groups: Array, + groups: ReadonlyArray, regionCode: string | undefined ): Array => { return filterAndSortConversationsByRecent(groups, searchTerm, regionCode); @@ -638,7 +638,7 @@ const getGroupCreationComposerState = createSelector( groupName: string; groupAvatar: undefined | Uint8Array; groupExpireTimer: DurationInSeconds; - selectedConversationIds: Array; + selectedConversationIds: ReadonlyArray; } => { switch (composerState?.step) { case ComposerStep.ChooseGroupMembers: diff --git a/ts/state/selectors/lightbox.ts b/ts/state/selectors/lightbox.ts index 317c7e6e7df7..49c0478b2dd2 100644 --- a/ts/state/selectors/lightbox.ts +++ b/ts/state/selectors/lightbox.ts @@ -36,5 +36,6 @@ export const getSelectedIndex = createSelector( export const getMedia = createSelector( getLightboxState, - (state): Array => (state.isShowingLightbox ? state.media : []) + (state): ReadonlyArray => + state.isShowingLightbox ? state.media : [] ); diff --git a/ts/state/smart/Lightbox.tsx b/ts/state/smart/Lightbox.tsx index 157a65b3cd05..6eba3dd326fa 100644 --- a/ts/state/smart/Lightbox.tsx +++ b/ts/state/smart/Lightbox.tsx @@ -33,7 +33,7 @@ export function SmartLightbox(): JSX.Element | null { const isShowingLightbox = useSelector(shouldShowLightbox); const isViewOnce = useSelector(getIsViewOnce); - const media = useSelector>(getMedia); + const media = useSelector>(getMedia); const selectedIndex = useSelector(getSelectedIndex); if (!isShowingLightbox) { diff --git a/ts/state/smart/ReactionPicker.tsx b/ts/state/smart/ReactionPicker.tsx index 717c086b1623..c76e0d95c218 100644 --- a/ts/state/smart/ReactionPicker.tsx +++ b/ts/state/smart/ReactionPicker.tsx @@ -34,7 +34,7 @@ export const SmartReactionPicker = React.forwardRef< const i18n = useSelector(getIntl); - const preferredReactionEmoji = useSelector>( + const preferredReactionEmoji = useSelector>( getPreferredReactionEmoji ); diff --git a/ts/state/smart/StoryViewer.tsx b/ts/state/smart/StoryViewer.tsx index d703c5e8c1f7..d9a6887409ba 100644 --- a/ts/state/smart/StoryViewer.tsx +++ b/ts/state/smart/StoryViewer.tsx @@ -54,7 +54,7 @@ export function SmartStoryViewer(): JSX.Element | null { const i18n = useSelector(getIntl); const getPreferredBadge = useSelector(getPreferredBadgeSelector); - const preferredReactionEmoji = useSelector>( + const preferredReactionEmoji = useSelector>( getPreferredReactionEmoji ); diff --git a/ts/test-electron/quill/mentions/completion_test.tsx b/ts/test-electron/quill/mentions/completion_test.tsx index f322860422e2..30d24d4358b7 100644 --- a/ts/test-electron/quill/mentions/completion_test.tsx +++ b/ts/test-electron/quill/mentions/completion_test.tsx @@ -99,7 +99,7 @@ describe('MentionCompletion', () => { describe('onTextChange', () => { let possiblyShowMemberResultsStub: sinon.SinonStub< [], - Array + ReadonlyArray >; beforeEach(() => { diff --git a/ts/textsecure/SendMessage.ts b/ts/textsecure/SendMessage.ts index 246cd06c3d6d..3d859a821601 100644 --- a/ts/textsecure/SendMessage.ts +++ b/ts/textsecure/SendMessage.ts @@ -97,11 +97,11 @@ export type GroupV2InfoType = { groupChange?: Uint8Array; masterKey: Uint8Array; revision: number; - members: Array; + members: ReadonlyArray; }; export type GroupV1InfoType = { id: string; - members: Array; + members: ReadonlyArray; }; type GroupCallUpdateType = { diff --git a/ts/types/Attachment.ts b/ts/types/Attachment.ts index c75bdb010de5..ca851aeb84f8 100644 --- a/ts/types/Attachment.ts +++ b/ts/types/Attachment.ts @@ -726,14 +726,16 @@ export function hasFailed(attachment?: AttachmentType): boolean { return Boolean(resolved && resolved.error); } -export function hasVideoBlurHash(attachments?: Array): boolean { +export function hasVideoBlurHash( + attachments?: ReadonlyArray +): boolean { const firstAttachment = attachments ? attachments[0] : null; return Boolean(firstAttachment && firstAttachment.blurHash); } export function hasVideoScreenshot( - attachments?: Array + attachments?: ReadonlyArray ): string | null | undefined { const firstAttachment = attachments ? attachments[0] : null; diff --git a/ts/types/Avatar.ts b/ts/types/Avatar.ts index d4c4151b5b3c..c6bd46d5d2e2 100644 --- a/ts/types/Avatar.ts +++ b/ts/types/Avatar.ts @@ -118,7 +118,9 @@ const personalDefaultAvatars = PersonalAvatarIcons.map((icon, index) => ({ icon, })); -export function getDefaultAvatars(isGroup?: boolean): Array { +export function getDefaultAvatars( + isGroup?: boolean +): ReadonlyArray { if (isGroup) { return groupDefaultAvatars; } diff --git a/ts/types/Storage.d.ts b/ts/types/Storage.d.ts index efa3eb9a17d5..307dacca8589 100644 --- a/ts/types/Storage.d.ts +++ b/ts/types/Storage.d.ts @@ -49,8 +49,8 @@ export type StorageAccessType = { 'audio-notification': boolean; 'auto-download-update': boolean; 'badge-count-muted-conversations': boolean; - 'blocked-groups': Array; - 'blocked-uuids': Array; + 'blocked-groups': ReadonlyArray; + 'blocked-uuids': ReadonlyArray; 'call-ringtone-notification': boolean; 'call-system-notification': boolean; 'hide-menu-bar': boolean; @@ -64,11 +64,11 @@ export type StorageAccessType = { 'theme-setting': ThemeSettingType; attachmentMigration_isComplete: boolean; attachmentMigration_lastProcessedIndex: number; - blocked: Array; + blocked: ReadonlyArray; defaultConversationColor: DefaultConversationColorType; customColors: CustomColorsItemType; device_name: string; - existingOnboardingStoryMessageIds: Array | undefined; + existingOnboardingStoryMessageIds: ReadonlyArray | undefined; hasRegisterSupportForUnauthenticatedDelivery: boolean; hasSetMyStoriesPrivacy: boolean; hasViewedOnboardingStory: boolean; @@ -98,12 +98,12 @@ export type StorageAccessType = { version: string; linkPreviews: boolean; universalExpireTimer: number; - retryPlaceholders: Array; + retryPlaceholders: ReadonlyArray; chromiumRegistrationDoneEver: ''; chromiumRegistrationDone: ''; phoneNumberSharingMode: PhoneNumberSharingMode; phoneNumberDiscoverability: PhoneNumberDiscoverability; - pinnedConversationIds: Array; + pinnedConversationIds: ReadonlyArray; preferContactAvatars: boolean; primarySendsSms: boolean; // Unlike `number_id` (which also includes device id) this field is only @@ -115,18 +115,18 @@ export type StorageAccessType = { avatarUrl: string | undefined; manifestVersion: number; storageCredentials: StorageServiceCredentials; - 'storage-service-error-records': Array; - 'storage-service-unknown-records': Array; - 'storage-service-pending-deletes': Array; + 'storage-service-error-records': ReadonlyArray; + 'storage-service-unknown-records': ReadonlyArray; + 'storage-service-pending-deletes': ReadonlyArray; 'preferred-video-input-device': string; 'preferred-audio-input-device': AudioDevice; 'preferred-audio-output-device': AudioDevice; previousAudioDeviceModule: AudioDeviceModule; remoteConfig: RemoteConfigType; unidentifiedDeliveryIndicators: boolean; - groupCredentials: Array; + groupCredentials: ReadonlyArray; lastReceivedAtCounter: number; - preferredReactionEmoji: Array; + preferredReactionEmoji: ReadonlyArray; skinTone: number; unreadCount: number; 'challenge:conversations': ReadonlyArray; diff --git a/ts/util/getAvatarData.ts b/ts/util/getAvatarData.ts index f1e56610c62b..20c6f7d4f166 100644 --- a/ts/util/getAvatarData.ts +++ b/ts/util/getAvatarData.ts @@ -8,7 +8,7 @@ import type { ConversationAttributesType } from '../model-types.d'; export function getAvatarData( conversationAttrs: Pick -): Array { +): ReadonlyArray { const { avatars } = conversationAttrs; if (avatars && avatars.length) { diff --git a/ts/util/getGroupMemberships.ts b/ts/util/getGroupMemberships.ts index ab99eb23fb16..5690224a0d7a 100644 --- a/ts/util/getGroupMemberships.ts +++ b/ts/util/getGroupMemberships.ts @@ -11,9 +11,9 @@ import type { UUIDStringType } from '../types/UUID'; import { isConversationUnregistered } from './isConversationUnregistered'; export type GroupMemberships = { - memberships: Array; - pendingApprovalMemberships: Array; - pendingMemberships: Array; + memberships: ReadonlyArray; + pendingApprovalMemberships: ReadonlyArray; + pendingMemberships: ReadonlyArray; }; export const getGroupMemberships = ( @@ -30,7 +30,7 @@ export const getGroupMemberships = ( getConversationByUuid: (uuid: UUIDStringType) => undefined | ConversationType ): GroupMemberships => ({ memberships: memberships.reduce( - (result: Array, membership) => { + (result: ReadonlyArray, membership) => { const member = getConversationByUuid(membership.uuid); if (!member) { return result; @@ -40,7 +40,7 @@ export const getGroupMemberships = ( [] ), pendingApprovalMemberships: pendingApprovalMemberships.reduce( - (result: Array, membership) => { + (result: ReadonlyArray, membership) => { const member = getConversationByUuid(membership.uuid); if (!member || isConversationUnregistered(member)) { return result; @@ -50,7 +50,7 @@ export const getGroupMemberships = ( [] ), pendingMemberships: pendingMemberships.reduce( - (result: Array, membership) => { + (result: ReadonlyArray, membership) => { const member = getConversationByUuid(membership.uuid); if (!member || isConversationUnregistered(member)) { return result; diff --git a/ts/util/getRecipients.ts b/ts/util/getRecipients.ts index cb9da2f40c51..3b4e97be5a14 100644 --- a/ts/util/getRecipients.ts +++ b/ts/util/getRecipients.ts @@ -18,7 +18,7 @@ export function getRecipients( isStoryReply = false, }: { includePendingMembers?: boolean; - extraConversationsForSend?: Array; + extraConversationsForSend?: ReadonlyArray; isStoryReply?: boolean; } = {} ): Array { diff --git a/ts/util/maybeForwardMessage.ts b/ts/util/maybeForwardMessage.ts index 347dc42be6fa..b64ba2c61d6e 100644 --- a/ts/util/maybeForwardMessage.ts +++ b/ts/util/maybeForwardMessage.ts @@ -14,9 +14,9 @@ import { getRecipientsByConversation } from './getRecipientsByConversation'; export async function maybeForwardMessage( messageAttributes: MessageAttributesType, - conversationIds: Array, + conversationIds: ReadonlyArray, messageBody?: string, - attachments?: Array, + attachments?: ReadonlyArray, linkPreview?: LinkPreviewType ): Promise { const idForLogging = getMessageIdForLogging(messageAttributes); diff --git a/ts/util/sendToGroup.ts b/ts/util/sendToGroup.ts index d9a54525d20d..217b165707e3 100644 --- a/ts/util/sendToGroup.ts +++ b/ts/util/sendToGroup.ts @@ -167,7 +167,7 @@ export async function sendContentMessageToGroup({ isPartialSend?: boolean; messageId: string | undefined; online?: boolean; - recipients: Array; + recipients: ReadonlyArray; sendOptions?: SendOptionsType; sendTarget: SenderKeyTargetType; sendType: SendTypesType; @@ -254,7 +254,7 @@ export async function sendToGroupViaSenderKey(options: { isPartialSend?: boolean; messageId: string | undefined; online?: boolean; - recipients: Array; + recipients: ReadonlyArray; recursionCount: number; sendOptions?: SendOptionsType; sendTarget: SenderKeyTargetType; @@ -836,7 +836,7 @@ export function _shouldFailSend(error: unknown, logId: string): boolean { return false; } -function getRecipients(options: GroupSendOptionsType): Array { +function getRecipients(options: GroupSendOptionsType): ReadonlyArray { if (options.groupV2) { return options.groupV2.members; }