Send edited messages support
Co-authored-by: Fedor Indutnyy <indutny@signal.org>
This commit is contained in:
@@ -27,7 +27,8 @@ import { ThemeType } from './Util';
|
||||
import * as GoogleChrome from '../util/GoogleChrome';
|
||||
import { ReadStatus } from '../messages/MessageReadStatus';
|
||||
import type { MessageStatusType } from '../components/conversation/Message';
|
||||
import { softAssert } from '../util/assert';
|
||||
import { strictAssert } from '../util/assert';
|
||||
import type { SignalService as Proto } from '../protobuf';
|
||||
|
||||
const MAX_WIDTH = 300;
|
||||
const MAX_HEIGHT = MAX_WIDTH * 1.5;
|
||||
@@ -84,6 +85,16 @@ export type AttachmentType = {
|
||||
key?: string;
|
||||
};
|
||||
|
||||
export type UploadedAttachmentType = Proto.IAttachmentPointer &
|
||||
Readonly<{
|
||||
// Required fields
|
||||
cdnId: Long;
|
||||
key: Uint8Array;
|
||||
size: number;
|
||||
digest: Uint8Array;
|
||||
contentType: string;
|
||||
}>;
|
||||
|
||||
export type AttachmentWithHydratedData = AttachmentType & {
|
||||
data: Uint8Array;
|
||||
};
|
||||
@@ -1006,6 +1017,6 @@ export const canBeDownloaded = (
|
||||
};
|
||||
|
||||
export function getAttachmentSignature(attachment: AttachmentType): string {
|
||||
softAssert(attachment.digest, 'attachment missing digest');
|
||||
return attachment.digest || String(attachment.blurHash);
|
||||
strictAssert(attachment.digest, 'attachment missing digest');
|
||||
return attachment.digest;
|
||||
}
|
||||
|
@@ -11,17 +11,22 @@ import {
|
||||
format as formatPhoneNumber,
|
||||
parse as parsePhoneNumber,
|
||||
} from './PhoneNumber';
|
||||
import type { AttachmentType, migrateDataToFileSystem } from './Attachment';
|
||||
import type {
|
||||
AttachmentType,
|
||||
AttachmentWithHydratedData,
|
||||
UploadedAttachmentType,
|
||||
migrateDataToFileSystem,
|
||||
} from './Attachment';
|
||||
import { toLogFormat } from './errors';
|
||||
import type { LoggerType } from './Logging';
|
||||
import type { UUIDStringType } from './UUID';
|
||||
|
||||
export type EmbeddedContactType = {
|
||||
type GenericEmbeddedContactType<AvatarType> = {
|
||||
name?: Name;
|
||||
number?: Array<Phone>;
|
||||
email?: Array<Email>;
|
||||
address?: Array<PostalAddress>;
|
||||
avatar?: Avatar;
|
||||
avatar?: AvatarType;
|
||||
organization?: string;
|
||||
|
||||
// Populated by selector
|
||||
@@ -29,6 +34,12 @@ export type EmbeddedContactType = {
|
||||
uuid?: UUIDStringType;
|
||||
};
|
||||
|
||||
export type EmbeddedContactType = GenericEmbeddedContactType<Avatar>;
|
||||
export type EmbeddedContactWithHydratedAvatar =
|
||||
GenericEmbeddedContactType<AvatarWithHydratedData>;
|
||||
export type EmbeddedContactWithUploadedAvatar =
|
||||
GenericEmbeddedContactType<UploadedAvatar>;
|
||||
|
||||
type Name = {
|
||||
givenName?: string;
|
||||
familyName?: string;
|
||||
@@ -75,11 +86,15 @@ export type PostalAddress = {
|
||||
country?: string;
|
||||
};
|
||||
|
||||
export type Avatar = {
|
||||
avatar: AttachmentType;
|
||||
type GenericAvatar<Attachment> = {
|
||||
avatar: Attachment;
|
||||
isProfile: boolean;
|
||||
};
|
||||
|
||||
export type Avatar = GenericAvatar<AttachmentType>;
|
||||
export type AvatarWithHydratedData = GenericAvatar<AttachmentWithHydratedData>;
|
||||
export type UploadedAvatar = GenericAvatar<UploadedAttachmentType>;
|
||||
|
||||
const DEFAULT_PHONE_TYPE = Proto.DataMessage.Contact.Phone.Type.HOME;
|
||||
const DEFAULT_EMAIL_TYPE = Proto.DataMessage.Contact.Email.Type.HOME;
|
||||
const DEFAULT_ADDRESS_TYPE = Proto.DataMessage.Contact.PostalAddress.Type.HOME;
|
||||
|
13
ts/types/ErrorWithToast.ts
Normal file
13
ts/types/ErrorWithToast.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2023 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { ToastType } from './Toast';
|
||||
|
||||
export class ErrorWithToast extends Error {
|
||||
public toastType: ToastType;
|
||||
|
||||
constructor(message: string, toastType: ToastType) {
|
||||
super(message);
|
||||
this.toastType = toastType;
|
||||
}
|
||||
}
|
@@ -8,11 +8,9 @@ import LinkifyIt from 'linkify-it';
|
||||
import { maybeParseUrl } from '../util/url';
|
||||
import { replaceEmojiWithSpaces } from '../util/emoji';
|
||||
|
||||
import type { AttachmentType } from './Attachment';
|
||||
import type { AttachmentWithHydratedData } from './Attachment';
|
||||
|
||||
export type LinkPreviewImage = AttachmentType & {
|
||||
data: Uint8Array;
|
||||
};
|
||||
export type LinkPreviewImage = AttachmentWithHydratedData;
|
||||
|
||||
export type LinkPreviewResult = {
|
||||
title: string | null;
|
||||
|
@@ -20,13 +20,19 @@ import { initializeAttachmentMetadata } from './message/initializeAttachmentMeta
|
||||
|
||||
import type * as MIME from './MIME';
|
||||
import type { LoggerType } from './Logging';
|
||||
import type { EmbeddedContactType } from './EmbeddedContact';
|
||||
import type {
|
||||
EmbeddedContactType,
|
||||
EmbeddedContactWithHydratedAvatar,
|
||||
} from './EmbeddedContact';
|
||||
|
||||
import type {
|
||||
MessageAttributesType,
|
||||
QuotedMessageType,
|
||||
} from '../model-types.d';
|
||||
import type { LinkPreviewType } from './message/LinkPreviews';
|
||||
import type {
|
||||
LinkPreviewType,
|
||||
LinkPreviewWithHydratedData,
|
||||
} from './message/LinkPreviews';
|
||||
import type { StickerType, StickerWithHydratedData } from './Stickers';
|
||||
|
||||
export { hasExpiration } from './Message';
|
||||
@@ -714,28 +720,33 @@ export const loadContactData = (
|
||||
loadAttachmentData: LoadAttachmentType
|
||||
): ((
|
||||
contact: Array<EmbeddedContactType> | undefined
|
||||
) => Promise<Array<EmbeddedContactType> | undefined>) => {
|
||||
) => Promise<Array<EmbeddedContactWithHydratedAvatar> | undefined>) => {
|
||||
if (!isFunction(loadAttachmentData)) {
|
||||
throw new TypeError('loadContactData: loadAttachmentData is required');
|
||||
}
|
||||
|
||||
return async (
|
||||
contact: Array<EmbeddedContactType> | undefined
|
||||
): Promise<Array<EmbeddedContactType> | undefined> => {
|
||||
): Promise<Array<EmbeddedContactWithHydratedAvatar> | undefined> => {
|
||||
if (!contact) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return Promise.all(
|
||||
contact.map(
|
||||
async (item: EmbeddedContactType): Promise<EmbeddedContactType> => {
|
||||
async (
|
||||
item: EmbeddedContactType
|
||||
): Promise<EmbeddedContactWithHydratedAvatar> => {
|
||||
if (
|
||||
!item ||
|
||||
!item.avatar ||
|
||||
!item.avatar.avatar ||
|
||||
!item.avatar.avatar.path
|
||||
) {
|
||||
return item;
|
||||
return {
|
||||
...item,
|
||||
avatar: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -758,7 +769,7 @@ export const loadPreviewData = (
|
||||
loadAttachmentData: LoadAttachmentType
|
||||
): ((
|
||||
preview: Array<LinkPreviewType> | undefined
|
||||
) => Promise<Array<LinkPreviewType>>) => {
|
||||
) => Promise<Array<LinkPreviewWithHydratedData>>) => {
|
||||
if (!isFunction(loadAttachmentData)) {
|
||||
throw new TypeError('loadPreviewData: loadAttachmentData is required');
|
||||
}
|
||||
@@ -769,16 +780,22 @@ export const loadPreviewData = (
|
||||
}
|
||||
|
||||
return Promise.all(
|
||||
preview.map(async item => {
|
||||
if (!item.image) {
|
||||
return item;
|
||||
}
|
||||
preview.map(
|
||||
async (item: LinkPreviewType): Promise<LinkPreviewWithHydratedData> => {
|
||||
if (!item.image) {
|
||||
return {
|
||||
...item,
|
||||
// Pacify typescript
|
||||
image: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...item,
|
||||
image: await loadAttachmentData(item.image),
|
||||
};
|
||||
})
|
||||
return {
|
||||
...item,
|
||||
image: await loadAttachmentData(item.image),
|
||||
};
|
||||
}
|
||||
)
|
||||
);
|
||||
};
|
||||
};
|
||||
|
@@ -7,6 +7,7 @@ export enum ToastType {
|
||||
AlreadyRequestedToJoin = 'AlreadyRequestedToJoin',
|
||||
Blocked = 'Blocked',
|
||||
BlockedGroup = 'BlockedGroup',
|
||||
CannotEditMessage = 'CannotEditMessage',
|
||||
CannotForwardEmptyMessage = 'CannotForwardEmptyMessage',
|
||||
CannotMixMultiAndNonMultiAttachments = 'CannotMixMultiAndNonMultiAttachments',
|
||||
CannotOpenGiftBadgeIncoming = 'CannotOpenGiftBadgeIncoming',
|
||||
@@ -54,6 +55,7 @@ export type AnyToast =
|
||||
| { toastType: ToastType.AlreadyRequestedToJoin }
|
||||
| { toastType: ToastType.Blocked }
|
||||
| { toastType: ToastType.BlockedGroup }
|
||||
| { toastType: ToastType.CannotEditMessage }
|
||||
| { toastType: ToastType.CannotForwardEmptyMessage }
|
||||
| { toastType: ToastType.CannotMixMultiAndNonMultiAttachments }
|
||||
| { toastType: ToastType.CannotOpenGiftBadgeIncoming }
|
||||
|
@@ -1,14 +1,18 @@
|
||||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { AttachmentType } from '../Attachment';
|
||||
import type { AttachmentType, AttachmentWithHydratedData } from '../Attachment';
|
||||
|
||||
export type LinkPreviewType = {
|
||||
type GenericLinkPreviewType<Image> = {
|
||||
title?: string;
|
||||
description?: string;
|
||||
domain?: string;
|
||||
url: string;
|
||||
isStickerPack?: boolean;
|
||||
image?: Readonly<AttachmentType>;
|
||||
image?: Readonly<Image>;
|
||||
date?: number;
|
||||
};
|
||||
|
||||
export type LinkPreviewType = GenericLinkPreviewType<AttachmentType>;
|
||||
export type LinkPreviewWithHydratedData =
|
||||
GenericLinkPreviewType<AttachmentWithHydratedData>;
|
||||
|
Reference in New Issue
Block a user