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.
		
		
		
		
		
			
		
			
				
	
	
		
			269 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			269 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			TypeScript
		
	
| import { defaultsDeep } from 'lodash';
 | |
| import { v4 as uuidv4 } from 'uuid';
 | |
| import {
 | |
|   CallNotificationType,
 | |
|   PropsForExpiringMessage,
 | |
|   PropsForMessageWithConvoProps,
 | |
| } from '../state/ducks/conversations';
 | |
| import { AttachmentTypeWithPath } from '../types/Attachment';
 | |
| import { Reaction, ReactionList, SortedReactionList } from '../types/Reaction';
 | |
| import { DisappearingMessageType } from '../util/expiringMessages';
 | |
| 
 | |
| 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;
 | |
|   received_at?: number;
 | |
|   sent_at?: number;
 | |
|   preview?: any;
 | |
|   reaction?: Reaction;
 | |
|   reacts?: ReactionList;
 | |
|   reactsIndex?: number;
 | |
|   body?: string;
 | |
|   // NOTE this is used for the logic
 | |
|   expirationType?: DisappearingMessageType;
 | |
|   expireTimer: number;
 | |
|   expirationStartTimestamp: number;
 | |
|   expires_at?: number;
 | |
|   // NOTE this is used for conversation setting
 | |
|   expirationTimerUpdate?: {
 | |
|     expirationType: DisappearingMessageType;
 | |
|     expireTimer: number;
 | |
|     lastDisappearingMessageChangeTimestamp: number;
 | |
|     source: string;
 | |
|     fromSync?: boolean;
 | |
|   };
 | |
|   read_by: Array<string>; // we actually only care about the length of this. values are not used for anything
 | |
|   type: MessageModelType;
 | |
|   group_update?: MessageGroupUpdate;
 | |
|   groupInvitation?: any;
 | |
|   attachments?: any;
 | |
|   conversationId: string;
 | |
|   errors?: any;
 | |
|   flags?: number;
 | |
|   hasAttachments: 1 | 0;
 | |
|   hasFileAttachments: 1 | 0;
 | |
|   hasVisualMediaAttachments: 1 | 0;
 | |
|   /**
 | |
|    * 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 interface PropsForDataExtractionNotification
 | |
|   extends DataExtractionNotificationMsg,
 | |
|     PropsForExpiringMessage {
 | |
|   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;
 | |
|   received_at?: number;
 | |
|   sent_at?: number;
 | |
|   preview?: any;
 | |
|   reaction?: Reaction;
 | |
|   reacts?: ReactionList;
 | |
|   reactsIndex?: number;
 | |
|   body?: string;
 | |
|   expirationType?: DisappearingMessageType;
 | |
|   expireTimer?: number;
 | |
|   expirationStartTimestamp?: number;
 | |
|   expires_at?: number;
 | |
|   expirationTimerUpdate?: {
 | |
|     expirationType: DisappearingMessageType;
 | |
|     expireTimer: number;
 | |
|     lastDisappearingMessageChangeTimestamp: number;
 | |
|     source: string;
 | |
|     fromSync?: boolean;
 | |
|   };
 | |
|   read_by?: Array<string>; // we actually only care about the length of this. values are not used for anything
 | |
|   type: MessageModelType;
 | |
|   group_update?: MessageGroupUpdate;
 | |
|   groupInvitation?: any;
 | |
|   attachments?: any;
 | |
|   contact?: any;
 | |
|   conversationId: string;
 | |
|   errors?: any;
 | |
|   flags?: number;
 | |
|   hasAttachments?: boolean;
 | |
|   hasFileAttachments?: boolean;
 | |
|   hasVisualMediaAttachments?: 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;
 | |
| };
 |