signal-desktop/ts/model-types.d.ts

502 lines
15 KiB
TypeScript
Raw Normal View History

2023-01-03 19:55:46 +00:00
// Copyright 2020 Signal Messenger, LLC
2020-10-30 20:34:04 +00:00
// SPDX-License-Identifier: AGPL-3.0-only
import * as Backbone from 'backbone';
2022-09-06 20:51:34 +00:00
import type { GroupV2ChangeType } from './groups';
import type { DraftBodyRanges, RawBodyRange } from './types/BodyRange';
2022-09-06 20:51:34 +00:00
import type { CustomColorType, ConversationColorType } from './types/Colors';
import type { SendMessageChallengeData } from './textsecure/Errors';
import type { ConversationModel } from './models/conversations';
import type { ProfileNameChangeType } from './util/getStringForProfileChange';
import type { CapabilitiesType } from './textsecure/WebAPI';
import type { ReadStatus } from './messages/MessageReadStatus';
import type { SendStateByConversationId } from './messages/MessageSendState';
import type { GroupNameCollisionsWithIdsByTitle } from './util/groupMemberNameCollisions';
import type { AttachmentDraftType, AttachmentType } from './types/Attachment';
import type { EmbeddedContactType } from './types/EmbeddedContact';
2021-07-13 18:54:53 +00:00
import { SignalService as Proto } from './protobuf';
import type { AvatarDataType, ContactAvatarType } from './types/Avatar';
import type { AciString, PniString, ServiceIdString } from './types/ServiceId';
import type { StoryDistributionIdString } from './types/StoryDistributionId';
2022-09-06 20:51:34 +00:00
import type { SeenStatus } from './MessageSeenStatus';
import type { GiftBadgeStates } from './components/conversation/Message';
import type { LinkPreviewType } from './types/message/LinkPreviews';
import type { StickerType } from './types/Stickers';
import type { StorySendMode } from './types/Stories';
2022-09-06 20:51:34 +00:00
import type { MIMEType } from './types/MIME';
2022-11-16 20:18:02 +00:00
import type { DurationInSeconds } from './util/durations';
2022-11-30 21:47:54 +00:00
import type { AnyPaymentEvent } from './types/Payment';
2021-07-13 18:54:53 +00:00
import AccessRequiredEnum = Proto.AccessControl.AccessRequired;
import MemberRoleEnum = Proto.Member.Role;
export type LastMessageStatus =
| 'paused'
| 'error'
| 'partial-sent'
| 'sending'
| 'sent'
| 'delivered'
| 'read'
| 'viewed';
export type SenderKeyDeviceType = {
id: number;
2023-08-16 20:54:39 +00:00
serviceId: ServiceIdString;
registrationId: number;
};
export type SenderKeyInfoType = {
createdAtDate: number;
distributionId: string;
memberDevices: Array<SenderKeyDeviceType>;
};
export type CustomError = Error & {
serviceId?: ServiceIdString;
number?: string;
data?: object;
retryAfter?: number;
};
export type GroupMigrationType = {
areWeInvited: boolean;
droppedMemberIds: Array<string>;
2023-08-16 20:54:39 +00:00
invitedMembers: Array<LegacyMigrationPendingMemberType>;
};
export type QuotedAttachment = {
contentType: MIMEType;
fileName?: string;
thumbnail?: AttachmentType;
};
2022-03-04 21:14:52 +00:00
2021-04-14 22:15:57 +00:00
export type QuotedMessageType = {
2022-07-13 00:37:21 +00:00
// TODO DESKTOP-3826
2022-09-06 20:51:34 +00:00
// eslint-disable-next-line @typescript-eslint/no-explicit-any
attachments: ReadonlyArray<any>;
2022-11-30 21:47:54 +00:00
payment?: AnyPaymentEvent;
2021-04-14 22:15:57 +00:00
// `author` is an old attribute that holds the author's E164. We shouldn't use it for
// new messages, but old messages might have this attribute.
author?: string;
2023-08-16 20:54:39 +00:00
authorAci?: AciString;
bodyRanges?: ReadonlyArray<RawBodyRange>;
2021-07-09 19:36:10 +00:00
id: number;
2022-05-11 20:59:58 +00:00
isGiftBadge?: boolean;
isViewOnce: boolean;
2021-06-25 16:08:16 +00:00
messageId: string;
2022-05-11 20:59:58 +00:00
referencedMessageNotFound: boolean;
text?: string;
2021-04-14 22:15:57 +00:00
};
2022-03-16 17:30:14 +00:00
type StoryReplyContextType = {
attachment?: AttachmentType;
2023-08-16 20:54:39 +00:00
authorAci?: AciString;
2022-03-16 17:30:14 +00:00
messageId: string;
};
2021-06-23 16:14:11 +00:00
export type GroupV1Update = {
avatarUpdated?: boolean;
joined?: Array<string>;
left?: string | 'You';
name?: string;
};
export type MessageReactionType = {
emoji: undefined | string;
fromId: string;
targetTimestamp: number;
timestamp: number;
2023-12-08 01:30:20 +00:00
receivedAtDate: undefined | number;
isSentByConversationId?: Record<string, boolean>;
};
// Note: when adding to the set of things that can change via edits, sendNormalMessage.ts
// needs more usage of get/setPropForTimestamp.
2023-03-27 23:48:57 +00:00
export type EditHistoryType = {
attachments?: Array<AttachmentType>;
body?: string;
bodyRanges?: ReadonlyArray<RawBodyRange>;
2023-03-27 23:48:57 +00:00
preview?: Array<LinkPreviewType>;
quote?: QuotedMessageType;
2023-08-15 23:24:19 +00:00
sendStateByConversationId?: SendStateByConversationId;
2023-03-27 23:48:57 +00:00
timestamp: number;
};
2020-09-11 19:37:01 +00:00
export type MessageAttributesType = {
bodyAttachment?: AttachmentType;
bodyRanges?: ReadonlyArray<RawBodyRange>;
2023-08-09 00:53:06 +00:00
callId?: string;
2022-07-01 00:52:03 +00:00
canReplyToStory?: boolean;
changedId?: string;
2021-09-24 00:49:05 +00:00
dataMessage?: Uint8Array | null;
decrypted_at?: number;
deletedForEveryone?: boolean;
deletedForEveryoneTimestamp?: number;
errors?: Array<CustomError>;
expirationStartTimestamp?: number | null;
2022-11-16 20:18:02 +00:00
expireTimer?: DurationInSeconds;
groupMigration?: GroupMigrationType;
2021-06-23 16:14:11 +00:00
group_update?: GroupV1Update;
hasAttachments?: boolean | 0 | 1;
hasFileAttachments?: boolean | 0 | 1;
hasVisualMediaAttachments?: boolean | 0 | 1;
mentionsMe?: boolean | 0 | 1;
isErased?: boolean;
isTapToViewInvalid?: boolean;
isViewOnce?: boolean;
2023-03-27 23:48:57 +00:00
editHistory?: Array<EditHistoryType>;
editMessageTimestamp?: number;
key_changed?: string;
local?: boolean;
logger?: unknown;
message?: unknown;
messageTimer?: unknown;
profileChange?: ProfileNameChangeType;
2022-11-30 21:47:54 +00:00
payment?: AnyPaymentEvent;
2021-04-14 22:15:57 +00:00
quote?: QuotedMessageType;
2022-11-02 23:48:38 +00:00
reactions?: ReadonlyArray<MessageReactionType>;
requiredProtocolVersion?: number;
sourceDevice?: number;
storyDistributionListId?: StoryDistributionIdString;
storyId?: string;
2022-03-16 17:30:14 +00:00
storyReplyContext?: StoryReplyContextType;
2022-11-29 02:07:26 +00:00
storyRecipientsVersion?: number;
supportedVersionAtReceive?: unknown;
synced?: boolean;
unidentifiedDeliveryReceived?: boolean;
verified?: boolean;
verifiedChanged?: string;
id: string;
type:
| 'call-history'
| 'change-number-notification'
| 'chat-session-refreshed'
| 'conversation-merge'
2021-05-28 19:11:19 +00:00
| 'delivery-issue'
| 'group-v1-migration'
| 'group-v2-change'
| 'group'
2021-05-28 19:11:19 +00:00
| 'incoming'
| 'keychange'
| 'outgoing'
| 'phone-number-discovery'
| 'profile-change'
| 'story'
2021-05-28 19:11:19 +00:00
| 'timer-notification'
2021-06-01 20:45:43 +00:00
| 'universal-timer-notification'
2023-04-05 20:48:00 +00:00
| 'contact-removed-notification'
2021-05-28 19:11:19 +00:00
| 'verified-change';
body?: string;
attachments?: Array<AttachmentType>;
preview?: Array<LinkPreviewType>;
sticker?: StickerType;
2021-05-03 16:38:20 +00:00
sent_at: number;
unidentifiedDeliveries?: Array<string>;
contact?: Array<EmbeddedContactType>;
conversationId: string;
2022-11-02 23:48:38 +00:00
storyReaction?: {
emoji: string;
2023-08-16 20:54:39 +00:00
targetAuthorAci: AciString;
2022-11-02 23:48:38 +00:00
targetTimestamp: number;
};
2022-05-11 20:59:58 +00:00
giftBadge?: {
expiration: number;
level: number;
2022-05-16 19:54:38 +00:00
id: string | undefined;
2022-05-11 20:59:58 +00:00
receiptCredentialPresentation: string;
state: GiftBadgeStates;
};
2020-09-09 02:25:05 +00:00
expirationTimerUpdate?: {
2022-11-16 20:18:02 +00:00
expireTimer?: DurationInSeconds;
fromSync?: unknown;
2020-09-09 02:25:05 +00:00
source?: string;
2023-08-16 20:54:39 +00:00
sourceServiceId?: ServiceIdString;
2020-09-09 02:25:05 +00:00
};
phoneNumberDiscovery?: {
e164: string;
};
conversationMerge?: {
renderInfo: ConversationRenderInfoType;
};
2020-09-09 02:25:05 +00:00
// Legacy fields for timer update notification only
flags?: number;
groupV2Change?: GroupV2ChangeType;
// Required. Used to sort messages in the database for the conversation timeline.
received_at: number;
2021-03-04 21:44:57 +00:00
received_at_ms?: number;
2020-09-09 02:25:05 +00:00
// More of a legacy feature, needed as we were updating the schema of messages in the
// background, when we were still in IndexedDB, before attachments had gone to disk
// We set this so that the idle message upgrade process doesn't pick this message up
schemaVersion?: number;
// migrateMessageData will increment this field on every failure and give up
// when the value is too high.
schemaMigrationAttempts?: number;
// This should always be set for new messages, but older messages may not have them. We
// may not have these for outbound messages, either, as we have not needed them.
serverGuid?: string;
2020-09-09 02:25:05 +00:00
serverTimestamp?: number;
source?: string;
2023-08-16 20:54:39 +00:00
sourceServiceId?: ServiceIdString;
timestamp: number;
// Backwards-compatibility with prerelease data schema
2023-08-16 20:54:39 +00:00
invitedGV2Members?: Array<LegacyMigrationPendingMemberType>;
droppedGV2MemberIds?: Array<string>;
2021-07-09 19:36:10 +00:00
sendHQImages?: boolean;
// Should only be present for incoming messages and errors
2022-09-21 23:54:48 +00:00
readAt?: number;
readStatus?: ReadStatus;
// Used for all kinds of notifications, as well as incoming messages
seenStatus?: SeenStatus;
// Should only be present for outgoing messages
sendStateByConversationId?: SendStateByConversationId;
// Should only be present for messages deleted for everyone
deletedForEveryoneSendStatus?: Record<string, boolean>;
deletedForEveryoneFailed?: boolean;
};
2022-09-06 20:51:34 +00:00
/* eslint-enable camelcase */
export type ConversationAttributesTypeType = 'private' | 'group';
export type ConversationLastProfileType = Readonly<{
profileKey: string;
profileKeyVersion: string;
}>;
2022-07-13 00:37:21 +00:00
export type ValidateConversationType = Pick<
ConversationAttributesType,
2023-08-16 20:54:39 +00:00
'e164' | 'serviceId' | 'type' | 'groupId'
2022-07-13 00:37:21 +00:00
>;
export type DraftEditMessageType = {
editHistoryLength: number;
attachmentThumbnail?: string;
bodyRanges?: DraftBodyRanges;
body: string;
preview?: LinkPreviewType;
targetMessageId: string;
quote?: QuotedMessageType;
};
2020-09-11 19:37:01 +00:00
export type ConversationAttributesType = {
accessKey?: string | null;
2020-10-06 17:06:34 +00:00
addedBy?: string;
2021-11-02 23:01:13 +00:00
badges?: Array<
| { id: string }
| {
id: string;
expiresAt: number;
isVisible: boolean;
}
>;
2020-11-20 17:30:45 +00:00
capabilities?: CapabilitiesType;
color?: string;
conversationColor?: ConversationColorType;
2021-05-28 16:15:17 +00:00
customColor?: CustomColorType;
customColorId?: string;
discoveredUnregisteredAt?: number;
firstUnregisteredAt?: number;
2021-08-30 21:32:56 +00:00
draftChanged?: boolean;
draftAttachments?: ReadonlyArray<AttachmentDraftType>;
draftBodyRanges?: DraftBodyRanges;
draftTimestamp?: number | null;
2022-03-04 21:14:52 +00:00
hideStory?: boolean;
inbox_position?: number;
2023-04-05 20:48:00 +00:00
// When contact is removed - it is initially placed into `justNotification`
// removal stage. In this stage user can still send messages (which will
// set `removalStage` to `undefined`), but if a new incoming message arrives -
// the stage will progress to `messageRequest` and composition area will be
// replaced with a message request.
removalStage?: 'justNotification' | 'messageRequest';
isPinned?: boolean;
lastMessageDeletedForEveryone?: boolean;
lastMessage?: string | null;
lastMessageBodyRanges?: ReadonlyArray<RawBodyRange>;
lastMessagePrefix?: string;
lastMessageAuthor?: string | null;
lastMessageStatus?: LastMessageStatus | null;
markedUnread?: boolean;
messageCount?: number;
messageCountBeforeMessageRequests?: number | null;
messageRequestResponseType?: number;
muteExpiresAt?: number;
2021-08-05 12:35:33 +00:00
dontNotifyForMentionsIfMuted?: boolean;
profileAvatar?: ContactAvatarType | null;
profileKeyCredential?: string | null;
2022-07-08 20:46:25 +00:00
profileKeyCredentialExpiration?: number | null;
lastProfile?: ConversationLastProfileType;
quotedMessageId?: string | null;
sealedSender?: unknown;
sentMessageCount?: number;
sharedGroupNames?: ReadonlyArray<string>;
voiceNotePlaybackRate?: number;
id: string;
type: ConversationAttributesTypeType;
timestamp?: number | null;
2020-09-09 02:25:05 +00:00
// Shared fields
active_at?: number | null;
draft?: string | null;
draftEditMessage?: DraftEditMessageType;
2022-03-29 01:10:08 +00:00
hasPostedStory?: boolean;
isArchived?: boolean;
2020-09-09 02:25:05 +00:00
name?: string;
systemGivenName?: string;
systemFamilyName?: string;
2023-02-13 22:40:11 +00:00
systemNickname?: string;
2020-09-09 00:56:23 +00:00
needsStorageServiceSync?: boolean;
needsVerification?: boolean;
profileSharing?: boolean;
storageID?: string;
2022-02-08 18:00:18 +00:00
storageVersion?: number;
storageUnknownFields?: string;
unreadCount?: number;
unreadMentionsCount?: number;
version: number;
2020-09-09 02:25:05 +00:00
// Private core info
2023-08-16 20:54:39 +00:00
serviceId?: ServiceIdString;
pni?: PniString;
2020-09-09 02:25:05 +00:00
e164?: string;
// Private other fields
2021-01-26 01:01:19 +00:00
about?: string;
aboutEmoji?: string;
profileFamilyName?: string;
profileKey?: string;
profileName?: string;
2020-09-09 02:25:05 +00:00
verified?: number;
profileLastFetchedAt?: number;
2021-06-01 20:45:43 +00:00
pendingUniversalTimer?: string;
2023-04-05 20:48:00 +00:00
pendingRemovedContactNotification?: string;
username?: string;
2022-08-15 21:53:33 +00:00
shareMyPhoneNumber?: boolean;
previousIdentityKey?: string;
2023-02-08 00:55:12 +00:00
reportingToken?: string;
2020-09-09 02:25:05 +00:00
// Group-only
groupId?: string;
// A shorthand, representing whether the user is part of the group. Not strictly for
// when the user manually left the group. But historically, that was the only way
// to leave a group.
left?: boolean;
2020-09-09 02:25:05 +00:00
groupVersion?: number;
storySendMode?: StorySendMode;
2020-09-09 02:25:05 +00:00
// GroupV1 only
members?: Array<string>;
2020-11-20 17:30:45 +00:00
derivedGroupV2Id?: string;
2020-09-09 02:25:05 +00:00
// GroupV2 core info
masterKey?: string;
secretParams?: string;
publicParams?: string;
revision?: number;
senderKeyInfo?: SenderKeyInfoType;
2020-09-09 02:25:05 +00:00
// GroupV2 other fields
accessControl?: {
attributes: AccessRequiredEnum;
members: AccessRequiredEnum;
addFromInviteLink: AccessRequiredEnum;
2020-09-09 02:25:05 +00:00
};
2021-07-20 20:18:35 +00:00
announcementsOnly?: boolean;
avatar?: ContactAvatarType | null;
2021-08-06 00:17:05 +00:00
avatars?: Array<AvatarDataType>;
2021-06-02 00:24:28 +00:00
description?: string;
2022-11-16 20:18:02 +00:00
expireTimer?: DurationInSeconds;
2020-09-09 02:25:05 +00:00
membersV2?: Array<GroupV2MemberType>;
pendingMembersV2?: Array<GroupV2PendingMemberType>;
pendingAdminApprovalV2?: Array<GroupV2PendingAdminApprovalType>;
2022-03-23 22:34:51 +00:00
bannedMembersV2?: Array<GroupV2BannedMemberType>;
groupInviteLinkPassword?: string;
2020-11-20 17:30:45 +00:00
previousGroupV1Id?: string;
previousGroupV1Members?: Array<string>;
2021-06-01 23:30:25 +00:00
acknowledgedGroupNameCollisions?: GroupNameCollisionsWithIdsByTitle;
// Used only when user is waiting for approval to join via link
isTemporary?: boolean;
temporaryMemberCount?: number;
// Avatars are blurred for some unapproved conversations, but users can manually unblur
// them. If the avatar was unblurred and then changed, we don't update this value so
// the new avatar gets blurred.
//
// This value is useless once the message request has been approved. We don't clean it
// up but could. We don't persist it but could (though we'd probably want to clean it
// up in that case).
unblurredAvatarPath?: string;
2020-09-09 02:25:05 +00:00
};
2022-09-06 20:51:34 +00:00
/* eslint-enable camelcase */
2020-09-09 02:25:05 +00:00
export type ConversationRenderInfoType = Pick<
ConversationAttributesType,
| 'e164'
| 'name'
| 'profileFamilyName'
| 'profileName'
| 'systemGivenName'
| 'systemFamilyName'
| 'systemNickname'
| 'type'
| 'username'
>;
2020-09-09 02:25:05 +00:00
export type GroupV2MemberType = {
2023-08-16 20:54:39 +00:00
aci: AciString;
role: MemberRoleEnum;
2020-09-09 02:25:05 +00:00
joinedAtVersion: number;
// Note that these are temporary flags, generated by applyGroupChange, but eliminated
// by applyGroupState. They are used to make our diff-generation more intelligent but
// not after that.
joinedFromLink?: boolean;
approvedByAdmin?: boolean;
2020-09-09 02:25:05 +00:00
};
2023-08-16 20:54:39 +00:00
export type LegacyMigrationPendingMemberType = {
addedByUserId?: string;
uuid: string;
timestamp: number;
role: MemberRoleEnum;
};
2020-09-09 02:25:05 +00:00
export type GroupV2PendingMemberType = {
addedByUserId?: AciString;
2023-08-16 20:54:39 +00:00
serviceId: ServiceIdString;
2020-09-09 02:25:05 +00:00
timestamp: number;
role: MemberRoleEnum;
};
2022-03-23 22:34:51 +00:00
export type GroupV2BannedMemberType = {
2023-08-16 20:54:39 +00:00
serviceId: ServiceIdString;
2022-03-23 22:34:51 +00:00
timestamp: number;
};
export type GroupV2PendingAdminApprovalType = {
2023-08-16 20:54:39 +00:00
aci: AciString;
timestamp: number;
};
export type ShallowChallengeError = CustomError & {
readonly retryAfter: number;
readonly data: SendMessageChallengeData;
};
2021-04-26 16:38:50 +00:00
export declare class ConversationModelCollectionType extends Backbone.Collection<ConversationModel> {
resetLookups(): void;
}