You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-desktop/ts/models/messageType.ts

254 lines
7.3 KiB
TypeScript

import { defaultsDeep } from 'lodash';
import { v4 as uuidv4 } from 'uuid';
import { CallNotificationType, PropsForMessageWithConvoProps } from '../state/ducks/conversations';
import { AttachmentTypeWithPath } from '../types/Attachment';
import { Reaction, ReactionList, SortedReactionList } from '../types/Reaction';
export type MessageModelType = 'incoming' | 'outgoing';
export type MessageDeliveryStatus = 'sending' | 'sent' | 'read' | 'error';
export interface MessageAttributes {
// the id of the message
// this can have several uses:
id: string;
source: string;
quote?: any;
expireTimer: number;
received_at?: number;
sent_at?: number;
preview?: any;
reaction?: Reaction;
reacts?: ReactionList;
reactsIndex?: number;
body?: string;
expirationStartTimestamp: number;
read_by: Array<string>; // we actually only care about the length of this. values are not used for anything
expires_at?: number;
type: MessageModelType;
group_update?: MessageGroupUpdate;
groupInvitation?: any;
attachments?: any;
conversationId: string;
errors?: any;
flags?: number;
hasAttachments: 1 | 0;
hasFileAttachments: 1 | 0;
hasVisualMediaAttachments: 1 | 0;
expirationTimerUpdate?: {
expireTimer: number;
source: string;
fromSync?: boolean;
};
/**
* 1 means unread, 0 or anything else is read.
*/
unread: number;
group?: any;
/**
* timestamp is the sent_at timestamp, which is the envelope.timestamp
*/
timestamp?: number;
status?: MessageDeliveryStatus;
sent_to: Array<string>;
sent: boolean;
/**
* The serverId is the id on the open group server itself.
* Each message sent to an open group gets a serverId.
* This is not the id for the server, but the id ON the server.
*
* This field is not set for a message not on an opengroup server.
*/
serverId?: number;
/**
* This is the timestamp of that messages as it was saved by the Open group server.
* We rely on this one to order Open Group messages.
* This field is not set for a message not on an opengroup server.
*/
serverTimestamp?: number;
/**
* This field is set to true if the message is for a public server.
* This is useful to make the Badge `Public` Appear on a sent message to a server, even if we did not get
* the response from the server yet that this message was successfully added.
*/
isPublic: boolean;
/**
* sentSync set to true means we just triggered the sync message for this Private Chat message.
* We did not yet get the message sent confirmation, it was just added to the Outgoing MessageQueue
*/
sentSync: boolean;
/**
* synced set to true means that this message was successfully sent by our current device to our other devices.
* It is set to true when the MessageQueue did effectively sent our sync message without errors.
*/
synced: boolean;
sync: boolean;
direction: MessageModelType;
/**
* This is used for when a user screenshots or saves an attachment you sent.
* We display a small message just below the message referenced
*/
dataExtractionNotification?: DataExtractionNotificationMsg;
/**
* For displaying a message to notifying when a request has been accepted.
*/
messageRequestResponse?: MessageRequestResponseMsg;
/**
* This field is used for unsending messages and used in sending unsend message requests.
*/
messageHash?: string;
/**
* This field is used for unsending messages and used in sending unsend message requests.
*/
isDeleted?: boolean;
callNotificationType?: CallNotificationType;
}
export interface DataExtractionNotificationMsg {
type: number; // screenshot or saving event, based on SignalService.DataExtractionNotification.Type
source: string; // the guy who made a screenshot
referencedAttachmentTimestamp: number; // the attachment timestamp he screenshot
}
export interface MessageRequestResponseMsg {
source: string;
isApproved: boolean;
}
export enum MessageDirection {
outgoing = 'outgoing',
incoming = 'incoming',
any = '%',
}
export type PropsForDataExtractionNotification = DataExtractionNotificationMsg & {
name: string;
messageId: string;
receivedAt?: number;
isUnread: boolean;
};
export type PropsForMessageRequestResponse = MessageRequestResponseMsg & {
conversationId?: string;
name?: string;
messageId: string;
receivedAt?: number;
isUnread: boolean;
isApproved?: boolean;
source?: string;
};
export type MessageGroupUpdate = {
left?: Array<string>;
joined?: Array<string>;
kicked?: Array<string>;
name?: string;
};
export interface MessageAttributesOptionals {
id?: string;
source: string;
quote?: any;
expireTimer?: number;
received_at?: number;
sent_at?: number;
preview?: any;
reaction?: Reaction;
reacts?: ReactionList;
reactsIndex?: number;
body?: string;
expirationStartTimestamp?: number;
read_by?: Array<string>; // we actually only care about the length of this. values are not used for anything
expires_at?: number;
type: MessageModelType;
group_update?: MessageGroupUpdate;
groupInvitation?: any;
attachments?: any;
contact?: any;
conversationId: string;
errors?: any;
flags?: number;
hasAttachments?: boolean;
hasFileAttachments?: boolean;
hasVisualMediaAttachments?: boolean;
expirationTimerUpdate?: {
expireTimer: number;
source: string;
fromSync?: boolean;
};
dataExtractionNotification?: {
type: number;
source: string;
referencedAttachmentTimestamp: number;
};
messageRequestResponse?: {
/** 1 means approved, 0 means unapproved. */
isApproved?: number;
};
unread?: number;
group?: any;
timestamp?: number;
status?: MessageDeliveryStatus;
sent_to?: Array<string>;
sent?: boolean;
serverId?: number;
serverTimestamp?: number;
isPublic?: boolean;
sentSync?: boolean;
synced?: boolean;
sync?: boolean;
direction?: MessageModelType;
messageHash?: string;
isDeleted?: boolean;
callNotificationType?: CallNotificationType;
}
/**
* This function mutates optAttributes
* @param optAttributes the entry object attributes to set the defaults to.
*/
export const fillMessageAttributesWithDefaults = (
optAttributes: MessageAttributesOptionals
): MessageAttributes => {
const defaulted = defaultsDeep(optAttributes, {
expireTimer: 0, // disabled
id: uuidv4(),
unread: 0, // if nothing is set, this message is considered read
});
// this is just to cleanup a bit the db. delivered and delivered_to were removed, so everytime we load a message
// we make sure to clean those fields in the json.
// the next commit() will write that to the disk
if (defaulted.delivered) {
delete defaulted.delivered;
}
if (defaulted.delivered_to) {
delete defaulted.delivered_to;
}
return defaulted;
};
/**
* Those props are the one generated from a single Message improved by the one by the app itself.
* Some of the one added comes from the MessageList, some from redux, etc..
*/
export type MessageRenderingProps = PropsForMessageWithConvoProps & {
disableMenu?: boolean;
/** Note: this should be formatted for display */
attachments?: Array<AttachmentTypeWithPath>; // vs Array<PropsForAttachment>;
// whether or not to allow selecting the message
multiSelectMode: boolean;
firstMessageOfSeries: boolean;
lastMessageOfSeries: boolean;
sortedReacts?: SortedReactionList;
};