Send related emoji along with Sticker, fix SendMessage types
This commit is contained in:
parent
3c91dce993
commit
bd380086a4
|
@ -168,14 +168,16 @@ export const createDoesExist = (
|
|||
|
||||
export const copyIntoAttachmentsDirectory = (
|
||||
root: string
|
||||
): ((sourcePath: string) => Promise<string>) => {
|
||||
): ((sourcePath: string) => Promise<{ path: string; size: number }>) => {
|
||||
if (!isString(root)) {
|
||||
throw new TypeError("'root' must be a path");
|
||||
}
|
||||
|
||||
const userDataPath = getApp().getPath('userData');
|
||||
|
||||
return async (sourcePath: string): Promise<string> => {
|
||||
return async (
|
||||
sourcePath: string
|
||||
): Promise<{ path: string; size: number }> => {
|
||||
if (!isString(sourcePath)) {
|
||||
throw new TypeError('sourcePath must be a string');
|
||||
}
|
||||
|
@ -196,7 +198,12 @@ export const copyIntoAttachmentsDirectory = (
|
|||
|
||||
await fse.ensureFile(normalized);
|
||||
await fse.copy(sourcePath, normalized);
|
||||
return relativePath;
|
||||
const { size } = await fse.stat(normalized);
|
||||
|
||||
return {
|
||||
path: relativePath,
|
||||
size,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -220,6 +220,7 @@ message DataMessage {
|
|||
optional bytes packKey = 2;
|
||||
optional uint32 stickerId = 3;
|
||||
optional AttachmentPointer data = 4;
|
||||
optional string emoji = 5;
|
||||
}
|
||||
|
||||
message Reaction {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2018-2020 Signal Messenger, LLC
|
||||
// Copyright 2018-2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
const fs = require('fs');
|
||||
|
@ -222,14 +222,14 @@ describe('Attachments', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('returns a function that copies the source path into the attachments directory', async function thisNeeded() {
|
||||
it('returns a function that copies the source path into the attachments directory and returns its path and size', async function thisNeeded() {
|
||||
const attachmentsPath = await this.getFakeAttachmentsDirectory();
|
||||
const someOtherPath = path.join(app.getPath('userData'), 'somethingElse');
|
||||
await fse.outputFile(someOtherPath, 'hello world');
|
||||
this.filesToRemove.push(someOtherPath);
|
||||
|
||||
const copier = Attachments.copyIntoAttachmentsDirectory(attachmentsPath);
|
||||
const relativePath = await copier(someOtherPath);
|
||||
const { path: relativePath, size } = await copier(someOtherPath);
|
||||
|
||||
const absolutePath = path.join(attachmentsPath, relativePath);
|
||||
assert.notEqual(someOtherPath, absolutePath);
|
||||
|
@ -237,6 +237,8 @@ describe('Attachments', () => {
|
|||
await fs.promises.readFile(absolutePath, 'utf8'),
|
||||
'hello world'
|
||||
);
|
||||
|
||||
assert.strictEqual(size, 'hello world'.length);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -12,17 +12,19 @@ import { AUDIO_MP3, IMAGE_JPEG, VIDEO_MP4 } from '../types/MIME';
|
|||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
import { fakeAttachment } from '../test-both/helpers/fakeAttachment';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
const stories = storiesOf('Components/Caption Editor', module);
|
||||
|
||||
const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: '',
|
||||
url: '',
|
||||
...overrideProps.attachment,
|
||||
},
|
||||
}),
|
||||
caption: text('caption', overrideProps.caption || ''),
|
||||
close: action('close'),
|
||||
i18n,
|
||||
|
@ -50,11 +52,11 @@ stories.add('Image with Caption', () => {
|
|||
|
||||
stories.add('Video', () => {
|
||||
const props = createProps({
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
contentType: VIDEO_MP4,
|
||||
fileName: 'pixabay-Soap-Bubble-7141.mp4',
|
||||
url: '/fixtures/pixabay-Soap-Bubble-7141.mp4',
|
||||
},
|
||||
}),
|
||||
url: '/fixtures/pixabay-Soap-Bubble-7141.mp4',
|
||||
});
|
||||
|
||||
|
@ -63,11 +65,11 @@ stories.add('Video', () => {
|
|||
|
||||
stories.add('Video with Caption', () => {
|
||||
const props = createProps({
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
contentType: VIDEO_MP4,
|
||||
fileName: 'pixabay-Soap-Bubble-7141.mp4',
|
||||
url: '/fixtures/pixabay-Soap-Bubble-7141.mp4',
|
||||
},
|
||||
}),
|
||||
caption:
|
||||
'This is the user-provided caption. We show it overlaid on the image. If it is really long, then it wraps, but it does not get too close to the edges of the image.',
|
||||
url: '/fixtures/pixabay-Soap-Bubble-7141.mp4',
|
||||
|
@ -78,11 +80,11 @@ stories.add('Video with Caption', () => {
|
|||
|
||||
stories.add('Unsupported Attachment Type', () => {
|
||||
const props = createProps({
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
contentType: AUDIO_MP3,
|
||||
fileName: 'incompetech-com-Agnus-Dei-X.mp3',
|
||||
url: '/fixtures/incompetech-com-Agnus-Dei-X.mp3',
|
||||
},
|
||||
}),
|
||||
url: '/fixtures/incompetech-com-Agnus-Dei-X.mp3',
|
||||
});
|
||||
|
||||
|
|
|
@ -12,6 +12,9 @@ import { CompositionArea, Props } from './CompositionArea';
|
|||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
import { fakeAttachment } from '../test-both/helpers/fakeAttachment';
|
||||
import { landscapeGreenUrl } from '../storybook/Fixtures';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
const story = storiesOf('Components/CompositionArea', module);
|
||||
|
@ -154,9 +157,10 @@ story.add('SMS-only', () => {
|
|||
story.add('Attachments', () => {
|
||||
const props = createProps({
|
||||
draftAttachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
},
|
||||
url: landscapeGreenUrl,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ const createAttachment = (
|
|||
fileName: text('attachment fileName', props.fileName || ''),
|
||||
screenshot: props.screenshot,
|
||||
url: text('attachment url', props.url || ''),
|
||||
size: 3433,
|
||||
});
|
||||
|
||||
const story = storiesOf('Components/ForwardMessageModal', module);
|
||||
|
|
|
@ -19,6 +19,8 @@ import {
|
|||
stringToMIMEType,
|
||||
} from '../types/MIME';
|
||||
|
||||
import { fakeAttachment } from '../test-both/helpers/fakeAttachment';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
const story = storiesOf('Components/Lightbox', module);
|
||||
|
@ -29,12 +31,12 @@ function createMediaItem(
|
|||
overrideProps: OverridePropsMediaItemType
|
||||
): MediaItemType {
|
||||
return {
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
caption: overrideProps.caption || '',
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: overrideProps.objectURL,
|
||||
url: overrideProps.objectURL,
|
||||
},
|
||||
}),
|
||||
contentType: IMAGE_JPEG,
|
||||
index: 0,
|
||||
message: {
|
||||
|
@ -63,13 +65,13 @@ story.add('Multimedia', () => {
|
|||
const props = createProps({
|
||||
media: [
|
||||
{
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
caption:
|
||||
'Still from The Lighthouse, starring Robert Pattinson and Willem Defoe.',
|
||||
},
|
||||
}),
|
||||
contentType: IMAGE_JPEG,
|
||||
index: 0,
|
||||
message: {
|
||||
|
@ -83,11 +85,11 @@ story.add('Multimedia', () => {
|
|||
objectURL: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
},
|
||||
{
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
contentType: VIDEO_MP4,
|
||||
fileName: 'pixabay-Soap-Bubble-7141.mp4',
|
||||
url: '/fixtures/pixabay-Soap-Bubble-7141.mp4',
|
||||
},
|
||||
}),
|
||||
contentType: VIDEO_MP4,
|
||||
index: 1,
|
||||
message: {
|
||||
|
@ -122,11 +124,11 @@ story.add('Missing Media', () => {
|
|||
const props = createProps({
|
||||
media: [
|
||||
{
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
},
|
||||
}),
|
||||
contentType: IMAGE_JPEG,
|
||||
index: 0,
|
||||
message: {
|
||||
|
|
|
@ -17,6 +17,8 @@ import {
|
|||
import { setupI18n } from '../../util/setupI18n';
|
||||
import enMessages from '../../../_locales/en/messages.json';
|
||||
|
||||
import { fakeAttachment } from '../../test-both/helpers/fakeAttachment';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
const story = storiesOf('Components/Conversation/AttachmentList', module);
|
||||
|
@ -33,11 +35,11 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
|||
story.add('One File', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
return <AttachmentList {...props} />;
|
||||
|
@ -46,12 +48,12 @@ story.add('One File', () => {
|
|||
story.add('Multiple Visual Attachments', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: VIDEO_MP4,
|
||||
fileName: 'pixabay-Soap-Bubble-7141.mp4',
|
||||
url: '/fixtures/pixabay-Soap-Bubble-7141.mp4',
|
||||
|
@ -62,12 +64,12 @@ story.add('Multiple Visual Attachments', () => {
|
|||
contentType: IMAGE_JPEG,
|
||||
path: 'originalpath',
|
||||
},
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_GIF,
|
||||
fileName: 'giphy-GVNv0UpeYm17e',
|
||||
url: '/fixtures/giphy-GVNvOUpeYmI7e.gif',
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -77,22 +79,22 @@ story.add('Multiple Visual Attachments', () => {
|
|||
story.add('Multiple with Non-Visual Types', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: stringToMIMEType('text/plain'),
|
||||
fileName: 'lorem-ipsum.txt',
|
||||
url: '/fixtures/lorem-ipsum.txt',
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: AUDIO_MP3,
|
||||
fileName: 'incompetech-com-Agnus-Dei-X.mp3',
|
||||
url: '/fixtures/incompetech-com-Agnus-Dei-X.mp3',
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: VIDEO_MP4,
|
||||
fileName: 'pixabay-Soap-Bubble-7141.mp4',
|
||||
url: '/fixtures/pixabay-Soap-Bubble-7141.mp4',
|
||||
|
@ -103,12 +105,12 @@ story.add('Multiple with Non-Visual Types', () => {
|
|||
contentType: IMAGE_JPEG,
|
||||
path: 'originalpath',
|
||||
},
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_GIF,
|
||||
fileName: 'giphy-GVNv0UpeYm17e',
|
||||
url: '/fixtures/giphy-GVNvOUpeYmI7e.gif',
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ import { setupI18n } from '../../util/setupI18n';
|
|||
import enMessages from '../../../_locales/en/messages.json';
|
||||
import { IMAGE_GIF } from '../../types/MIME';
|
||||
|
||||
import { fakeAttachment } from '../../test-both/helpers/fakeAttachment';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
const story = storiesOf('Components/Conversation/ContactDetail', module);
|
||||
|
@ -72,10 +74,10 @@ const fullContact = {
|
|||
},
|
||||
],
|
||||
avatar: {
|
||||
avatar: {
|
||||
avatar: fakeAttachment({
|
||||
path: '/fixtures/giphy-GVNvOUpeYmI7e.gif',
|
||||
contentType: IMAGE_GIF,
|
||||
},
|
||||
}),
|
||||
isProfile: true,
|
||||
},
|
||||
email: [
|
||||
|
@ -209,10 +211,10 @@ story.add('Loading Avatar', () => {
|
|||
const props = createProps({
|
||||
contact: {
|
||||
avatar: {
|
||||
avatar: {
|
||||
avatar: fakeAttachment({
|
||||
contentType: IMAGE_GIF,
|
||||
pending: true,
|
||||
},
|
||||
}),
|
||||
isProfile: true,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -13,6 +13,8 @@ import enMessages from '../../../_locales/en/messages.json';
|
|||
import { ContactFormType } from '../../types/EmbeddedContact';
|
||||
import { IMAGE_GIF } from '../../types/MIME';
|
||||
|
||||
import { fakeAttachment } from '../../test-both/helpers/fakeAttachment';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
const story = storiesOf('Components/Conversation/EmbeddedContact', module);
|
||||
|
@ -35,10 +37,10 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
|||
|
||||
const fullContact = {
|
||||
avatar: {
|
||||
avatar: {
|
||||
avatar: fakeAttachment({
|
||||
path: '/fixtures/giphy-GVNvOUpeYmI7e.gif',
|
||||
contentType: IMAGE_GIF,
|
||||
},
|
||||
}),
|
||||
isProfile: true,
|
||||
},
|
||||
email: [
|
||||
|
@ -134,10 +136,10 @@ story.add('Loading Avatar', () => {
|
|||
displayName: 'Jerry Jordan',
|
||||
},
|
||||
avatar: {
|
||||
avatar: {
|
||||
avatar: fakeAttachment({
|
||||
pending: true,
|
||||
contentType: IMAGE_GIF,
|
||||
},
|
||||
}),
|
||||
isProfile: true,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -14,17 +14,21 @@ import { ThemeType } from '../../types/Util';
|
|||
import { setupI18n } from '../../util/setupI18n';
|
||||
import enMessages from '../../../_locales/en/messages.json';
|
||||
|
||||
import { fakeAttachment } from '../../test-both/helpers/fakeAttachment';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
const story = storiesOf('Components/Conversation/Image', module);
|
||||
|
||||
const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||
alt: text('alt', overrideProps.alt || ''),
|
||||
attachment: overrideProps.attachment || {
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
url: pngUrl,
|
||||
},
|
||||
attachment:
|
||||
overrideProps.attachment ||
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
url: pngUrl,
|
||||
}),
|
||||
blurHash: text('blurHash', overrideProps.blurHash || ''),
|
||||
bottomOverlay: boolean('bottomOverlay', overrideProps.bottomOverlay || false),
|
||||
closeButton: boolean('closeButton', overrideProps.closeButton || false),
|
||||
|
@ -99,11 +103,11 @@ story.add('Close Button', () => {
|
|||
|
||||
story.add('No Border or Background', () => {
|
||||
const props = createProps({
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
url: pngUrl,
|
||||
},
|
||||
}),
|
||||
noBackground: true,
|
||||
noBorder: true,
|
||||
url: pngUrl,
|
||||
|
|
|
@ -19,6 +19,7 @@ import {
|
|||
import { setupI18n } from '../../util/setupI18n';
|
||||
import enMessages from '../../../_locales/en/messages.json';
|
||||
import { pngUrl, squareStickerUrl } from '../../storybook/Fixtures';
|
||||
import { fakeAttachment } from '../../test-both/helpers/fakeAttachment';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
|
@ -26,13 +27,13 @@ const story = storiesOf('Components/Conversation/ImageGrid', module);
|
|||
|
||||
const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||
attachments: overrideProps.attachments || [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
height: 1200,
|
||||
url: pngUrl,
|
||||
width: 800,
|
||||
},
|
||||
}),
|
||||
],
|
||||
bottomOverlay: boolean('bottomOverlay', overrideProps.bottomOverlay || false),
|
||||
i18n,
|
||||
|
@ -60,20 +61,20 @@ story.add('One Image', () => {
|
|||
story.add('Two Images', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
height: 1200,
|
||||
url: pngUrl,
|
||||
width: 800,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
height: 1680,
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
width: 3000,
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -83,27 +84,27 @@ story.add('Two Images', () => {
|
|||
story.add('Three Images', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
height: 1200,
|
||||
url: pngUrl,
|
||||
width: 800,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
height: 1680,
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
width: 3000,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
height: 1200,
|
||||
url: pngUrl,
|
||||
width: 800,
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -113,34 +114,34 @@ story.add('Three Images', () => {
|
|||
story.add('Four Images', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
height: 1200,
|
||||
url: pngUrl,
|
||||
width: 800,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
height: 1680,
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
width: 3000,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
height: 1200,
|
||||
url: pngUrl,
|
||||
width: 800,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
height: 1680,
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
width: 3000,
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -150,41 +151,41 @@ story.add('Four Images', () => {
|
|||
story.add('Five Images', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
height: 1200,
|
||||
url: pngUrl,
|
||||
width: 800,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
height: 1680,
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
width: 3000,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
height: 1200,
|
||||
url: pngUrl,
|
||||
width: 800,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
height: 1680,
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
width: 3000,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
height: 1200,
|
||||
url: pngUrl,
|
||||
width: 800,
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -194,55 +195,55 @@ story.add('Five Images', () => {
|
|||
story.add('6+ Images', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
height: 1200,
|
||||
url: pngUrl,
|
||||
width: 800,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
height: 1680,
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
width: 3000,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
height: 1200,
|
||||
url: pngUrl,
|
||||
width: 800,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
height: 1680,
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
width: 3000,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
height: 1200,
|
||||
url: pngUrl,
|
||||
width: 800,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
height: 1200,
|
||||
url: pngUrl,
|
||||
width: 800,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
height: 1200,
|
||||
url: pngUrl,
|
||||
width: 800,
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -251,7 +252,7 @@ story.add('6+ Images', () => {
|
|||
story.add('Mixed Content Types', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: VIDEO_MP4,
|
||||
fileName: 'pixabay-Soap-Bubble-7141.mp4',
|
||||
height: 112,
|
||||
|
@ -264,24 +265,24 @@ story.add('Mixed Content Types', () => {
|
|||
},
|
||||
url: '/fixtures/pixabay-Soap-Bubble-7141.mp4',
|
||||
width: 112,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'sax.png',
|
||||
height: 1200,
|
||||
url: pngUrl,
|
||||
width: 800,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: stringToMIMEType('text/plain'),
|
||||
fileName: 'lorem-ipsum.txt',
|
||||
url: '/fixtures/lorem-ipsum.txt',
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
contentType: AUDIO_MP3,
|
||||
fileName: 'incompetech-com-Agnus-Dei-X.mp3',
|
||||
url: '/fixtures/incompetech-com-Agnus-Dei-X.mp3',
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -291,13 +292,13 @@ story.add('Mixed Content Types', () => {
|
|||
story.add('Sticker', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: IMAGE_WEBP,
|
||||
fileName: 'sticker.webp',
|
||||
height: 512,
|
||||
url: squareStickerUrl,
|
||||
width: 512,
|
||||
},
|
||||
}),
|
||||
],
|
||||
isSticker: true,
|
||||
stickerSize: 128,
|
||||
|
|
|
@ -28,6 +28,8 @@ import enMessages from '../../../_locales/en/messages.json';
|
|||
import { pngUrl } from '../../storybook/Fixtures';
|
||||
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
|
||||
|
||||
import { fakeAttachment } from '../../test-both/helpers/fakeAttachment';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
function getJoyReaction() {
|
||||
|
@ -444,13 +446,13 @@ story.add('Avatar in Group', () => {
|
|||
story.add('Sticker', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
url: '/fixtures/512x515-thumbs-up-lincoln.webp',
|
||||
fileName: '512x515-thumbs-up-lincoln.webp',
|
||||
contentType: IMAGE_WEBP,
|
||||
width: 128,
|
||||
height: 128,
|
||||
},
|
||||
}),
|
||||
],
|
||||
isSticker: true,
|
||||
status: 'sent',
|
||||
|
@ -524,13 +526,13 @@ story.add('Link Preview', () => {
|
|||
previews: [
|
||||
{
|
||||
domain: 'signal.org',
|
||||
image: {
|
||||
image: fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'the-sax.png',
|
||||
height: 240,
|
||||
url: pngUrl,
|
||||
width: 320,
|
||||
},
|
||||
}),
|
||||
isStickerPack: false,
|
||||
title: 'Signal',
|
||||
description:
|
||||
|
@ -551,13 +553,13 @@ story.add('Link Preview with Small Image', () => {
|
|||
previews: [
|
||||
{
|
||||
domain: 'signal.org',
|
||||
image: {
|
||||
image: fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'the-sax.png',
|
||||
height: 50,
|
||||
url: pngUrl,
|
||||
width: 50,
|
||||
},
|
||||
}),
|
||||
isStickerPack: false,
|
||||
title: 'Signal',
|
||||
description:
|
||||
|
@ -639,13 +641,13 @@ story.add('Link Preview with small image, long description', () => {
|
|||
previews: [
|
||||
{
|
||||
domain: 'signal.org',
|
||||
image: {
|
||||
image: fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'the-sax.png',
|
||||
height: 50,
|
||||
url: pngUrl,
|
||||
width: 50,
|
||||
},
|
||||
}),
|
||||
isStickerPack: false,
|
||||
title: 'Signal',
|
||||
description: Array(10)
|
||||
|
@ -669,13 +671,13 @@ story.add('Link Preview with no date', () => {
|
|||
previews: [
|
||||
{
|
||||
domain: 'signal.org',
|
||||
image: {
|
||||
image: fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'the-sax.png',
|
||||
height: 240,
|
||||
url: pngUrl,
|
||||
width: 320,
|
||||
},
|
||||
}),
|
||||
isStickerPack: false,
|
||||
title: 'Signal',
|
||||
description:
|
||||
|
@ -695,13 +697,13 @@ story.add('Link Preview with too new a date', () => {
|
|||
previews: [
|
||||
{
|
||||
domain: 'signal.org',
|
||||
image: {
|
||||
image: fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'the-sax.png',
|
||||
height: 240,
|
||||
url: pngUrl,
|
||||
width: 320,
|
||||
},
|
||||
}),
|
||||
isStickerPack: false,
|
||||
title: 'Signal',
|
||||
description:
|
||||
|
@ -720,13 +722,13 @@ story.add('Link Preview with too new a date', () => {
|
|||
story.add('Image', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
contentType: IMAGE_JPEG,
|
||||
width: 128,
|
||||
height: 128,
|
||||
},
|
||||
}),
|
||||
],
|
||||
status: 'sent',
|
||||
});
|
||||
|
@ -738,41 +740,41 @@ for (let i = 2; i <= 5; i += 1) {
|
|||
story.add(`Multiple Images x${i}`, () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
contentType: IMAGE_JPEG,
|
||||
width: 128,
|
||||
height: 128,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
contentType: IMAGE_JPEG,
|
||||
width: 128,
|
||||
height: 128,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
contentType: IMAGE_JPEG,
|
||||
width: 128,
|
||||
height: 128,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
contentType: IMAGE_JPEG,
|
||||
width: 128,
|
||||
height: 128,
|
||||
},
|
||||
{
|
||||
}),
|
||||
fakeAttachment({
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
contentType: IMAGE_JPEG,
|
||||
width: 128,
|
||||
height: 128,
|
||||
},
|
||||
}),
|
||||
].slice(0, i),
|
||||
status: 'sent',
|
||||
});
|
||||
|
@ -784,13 +786,13 @@ for (let i = 2; i <= 5; i += 1) {
|
|||
story.add('Image with Caption', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
contentType: IMAGE_JPEG,
|
||||
width: 128,
|
||||
height: 128,
|
||||
},
|
||||
}),
|
||||
],
|
||||
status: 'sent',
|
||||
text: 'This is my home.',
|
||||
|
@ -802,14 +804,14 @@ story.add('Image with Caption', () => {
|
|||
story.add('GIF', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: VIDEO_MP4,
|
||||
flags: SignalService.AttachmentPointer.Flags.GIF,
|
||||
fileName: 'cat-gif.mp4',
|
||||
url: '/fixtures/cat-gif.mp4',
|
||||
width: 400,
|
||||
height: 332,
|
||||
},
|
||||
}),
|
||||
],
|
||||
status: 'sent',
|
||||
});
|
||||
|
@ -820,14 +822,14 @@ story.add('GIF', () => {
|
|||
story.add('GIF in a group', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: VIDEO_MP4,
|
||||
flags: SignalService.AttachmentPointer.Flags.GIF,
|
||||
fileName: 'cat-gif.mp4',
|
||||
url: '/fixtures/cat-gif.mp4',
|
||||
width: 400,
|
||||
height: 332,
|
||||
},
|
||||
}),
|
||||
],
|
||||
conversationType: 'group',
|
||||
status: 'sent',
|
||||
|
@ -839,7 +841,7 @@ story.add('GIF in a group', () => {
|
|||
story.add('Not Downloaded GIF', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: VIDEO_MP4,
|
||||
flags: SignalService.AttachmentPointer.Flags.GIF,
|
||||
fileName: 'cat-gif.mp4',
|
||||
|
@ -847,7 +849,7 @@ story.add('Not Downloaded GIF', () => {
|
|||
blurHash: 'LDA,FDBnm+I=p{tkIUI;~UkpELV]',
|
||||
width: 400,
|
||||
height: 332,
|
||||
},
|
||||
}),
|
||||
],
|
||||
status: 'sent',
|
||||
});
|
||||
|
@ -858,7 +860,7 @@ story.add('Not Downloaded GIF', () => {
|
|||
story.add('Pending GIF', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
pending: true,
|
||||
contentType: VIDEO_MP4,
|
||||
flags: SignalService.AttachmentPointer.Flags.GIF,
|
||||
|
@ -867,7 +869,7 @@ story.add('Pending GIF', () => {
|
|||
blurHash: 'LDA,FDBnm+I=p{tkIUI;~UkpELV]',
|
||||
width: 400,
|
||||
height: 332,
|
||||
},
|
||||
}),
|
||||
],
|
||||
status: 'sent',
|
||||
});
|
||||
|
@ -881,11 +883,11 @@ story.add('Audio', () => {
|
|||
|
||||
const messageProps = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: AUDIO_MP3,
|
||||
fileName: 'incompetech-com-Agnus-Dei-X.mp3',
|
||||
url: '/fixtures/incompetech-com-Agnus-Dei-X.mp3',
|
||||
},
|
||||
}),
|
||||
],
|
||||
...(isPlayed
|
||||
? {
|
||||
|
@ -923,11 +925,11 @@ story.add('Audio', () => {
|
|||
story.add('Long Audio', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: AUDIO_MP3,
|
||||
fileName: 'long-audio.mp3',
|
||||
url: '/fixtures/long-audio.mp3',
|
||||
},
|
||||
}),
|
||||
],
|
||||
status: 'sent',
|
||||
});
|
||||
|
@ -938,11 +940,11 @@ story.add('Long Audio', () => {
|
|||
story.add('Audio with Caption', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: AUDIO_MP3,
|
||||
fileName: 'incompetech-com-Agnus-Dei-X.mp3',
|
||||
url: '/fixtures/incompetech-com-Agnus-Dei-X.mp3',
|
||||
},
|
||||
}),
|
||||
],
|
||||
status: 'sent',
|
||||
text: 'This is what I sound like.',
|
||||
|
@ -954,10 +956,10 @@ story.add('Audio with Caption', () => {
|
|||
story.add('Audio with Not Downloaded Attachment', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: AUDIO_MP3,
|
||||
fileName: 'incompetech-com-Agnus-Dei-X.mp3',
|
||||
},
|
||||
}),
|
||||
],
|
||||
status: 'sent',
|
||||
});
|
||||
|
@ -968,11 +970,11 @@ story.add('Audio with Not Downloaded Attachment', () => {
|
|||
story.add('Audio with Pending Attachment', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: AUDIO_MP3,
|
||||
fileName: 'incompetech-com-Agnus-Dei-X.mp3',
|
||||
pending: true,
|
||||
},
|
||||
}),
|
||||
],
|
||||
status: 'sent',
|
||||
});
|
||||
|
@ -983,11 +985,11 @@ story.add('Audio with Pending Attachment', () => {
|
|||
story.add('Other File Type', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: stringToMIMEType('text/plain'),
|
||||
fileName: 'my-resume.txt',
|
||||
url: 'my-resume.txt',
|
||||
},
|
||||
}),
|
||||
],
|
||||
status: 'sent',
|
||||
});
|
||||
|
@ -998,11 +1000,11 @@ story.add('Other File Type', () => {
|
|||
story.add('Other File Type with Caption', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: stringToMIMEType('text/plain'),
|
||||
fileName: 'my-resume.txt',
|
||||
url: 'my-resume.txt',
|
||||
},
|
||||
}),
|
||||
],
|
||||
status: 'sent',
|
||||
text: 'This is what I have done.',
|
||||
|
@ -1014,12 +1016,12 @@ story.add('Other File Type with Caption', () => {
|
|||
story.add('Other File Type with Long Filename', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: stringToMIMEType('text/plain'),
|
||||
fileName:
|
||||
'INSERT-APP-NAME_INSERT-APP-APPLE-ID_AppStore_AppsGamesWatch.psd.zip',
|
||||
url: 'a2/a2334324darewer4234',
|
||||
},
|
||||
}),
|
||||
],
|
||||
status: 'sent',
|
||||
text: 'This is what I have done.',
|
||||
|
@ -1031,13 +1033,13 @@ story.add('Other File Type with Long Filename', () => {
|
|||
story.add('TapToView Image', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
contentType: IMAGE_JPEG,
|
||||
width: 128,
|
||||
height: 128,
|
||||
},
|
||||
}),
|
||||
],
|
||||
isTapToView: true,
|
||||
status: 'sent',
|
||||
|
@ -1049,13 +1051,13 @@ story.add('TapToView Image', () => {
|
|||
story.add('TapToView Video', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: VIDEO_MP4,
|
||||
fileName: 'pixabay-Soap-Bubble-7141.mp4',
|
||||
height: 128,
|
||||
url: '/fixtures/pixabay-Soap-Bubble-7141.mp4',
|
||||
width: 128,
|
||||
},
|
||||
}),
|
||||
],
|
||||
isTapToView: true,
|
||||
status: 'sent',
|
||||
|
@ -1067,14 +1069,14 @@ story.add('TapToView Video', () => {
|
|||
story.add('TapToView GIF', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: VIDEO_MP4,
|
||||
flags: SignalService.AttachmentPointer.Flags.GIF,
|
||||
fileName: 'cat-gif.mp4',
|
||||
url: '/fixtures/cat-gif.mp4',
|
||||
width: 400,
|
||||
height: 332,
|
||||
},
|
||||
}),
|
||||
],
|
||||
isTapToView: true,
|
||||
status: 'sent',
|
||||
|
@ -1086,13 +1088,13 @@ story.add('TapToView GIF', () => {
|
|||
story.add('TapToView Expired', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
contentType: IMAGE_JPEG,
|
||||
width: 128,
|
||||
height: 128,
|
||||
},
|
||||
}),
|
||||
],
|
||||
isTapToView: true,
|
||||
isTapToViewExpired: true,
|
||||
|
@ -1105,13 +1107,13 @@ story.add('TapToView Expired', () => {
|
|||
story.add('TapToView Error', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
contentType: IMAGE_JPEG,
|
||||
width: 128,
|
||||
height: 128,
|
||||
},
|
||||
}),
|
||||
],
|
||||
isTapToView: true,
|
||||
isTapToViewError: true,
|
||||
|
@ -1124,13 +1126,13 @@ story.add('TapToView Error', () => {
|
|||
story.add('Dangerous File Type', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
contentType: stringToMIMEType(
|
||||
'application/vnd.microsoft.portable-executable'
|
||||
),
|
||||
fileName: 'terrible.exe',
|
||||
url: 'terrible.exe',
|
||||
},
|
||||
}),
|
||||
],
|
||||
status: 'sent',
|
||||
});
|
||||
|
@ -1174,13 +1176,13 @@ story.add('@Mentions', () => {
|
|||
story.add('All the context menus', () => {
|
||||
const props = createProps({
|
||||
attachments: [
|
||||
{
|
||||
fakeAttachment({
|
||||
url: '/fixtures/tina-rolf-269345-unsplash.jpg',
|
||||
fileName: 'tina-rolf-269345-unsplash.jpg',
|
||||
contentType: IMAGE_JPEG,
|
||||
width: 128,
|
||||
height: 128,
|
||||
},
|
||||
}),
|
||||
],
|
||||
status: 'partial-sent',
|
||||
canDeleteForEveryone: true,
|
||||
|
@ -1194,13 +1196,13 @@ story.add('Not approved, with link preview', () => {
|
|||
previews: [
|
||||
{
|
||||
domain: 'signal.org',
|
||||
image: {
|
||||
image: fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
fileName: 'the-sax.png',
|
||||
height: 240,
|
||||
url: pngUrl,
|
||||
width: 320,
|
||||
},
|
||||
}),
|
||||
isStickerPack: false,
|
||||
title: 'Signal',
|
||||
description:
|
||||
|
|
|
@ -33,6 +33,7 @@ const createAttachment = (
|
|||
),
|
||||
fileName: text('attachment fileName', props.fileName || ''),
|
||||
url: '',
|
||||
size: 14243,
|
||||
});
|
||||
|
||||
story.add('Text File', () => {
|
||||
|
|
|
@ -32,6 +32,7 @@ const createAttachment = (
|
|||
),
|
||||
fileName: text('attachment fileName', props.fileName || ''),
|
||||
url: text('attachment url', props.url || ''),
|
||||
size: 24325,
|
||||
});
|
||||
|
||||
const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||
|
|
|
@ -27,8 +27,8 @@ import type {
|
|||
AttachmentType,
|
||||
GroupV1InfoType,
|
||||
GroupV2InfoType,
|
||||
PreviewType,
|
||||
} from '../textsecure/SendMessage';
|
||||
import type { LinkPreviewType } from '../types/message/LinkPreviews';
|
||||
import type { BodyRangesType } from '../types/Util';
|
||||
import type { WhatIsThis } from '../window.d';
|
||||
|
||||
|
@ -299,7 +299,7 @@ export class NormalMessageSendJobQueue extends JobQueue<NormalMessageSendJobData
|
|||
quote,
|
||||
preview,
|
||||
sticker,
|
||||
reaction: null,
|
||||
reaction: undefined,
|
||||
deletedForEveryoneTimestamp,
|
||||
timestamp: messageTimestamp,
|
||||
expireTimer,
|
||||
|
@ -464,7 +464,7 @@ async function getMessageSendData({
|
|||
expireTimer: undefined | number;
|
||||
mentions: undefined | BodyRangesType;
|
||||
messageTimestamp: number;
|
||||
preview: Array<PreviewType>;
|
||||
preview: Array<LinkPreviewType>;
|
||||
profileKey: undefined | Uint8Array;
|
||||
quote: WhatIsThis;
|
||||
sticker: WhatIsThis;
|
||||
|
|
|
@ -23,6 +23,7 @@ import { CapabilityError } from '../types/errors';
|
|||
import type {
|
||||
GroupV1InfoType,
|
||||
GroupV2InfoType,
|
||||
StickerType,
|
||||
} from '../textsecure/SendMessage';
|
||||
import createTaskWithTimeout from '../textsecure/TaskWithTimeout';
|
||||
import { CallbackResultType } from '../textsecure/Types.d';
|
||||
|
@ -60,6 +61,7 @@ import { sendReadReceiptsFor } from '../util/sendReadReceiptsFor';
|
|||
import { updateConversationsWithUuidLookup } from '../updateConversationsWithUuidLookup';
|
||||
import { ReadStatus } from '../messages/MessageReadStatus';
|
||||
import { SendState, SendStatus } from '../messages/MessageSendState';
|
||||
import type { LinkPreviewType } from '../types/message/LinkPreviews';
|
||||
import * as durations from '../util/durations';
|
||||
import {
|
||||
concat,
|
||||
|
@ -3279,8 +3281,8 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
|
||||
const { key } = packData;
|
||||
const { path, width, height } = stickerData;
|
||||
const arrayBuffer = await readStickerData(path);
|
||||
const { emoji, path, width, height } = stickerData;
|
||||
const data = await readStickerData(path);
|
||||
|
||||
// We need this content type to be an image so we can display an `<img>` instead of a
|
||||
// `<video>` or an error, but it's not critical that we get the full type correct.
|
||||
|
@ -3289,11 +3291,13 @@ export class ConversationModel extends window.Backbone
|
|||
// the MIME type here, but it's okay if we have to use a possibly-incorrect
|
||||
// fallback.
|
||||
let contentType: MIMEType;
|
||||
const sniffedMimeType = sniffImageMimeType(arrayBuffer);
|
||||
const sniffedMimeType = sniffImageMimeType(data);
|
||||
if (sniffedMimeType) {
|
||||
contentType = sniffedMimeType;
|
||||
} else {
|
||||
log.warn('Unable to sniff sticker MIME type; falling back to WebP');
|
||||
log.warn(
|
||||
'sendStickerMessage: Unable to sniff sticker MIME type; falling back to WebP'
|
||||
);
|
||||
contentType = IMAGE_WEBP;
|
||||
}
|
||||
|
||||
|
@ -3301,9 +3305,10 @@ export class ConversationModel extends window.Backbone
|
|||
packId,
|
||||
stickerId,
|
||||
packKey: key,
|
||||
emoji,
|
||||
data: {
|
||||
size: arrayBuffer.byteLength,
|
||||
data: arrayBuffer,
|
||||
size: data.byteLength,
|
||||
data,
|
||||
contentType,
|
||||
width,
|
||||
height,
|
||||
|
@ -3630,8 +3635,8 @@ export class ConversationModel extends window.Backbone
|
|||
body: string | undefined,
|
||||
attachments: Array<AttachmentType>,
|
||||
quote?: QuotedMessageType,
|
||||
preview?: WhatIsThis,
|
||||
sticker?: WhatIsThis,
|
||||
preview?: Array<LinkPreviewType>,
|
||||
sticker?: StickerType,
|
||||
mentions?: BodyRangesType,
|
||||
{
|
||||
dontClearDraft,
|
||||
|
|
|
@ -45,7 +45,7 @@ import * as Errors from '../types/errors';
|
|||
import * as EmbeddedContact from '../types/EmbeddedContact';
|
||||
import { AttachmentType, isImage, isVideo } from '../types/Attachment';
|
||||
import * as Attachment from '../types/Attachment';
|
||||
import { IMAGE_WEBP, stringToMIMEType } from '../types/MIME';
|
||||
import { stringToMIMEType } from '../types/MIME';
|
||||
import * as MIME from '../types/MIME';
|
||||
import { ReadStatus } from '../messages/MessageReadStatus';
|
||||
import {
|
||||
|
@ -117,7 +117,7 @@ import * as LinkPreview from '../types/LinkPreview';
|
|||
import { SignalService as Proto } from '../protobuf';
|
||||
import { normalMessageSendJobQueue } from '../jobs/normalMessageSendJobQueue';
|
||||
import { notificationService } from '../services/notifications';
|
||||
import type { PreviewType as OutgoingPreviewType } from '../textsecure/SendMessage';
|
||||
import type { LinkPreviewType } from '../types/message/LinkPreviews';
|
||||
import * as log from '../logging/log';
|
||||
import * as Bytes from '../Bytes';
|
||||
import { computeHash } from '../Crypto';
|
||||
|
@ -188,7 +188,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
|
||||
syncPromise?: Promise<CallbackResultType | void>;
|
||||
|
||||
cachedOutgoingPreviewData?: Array<OutgoingPreviewType>;
|
||||
cachedOutgoingPreviewData?: Array<LinkPreviewType>;
|
||||
|
||||
cachedOutgoingQuoteData?: WhatIsThis;
|
||||
|
||||
|
@ -2012,14 +2012,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
|
||||
if (status && (status === 'downloaded' || status === 'installed')) {
|
||||
try {
|
||||
const copiedSticker = await copyStickerToAttachments(
|
||||
packId,
|
||||
stickerId
|
||||
);
|
||||
data = {
|
||||
...copiedSticker,
|
||||
contentType: IMAGE_WEBP,
|
||||
};
|
||||
data = await copyStickerToAttachments(packId, stickerId);
|
||||
} catch (error) {
|
||||
log.error(
|
||||
`Problem copying sticker (${packId}, ${stickerId}) to attachments:`,
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { AttachmentType } from '../../types/Attachment';
|
||||
import { IMAGE_JPEG } from '../../types/MIME';
|
||||
|
||||
export const fakeAttachment = (
|
||||
overrides: Partial<AttachmentType> = {}
|
||||
): AttachmentType => ({
|
||||
contentType: IMAGE_JPEG,
|
||||
width: 800,
|
||||
height: 600,
|
||||
size: 10304,
|
||||
...overrides,
|
||||
});
|
|
@ -2,8 +2,9 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { IMAGE_JPEG, VIDEO_MP4 } from '../../types/MIME';
|
||||
import { AttachmentType } from '../../types/Attachment';
|
||||
import { VIDEO_MP4 } from '../../types/MIME';
|
||||
|
||||
import { fakeAttachment } from '../helpers/fakeAttachment';
|
||||
|
||||
import { shouldUseFullSizeLinkPreviewImage } from '../../linkPreviews/shouldUseFullSizeLinkPreviewImage';
|
||||
|
||||
|
@ -15,17 +16,6 @@ describe('shouldUseFullSizeLinkPreviewImage', () => {
|
|||
isStickerPack: false,
|
||||
};
|
||||
|
||||
const fakeAttachment = (
|
||||
overrides: Partial<AttachmentType> = {}
|
||||
): AttachmentType => ({
|
||||
contentType: IMAGE_JPEG,
|
||||
fileName: 'foo.jpg',
|
||||
url: '/tmp/foo.jpg',
|
||||
width: 800,
|
||||
height: 600,
|
||||
...overrides,
|
||||
});
|
||||
|
||||
it('returns false if there is no image', () => {
|
||||
assert.isFalse(
|
||||
shouldUseFullSizeLinkPreviewImage({
|
||||
|
|
|
@ -10,6 +10,7 @@ import { reducer as rootReducer } from '../../../state/reducer';
|
|||
|
||||
import { IMAGE_JPEG } from '../../../types/MIME';
|
||||
import { AttachmentType } from '../../../types/Attachment';
|
||||
import { fakeAttachment } from '../../helpers/fakeAttachment';
|
||||
|
||||
describe('both/state/ducks/composer', () => {
|
||||
const QUOTED_MESSAGE = {
|
||||
|
@ -40,7 +41,7 @@ describe('both/state/ducks/composer', () => {
|
|||
const dispatch = sinon.spy();
|
||||
|
||||
const attachments: Array<AttachmentType> = [
|
||||
{ contentType: IMAGE_JPEG, pending: false, url: '' },
|
||||
{ contentType: IMAGE_JPEG, pending: false, url: '', size: 2433 },
|
||||
];
|
||||
replaceAttachments('123', attachments)(
|
||||
dispatch,
|
||||
|
@ -82,7 +83,7 @@ describe('both/state/ducks/composer', () => {
|
|||
const { replaceAttachments } = actions;
|
||||
const dispatch = sinon.spy();
|
||||
|
||||
const attachments: Array<AttachmentType> = [{ contentType: IMAGE_JPEG }];
|
||||
const attachments = [fakeAttachment()];
|
||||
replaceAttachments('123', attachments)(
|
||||
dispatch,
|
||||
getRootStateFunction('456'),
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
Section,
|
||||
} from '../../../components/conversation/media-gallery/groupMediaItemsByDate';
|
||||
import { MediaItemType } from '../../../types/MediaItem';
|
||||
import { fakeAttachment } from '../../../test-both/helpers/fakeAttachment';
|
||||
|
||||
const testDate = (
|
||||
year: number,
|
||||
|
@ -31,11 +32,11 @@ const toMediaItem = (date: Date): MediaItemType => ({
|
|||
attachments: [],
|
||||
sent_at: date.getTime(),
|
||||
},
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
fileName: 'fileName',
|
||||
contentType: IMAGE_JPEG,
|
||||
url: 'url',
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
describe('groupMediaItemsByDate', () => {
|
||||
|
@ -74,11 +75,11 @@ describe('groupMediaItemsByDate', () => {
|
|||
attachments: [],
|
||||
sent_at: 1523534400000,
|
||||
},
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
fileName: 'fileName',
|
||||
contentType: IMAGE_JPEG,
|
||||
url: 'url',
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
objectURL: 'Thu, 12 Apr 2018 00:01:00 GMT',
|
||||
|
@ -91,11 +92,11 @@ describe('groupMediaItemsByDate', () => {
|
|||
attachments: [],
|
||||
sent_at: 1523491260000,
|
||||
},
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
fileName: 'fileName',
|
||||
contentType: IMAGE_JPEG,
|
||||
url: 'url',
|
||||
},
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -113,11 +114,11 @@ describe('groupMediaItemsByDate', () => {
|
|||
attachments: [],
|
||||
sent_at: 1523491140000,
|
||||
},
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
fileName: 'fileName',
|
||||
contentType: IMAGE_JPEG,
|
||||
url: 'url',
|
||||
},
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -135,11 +136,11 @@ describe('groupMediaItemsByDate', () => {
|
|||
attachments: [],
|
||||
sent_at: 1523232060000,
|
||||
},
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
fileName: 'fileName',
|
||||
contentType: IMAGE_JPEG,
|
||||
url: 'url',
|
||||
},
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -157,11 +158,11 @@ describe('groupMediaItemsByDate', () => {
|
|||
attachments: [],
|
||||
sent_at: 1523231940000,
|
||||
},
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
fileName: 'fileName',
|
||||
contentType: IMAGE_JPEG,
|
||||
url: 'url',
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
objectURL: 'Sun, 01 Apr 2018 00:01:00 GMT',
|
||||
|
@ -174,11 +175,11 @@ describe('groupMediaItemsByDate', () => {
|
|||
attachments: [],
|
||||
sent_at: 1522540860000,
|
||||
},
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
fileName: 'fileName',
|
||||
contentType: IMAGE_JPEG,
|
||||
url: 'url',
|
||||
},
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -198,11 +199,11 @@ describe('groupMediaItemsByDate', () => {
|
|||
attachments: [],
|
||||
sent_at: 1522540740000,
|
||||
},
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
fileName: 'fileName',
|
||||
contentType: IMAGE_JPEG,
|
||||
url: 'url',
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
objectURL: 'Thu, 01 Mar 2018 14:00:00 GMT',
|
||||
|
@ -215,11 +216,11 @@ describe('groupMediaItemsByDate', () => {
|
|||
attachments: [],
|
||||
sent_at: 1519912800000,
|
||||
},
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
fileName: 'fileName',
|
||||
contentType: IMAGE_JPEG,
|
||||
url: 'url',
|
||||
},
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -239,11 +240,11 @@ describe('groupMediaItemsByDate', () => {
|
|||
attachments: [],
|
||||
sent_at: 1298937540000,
|
||||
},
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
fileName: 'fileName',
|
||||
contentType: IMAGE_JPEG,
|
||||
url: 'url',
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
objectURL: 'Tue, 01 Feb 2011 10:00:00 GMT',
|
||||
|
@ -256,11 +257,11 @@ describe('groupMediaItemsByDate', () => {
|
|||
attachments: [],
|
||||
sent_at: 1296554400000,
|
||||
},
|
||||
attachment: {
|
||||
attachment: fakeAttachment({
|
||||
fileName: 'fileName',
|
||||
contentType: IMAGE_JPEG,
|
||||
url: 'url',
|
||||
},
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -9,6 +9,8 @@ import { SignalService } from '../../protobuf';
|
|||
import * as Bytes from '../../Bytes';
|
||||
import * as logger from '../../logging/log';
|
||||
|
||||
import { fakeAttachment } from '../../test-both/helpers/fakeAttachment';
|
||||
|
||||
describe('Attachment', () => {
|
||||
describe('getUploadSizeLimitKb', () => {
|
||||
const { getUploadSizeLimitKb } = Attachment;
|
||||
|
@ -37,18 +39,18 @@ describe('Attachment', () => {
|
|||
|
||||
describe('getFileExtension', () => {
|
||||
it('should return file extension from content type', () => {
|
||||
const input: Attachment.AttachmentType = {
|
||||
const input: Attachment.AttachmentType = fakeAttachment({
|
||||
data: Bytes.fromString('foo'),
|
||||
contentType: MIME.IMAGE_GIF,
|
||||
};
|
||||
});
|
||||
assert.strictEqual(Attachment.getFileExtension(input), 'gif');
|
||||
});
|
||||
|
||||
it('should return file extension for QuickTime videos', () => {
|
||||
const input: Attachment.AttachmentType = {
|
||||
const input: Attachment.AttachmentType = fakeAttachment({
|
||||
data: Bytes.fromString('foo'),
|
||||
contentType: MIME.VIDEO_QUICKTIME,
|
||||
};
|
||||
});
|
||||
assert.strictEqual(Attachment.getFileExtension(input), 'mov');
|
||||
});
|
||||
});
|
||||
|
@ -56,11 +58,11 @@ describe('Attachment', () => {
|
|||
describe('getSuggestedFilename', () => {
|
||||
context('for attachment with filename', () => {
|
||||
it('should return existing filename if present', () => {
|
||||
const attachment: Attachment.AttachmentType = {
|
||||
const attachment: Attachment.AttachmentType = fakeAttachment({
|
||||
fileName: 'funny-cat.mov',
|
||||
data: Bytes.fromString('foo'),
|
||||
contentType: MIME.VIDEO_QUICKTIME,
|
||||
};
|
||||
});
|
||||
const actual = Attachment.getSuggestedFilename({ attachment });
|
||||
const expected = 'funny-cat.mov';
|
||||
assert.strictEqual(actual, expected);
|
||||
|
@ -68,10 +70,10 @@ describe('Attachment', () => {
|
|||
});
|
||||
context('for attachment without filename', () => {
|
||||
it('should generate a filename based on timestamp', () => {
|
||||
const attachment: Attachment.AttachmentType = {
|
||||
const attachment: Attachment.AttachmentType = fakeAttachment({
|
||||
data: Bytes.fromString('foo'),
|
||||
contentType: MIME.VIDEO_QUICKTIME,
|
||||
};
|
||||
});
|
||||
const timestamp = new Date(new Date(0).getTimezoneOffset() * 60 * 1000);
|
||||
const actual = Attachment.getSuggestedFilename({
|
||||
attachment,
|
||||
|
@ -83,10 +85,10 @@ describe('Attachment', () => {
|
|||
});
|
||||
context('for attachment with index', () => {
|
||||
it('should generate a filename based on timestamp', () => {
|
||||
const attachment: Attachment.AttachmentType = {
|
||||
const attachment: Attachment.AttachmentType = fakeAttachment({
|
||||
data: Bytes.fromString('foo'),
|
||||
contentType: MIME.VIDEO_QUICKTIME,
|
||||
};
|
||||
});
|
||||
const timestamp = new Date(new Date(0).getTimezoneOffset() * 60 * 1000);
|
||||
const actual = Attachment.getSuggestedFilename({
|
||||
attachment,
|
||||
|
@ -101,107 +103,107 @@ describe('Attachment', () => {
|
|||
|
||||
describe('isVisualMedia', () => {
|
||||
it('should return true for images', () => {
|
||||
const attachment: Attachment.AttachmentType = {
|
||||
const attachment: Attachment.AttachmentType = fakeAttachment({
|
||||
fileName: 'meme.gif',
|
||||
data: Bytes.fromString('gif'),
|
||||
contentType: MIME.IMAGE_GIF,
|
||||
};
|
||||
});
|
||||
assert.isTrue(Attachment.isVisualMedia(attachment));
|
||||
});
|
||||
|
||||
it('should return true for videos', () => {
|
||||
const attachment: Attachment.AttachmentType = {
|
||||
const attachment: Attachment.AttachmentType = fakeAttachment({
|
||||
fileName: 'meme.mp4',
|
||||
data: Bytes.fromString('mp4'),
|
||||
contentType: MIME.VIDEO_MP4,
|
||||
};
|
||||
});
|
||||
assert.isTrue(Attachment.isVisualMedia(attachment));
|
||||
});
|
||||
|
||||
it('should return false for voice message attachment', () => {
|
||||
const attachment: Attachment.AttachmentType = {
|
||||
const attachment: Attachment.AttachmentType = fakeAttachment({
|
||||
fileName: 'Voice Message.aac',
|
||||
flags: SignalService.AttachmentPointer.Flags.VOICE_MESSAGE,
|
||||
data: Bytes.fromString('voice message'),
|
||||
contentType: MIME.AUDIO_AAC,
|
||||
};
|
||||
});
|
||||
assert.isFalse(Attachment.isVisualMedia(attachment));
|
||||
});
|
||||
|
||||
it('should return false for other attachments', () => {
|
||||
const attachment: Attachment.AttachmentType = {
|
||||
const attachment: Attachment.AttachmentType = fakeAttachment({
|
||||
fileName: 'foo.json',
|
||||
data: Bytes.fromString('{"foo": "bar"}'),
|
||||
contentType: MIME.APPLICATION_JSON,
|
||||
};
|
||||
});
|
||||
assert.isFalse(Attachment.isVisualMedia(attachment));
|
||||
});
|
||||
});
|
||||
|
||||
describe('isFile', () => {
|
||||
it('should return true for JSON', () => {
|
||||
const attachment: Attachment.AttachmentType = {
|
||||
const attachment: Attachment.AttachmentType = fakeAttachment({
|
||||
fileName: 'foo.json',
|
||||
data: Bytes.fromString('{"foo": "bar"}'),
|
||||
contentType: MIME.APPLICATION_JSON,
|
||||
};
|
||||
});
|
||||
assert.isTrue(Attachment.isFile(attachment));
|
||||
});
|
||||
|
||||
it('should return false for images', () => {
|
||||
const attachment: Attachment.AttachmentType = {
|
||||
const attachment: Attachment.AttachmentType = fakeAttachment({
|
||||
fileName: 'meme.gif',
|
||||
data: Bytes.fromString('gif'),
|
||||
contentType: MIME.IMAGE_GIF,
|
||||
};
|
||||
});
|
||||
assert.isFalse(Attachment.isFile(attachment));
|
||||
});
|
||||
|
||||
it('should return false for videos', () => {
|
||||
const attachment: Attachment.AttachmentType = {
|
||||
const attachment: Attachment.AttachmentType = fakeAttachment({
|
||||
fileName: 'meme.mp4',
|
||||
data: Bytes.fromString('mp4'),
|
||||
contentType: MIME.VIDEO_MP4,
|
||||
};
|
||||
});
|
||||
assert.isFalse(Attachment.isFile(attachment));
|
||||
});
|
||||
|
||||
it('should return false for voice message attachment', () => {
|
||||
const attachment: Attachment.AttachmentType = {
|
||||
const attachment: Attachment.AttachmentType = fakeAttachment({
|
||||
fileName: 'Voice Message.aac',
|
||||
flags: SignalService.AttachmentPointer.Flags.VOICE_MESSAGE,
|
||||
data: Bytes.fromString('voice message'),
|
||||
contentType: MIME.AUDIO_AAC,
|
||||
};
|
||||
});
|
||||
assert.isFalse(Attachment.isFile(attachment));
|
||||
});
|
||||
});
|
||||
|
||||
describe('isVoiceMessage', () => {
|
||||
it('should return true for voice message attachment', () => {
|
||||
const attachment: Attachment.AttachmentType = {
|
||||
const attachment: Attachment.AttachmentType = fakeAttachment({
|
||||
fileName: 'Voice Message.aac',
|
||||
flags: SignalService.AttachmentPointer.Flags.VOICE_MESSAGE,
|
||||
data: Bytes.fromString('voice message'),
|
||||
contentType: MIME.AUDIO_AAC,
|
||||
};
|
||||
});
|
||||
assert.isTrue(Attachment.isVoiceMessage(attachment));
|
||||
});
|
||||
|
||||
it('should return true for legacy Android voice message attachment', () => {
|
||||
const attachment: Attachment.AttachmentType = {
|
||||
const attachment: Attachment.AttachmentType = fakeAttachment({
|
||||
data: Bytes.fromString('voice message'),
|
||||
contentType: MIME.AUDIO_MP3,
|
||||
};
|
||||
});
|
||||
assert.isTrue(Attachment.isVoiceMessage(attachment));
|
||||
});
|
||||
|
||||
it('should return false for other attachments', () => {
|
||||
const attachment: Attachment.AttachmentType = {
|
||||
const attachment: Attachment.AttachmentType = fakeAttachment({
|
||||
fileName: 'foo.gif',
|
||||
data: Bytes.fromString('foo'),
|
||||
contentType: MIME.IMAGE_GIF,
|
||||
};
|
||||
});
|
||||
assert.isFalse(Attachment.isVoiceMessage(attachment));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
getName,
|
||||
parseAndWriteAvatar,
|
||||
} from '../../types/EmbeddedContact';
|
||||
import { fakeAttachment } from '../../test-both/helpers/fakeAttachment';
|
||||
|
||||
describe('Contact', () => {
|
||||
const NUMBER = '+12025550099';
|
||||
|
@ -127,10 +128,10 @@ describe('Contact', () => {
|
|||
organization: 'Somewhere, Inc.',
|
||||
avatar: {
|
||||
isProfile: true,
|
||||
avatar: {
|
||||
avatar: fakeAttachment({
|
||||
error: true,
|
||||
contentType: IMAGE_GIF,
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
const expected = {
|
||||
|
@ -164,10 +165,10 @@ describe('Contact', () => {
|
|||
organization: 'Somewhere, Inc.',
|
||||
avatar: {
|
||||
isProfile: true,
|
||||
avatar: {
|
||||
avatar: fakeAttachment({
|
||||
pending: true,
|
||||
contentType: IMAGE_GIF,
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
const expected = {
|
||||
|
@ -179,11 +180,11 @@ describe('Contact', () => {
|
|||
organization: 'Somewhere, Inc.',
|
||||
avatar: {
|
||||
isProfile: true,
|
||||
avatar: {
|
||||
avatar: fakeAttachment({
|
||||
pending: true,
|
||||
path: undefined,
|
||||
contentType: IMAGE_GIF,
|
||||
},
|
||||
}),
|
||||
},
|
||||
firstNumber,
|
||||
isNumberOnSignal,
|
||||
|
@ -208,10 +209,10 @@ describe('Contact', () => {
|
|||
organization: 'Somewhere, Inc.',
|
||||
avatar: {
|
||||
isProfile: true,
|
||||
avatar: {
|
||||
avatar: fakeAttachment({
|
||||
path: 'somewhere',
|
||||
contentType: IMAGE_GIF,
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
const expected = {
|
||||
|
@ -223,10 +224,10 @@ describe('Contact', () => {
|
|||
organization: 'Somewhere, Inc.',
|
||||
avatar: {
|
||||
isProfile: true,
|
||||
avatar: {
|
||||
avatar: fakeAttachment({
|
||||
path: 'absolute:somewhere',
|
||||
contentType: IMAGE_GIF,
|
||||
},
|
||||
}),
|
||||
},
|
||||
firstNumber,
|
||||
isNumberOnSignal: true,
|
||||
|
@ -363,10 +364,10 @@ describe('Contact', () => {
|
|||
|
||||
it('writes avatar to disk', async () => {
|
||||
const upgradeAttachment = async () => {
|
||||
return {
|
||||
return fakeAttachment({
|
||||
path: 'abc/abcdefg',
|
||||
contentType: IMAGE_PNG,
|
||||
};
|
||||
});
|
||||
};
|
||||
const upgradeVersion = parseAndWriteAvatar(upgradeAttachment);
|
||||
|
||||
|
@ -430,10 +431,10 @@ describe('Contact', () => {
|
|||
avatar: {
|
||||
otherKey: 'otherValue',
|
||||
isProfile: false,
|
||||
avatar: {
|
||||
avatar: fakeAttachment({
|
||||
contentType: IMAGE_PNG,
|
||||
path: 'abc/abcdefg',
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
/* eslint-disable class-methods-use-this */
|
||||
/* eslint-disable more/no-then */
|
||||
/* eslint-disable no-bitwise */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable max-classes-per-file */
|
||||
|
||||
import { Dictionary } from 'lodash';
|
||||
|
@ -23,6 +22,9 @@ import { Address } from '../types/Address';
|
|||
import { QualifiedAddress } from '../types/QualifiedAddress';
|
||||
import { UUID } from '../types/UUID';
|
||||
import { SenderKeys } from '../LibSignalStores';
|
||||
import type { LinkPreviewType } from '../types/message/LinkPreviews';
|
||||
import { MIMETypeToString } from '../types/MIME';
|
||||
import * as Attachment from '../types/Attachment';
|
||||
import {
|
||||
ChallengeType,
|
||||
GroupCredentialsType,
|
||||
|
@ -77,12 +79,6 @@ export type SendOptionsType = {
|
|||
online?: boolean;
|
||||
};
|
||||
|
||||
export type PreviewType = {
|
||||
url: string;
|
||||
title: string;
|
||||
image?: AttachmentType;
|
||||
};
|
||||
|
||||
type QuoteAttachmentType = {
|
||||
thumbnail?: AttachmentType;
|
||||
attachmentPointer?: Proto.IAttachmentPointer;
|
||||
|
@ -103,22 +99,65 @@ type GroupCallUpdateType = {
|
|||
eraId: string;
|
||||
};
|
||||
|
||||
export type StickerType = {
|
||||
packId: string;
|
||||
stickerId: number;
|
||||
packKey: string;
|
||||
data: Readonly<AttachmentType>;
|
||||
emoji?: string;
|
||||
|
||||
attachmentPointer?: Proto.IAttachmentPointer;
|
||||
};
|
||||
|
||||
export type QuoteType = {
|
||||
id?: number;
|
||||
authorUuid?: string;
|
||||
text?: string;
|
||||
attachments?: Array<AttachmentType>;
|
||||
bodyRanges?: BodyRangesType;
|
||||
};
|
||||
|
||||
export type ReactionType = {
|
||||
emoji?: string;
|
||||
remove?: boolean;
|
||||
targetAuthorUuid?: string;
|
||||
targetTimestamp?: number;
|
||||
};
|
||||
|
||||
export type AttachmentType = {
|
||||
size: number;
|
||||
data: Uint8Array;
|
||||
contentType: string;
|
||||
|
||||
fileName: string;
|
||||
flags: number;
|
||||
width: number;
|
||||
height: number;
|
||||
caption: string;
|
||||
fileName?: string;
|
||||
flags?: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
caption?: string;
|
||||
|
||||
attachmentPointer?: Proto.IAttachmentPointer;
|
||||
|
||||
blurHash?: string;
|
||||
};
|
||||
|
||||
function makeAttachmentSendReady(
|
||||
attachment: Attachment.AttachmentType
|
||||
): AttachmentType | undefined {
|
||||
const { data } = attachment;
|
||||
|
||||
if (!data) {
|
||||
throw new Error(
|
||||
'makeAttachmentSendReady: Missing data, returning undefined'
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...attachment,
|
||||
contentType: MIMETypeToString(attachment.contentType),
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
export type MessageOptionsType = {
|
||||
attachments?: ReadonlyArray<AttachmentType> | null;
|
||||
body?: string;
|
||||
|
@ -130,12 +169,12 @@ export type MessageOptionsType = {
|
|||
};
|
||||
groupV2?: GroupV2InfoType;
|
||||
needsSync?: boolean;
|
||||
preview?: ReadonlyArray<PreviewType> | null;
|
||||
preview?: ReadonlyArray<LinkPreviewType>;
|
||||
profileKey?: Uint8Array;
|
||||
quote?: any;
|
||||
quote?: QuoteType;
|
||||
recipients: ReadonlyArray<string>;
|
||||
sticker?: any;
|
||||
reaction?: any;
|
||||
sticker?: StickerType;
|
||||
reaction?: ReactionType;
|
||||
deletedForEveryoneTimestamp?: number;
|
||||
timestamp: number;
|
||||
mentions?: BodyRangesType;
|
||||
|
@ -147,11 +186,11 @@ export type GroupSendOptionsType = {
|
|||
groupV2?: GroupV2InfoType;
|
||||
groupV1?: GroupV1InfoType;
|
||||
messageText?: string;
|
||||
preview?: any;
|
||||
preview?: ReadonlyArray<LinkPreviewType>;
|
||||
profileKey?: Uint8Array;
|
||||
quote?: any;
|
||||
reaction?: any;
|
||||
sticker?: any;
|
||||
quote?: QuoteType;
|
||||
reaction?: ReactionType;
|
||||
sticker?: StickerType;
|
||||
deletedForEveryoneTimestamp?: number;
|
||||
timestamp: number;
|
||||
mentions?: BodyRangesType;
|
||||
|
@ -159,7 +198,7 @@ export type GroupSendOptionsType = {
|
|||
};
|
||||
|
||||
class Message {
|
||||
attachments: ReadonlyArray<any>;
|
||||
attachments: ReadonlyArray<AttachmentType>;
|
||||
|
||||
body?: string;
|
||||
|
||||
|
@ -176,28 +215,17 @@ class Message {
|
|||
|
||||
needsSync?: boolean;
|
||||
|
||||
preview: any;
|
||||
preview?: ReadonlyArray<LinkPreviewType>;
|
||||
|
||||
profileKey?: Uint8Array;
|
||||
|
||||
quote?: {
|
||||
id?: number;
|
||||
authorUuid?: string;
|
||||
text?: string;
|
||||
attachments?: Array<AttachmentType>;
|
||||
bodyRanges?: BodyRangesType;
|
||||
};
|
||||
quote?: QuoteType;
|
||||
|
||||
recipients: ReadonlyArray<string>;
|
||||
|
||||
sticker?: any;
|
||||
sticker?: StickerType;
|
||||
|
||||
reaction?: {
|
||||
emoji?: string;
|
||||
remove?: boolean;
|
||||
targetAuthorUuid?: string;
|
||||
targetTimestamp?: number;
|
||||
};
|
||||
reaction?: ReactionType;
|
||||
|
||||
timestamp: number;
|
||||
|
||||
|
@ -325,6 +353,7 @@ class Message {
|
|||
proto.sticker.packId = Bytes.fromHex(this.sticker.packId);
|
||||
proto.sticker.packKey = Bytes.fromBase64(this.sticker.packKey);
|
||||
proto.sticker.stickerId = this.sticker.stickerId;
|
||||
proto.sticker.emoji = this.sticker.emoji;
|
||||
|
||||
if (this.sticker.attachmentPointer) {
|
||||
proto.sticker.data = this.sticker.attachmentPointer;
|
||||
|
@ -345,7 +374,9 @@ class Message {
|
|||
item.url = preview.url;
|
||||
item.description = preview.description || null;
|
||||
item.date = preview.date || null;
|
||||
item.image = preview.image || null;
|
||||
if (preview.attachmentPointer) {
|
||||
item.image = preview.attachmentPointer;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
}
|
||||
|
@ -364,7 +395,9 @@ class Message {
|
|||
const quotedAttachment = new QuotedAttachment();
|
||||
|
||||
quotedAttachment.contentType = attachment.contentType;
|
||||
quotedAttachment.fileName = attachment.fileName;
|
||||
if (attachment.fileName) {
|
||||
quotedAttachment.fileName = attachment.fileName;
|
||||
}
|
||||
if (attachment.attachmentPointer) {
|
||||
quotedAttachment.thumbnail = attachment.attachmentPointer;
|
||||
}
|
||||
|
@ -442,10 +475,10 @@ export default class MessageSender {
|
|||
this.pendingMessages = {};
|
||||
}
|
||||
|
||||
async queueJobForIdentifier(
|
||||
async queueJobForIdentifier<T>(
|
||||
identifier: string,
|
||||
runJob: () => Promise<any>
|
||||
): Promise<void> {
|
||||
runJob: () => Promise<T>
|
||||
): Promise<T> {
|
||||
const { id } = await window.ConversationController.getOrCreateAndWait(
|
||||
identifier,
|
||||
'private'
|
||||
|
@ -546,8 +579,10 @@ export default class MessageSender {
|
|||
}
|
||||
|
||||
async uploadAttachments(message: Message): Promise<void> {
|
||||
return Promise.all(
|
||||
message.attachments.map(this.makeAttachmentPointer.bind(this))
|
||||
await Promise.all(
|
||||
message.attachments.map(attachment =>
|
||||
this.makeAttachmentPointer(attachment)
|
||||
)
|
||||
)
|
||||
.then(attachmentPointers => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
|
@ -565,12 +600,20 @@ export default class MessageSender {
|
|||
async uploadLinkPreviews(message: Message): Promise<void> {
|
||||
try {
|
||||
const preview = await Promise.all(
|
||||
(message.preview || []).map(async (item: PreviewType) => ({
|
||||
...item,
|
||||
image: item.image
|
||||
? await this.makeAttachmentPointer(item.image)
|
||||
: undefined,
|
||||
}))
|
||||
(message.preview || []).map(async (item: Readonly<LinkPreviewType>) => {
|
||||
if (!item.image) {
|
||||
return item;
|
||||
}
|
||||
const attachment = makeAttachmentSendReady(item.image);
|
||||
if (!attachment) {
|
||||
return item;
|
||||
}
|
||||
|
||||
return {
|
||||
...item,
|
||||
attachmentPointer: await this.makeAttachmentPointer(attachment),
|
||||
};
|
||||
})
|
||||
);
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
message.preview = preview;
|
||||
|
@ -968,10 +1011,10 @@ export default class MessageSender {
|
|||
identifier: string;
|
||||
messageText: string | undefined;
|
||||
attachments: ReadonlyArray<AttachmentType> | undefined;
|
||||
quote: unknown;
|
||||
preview: ReadonlyArray<PreviewType> | undefined;
|
||||
sticker: unknown;
|
||||
reaction: unknown;
|
||||
quote?: QuoteType;
|
||||
preview?: ReadonlyArray<LinkPreviewType> | undefined;
|
||||
sticker?: StickerType;
|
||||
reaction?: ReactionType;
|
||||
deletedForEveryoneTimestamp: number | undefined;
|
||||
timestamp: number;
|
||||
expireTimer: number | undefined;
|
||||
|
@ -2080,7 +2123,7 @@ export default class MessageSender {
|
|||
profileKeyVersion?: string;
|
||||
profileKeyCredentialRequest?: string;
|
||||
}> = {}
|
||||
): Promise<any> {
|
||||
): Promise<ReturnType<WebAPIType['getProfile']>> {
|
||||
const { accessKey } = options;
|
||||
|
||||
if (accessKey) {
|
||||
|
@ -2100,15 +2143,20 @@ export default class MessageSender {
|
|||
return this.server.getUuidsForE164s(numbers);
|
||||
}
|
||||
|
||||
async getAvatar(path: string): Promise<any> {
|
||||
async getAvatar(path: string): Promise<ReturnType<WebAPIType['getAvatar']>> {
|
||||
return this.server.getAvatar(path);
|
||||
}
|
||||
|
||||
async getSticker(packId: string, stickerId: number): Promise<any> {
|
||||
async getSticker(
|
||||
packId: string,
|
||||
stickerId: number
|
||||
): Promise<ReturnType<WebAPIType['getSticker']>> {
|
||||
return this.server.getSticker(packId, stickerId);
|
||||
}
|
||||
|
||||
async getStickerPackManifest(packId: string): Promise<any> {
|
||||
async getStickerPackManifest(
|
||||
packId: string
|
||||
): Promise<ReturnType<WebAPIType['getStickerPackManifest']>> {
|
||||
return this.server.getStickerPackManifest(packId);
|
||||
}
|
||||
|
||||
|
@ -2184,7 +2232,7 @@ export default class MessageSender {
|
|||
async makeProxiedRequest(
|
||||
url: string,
|
||||
options?: Readonly<ProxiedRequestOptionsType>
|
||||
): Promise<any> {
|
||||
): Promise<ReturnType<WebAPIType['makeProxiedRequest']>> {
|
||||
return this.server.makeProxiedRequest(url, options);
|
||||
}
|
||||
|
||||
|
|
|
@ -678,7 +678,8 @@ export type ProfileType = Readonly<{
|
|||
username?: string;
|
||||
uuid?: string;
|
||||
credential?: string;
|
||||
capabilities?: unknown;
|
||||
capabilities?: CapabilitiesType;
|
||||
paymentAddress?: string;
|
||||
}>;
|
||||
|
||||
export type GetIceServersResultType = Readonly<{
|
||||
|
|
|
@ -52,6 +52,7 @@ export async function downloadAttachment(
|
|||
return {
|
||||
...omit(attachment, 'digest', 'key'),
|
||||
|
||||
size,
|
||||
contentType: contentType
|
||||
? MIME.stringToMIMEType(contentType)
|
||||
: MIME.APPLICATION_OCTET_STREAM,
|
||||
|
|
|
@ -42,7 +42,7 @@ export type AttachmentType = {
|
|||
isVoiceMessage?: boolean;
|
||||
/** For messages not already on disk, this will be a data url */
|
||||
url?: string;
|
||||
size?: number;
|
||||
size: number;
|
||||
fileSize?: string;
|
||||
pending?: boolean;
|
||||
width?: number;
|
||||
|
@ -95,6 +95,7 @@ export type InMemoryAttachmentDraftType =
|
|||
fileName: string;
|
||||
path: string;
|
||||
pending: true;
|
||||
size: number;
|
||||
};
|
||||
|
||||
export type AttachmentDraftType =
|
||||
|
@ -109,6 +110,7 @@ export type AttachmentDraftType =
|
|||
fileName: string;
|
||||
path: string;
|
||||
pending: true;
|
||||
size: number;
|
||||
};
|
||||
|
||||
export type ThumbnailType = {
|
||||
|
@ -621,7 +623,9 @@ export function isImage(attachments?: ReadonlyArray<AttachmentType>): boolean {
|
|||
);
|
||||
}
|
||||
|
||||
export function isImageAttachment(attachment?: AttachmentType): boolean {
|
||||
export function isImageAttachment(
|
||||
attachment?: Pick<AttachmentType, 'contentType'>
|
||||
): boolean {
|
||||
return Boolean(
|
||||
attachment &&
|
||||
attachment.contentType &&
|
||||
|
@ -630,8 +634,8 @@ export function isImageAttachment(attachment?: AttachmentType): boolean {
|
|||
}
|
||||
|
||||
export function canBeTranscoded(
|
||||
attachment?: AttachmentType
|
||||
): attachment is AttachmentType {
|
||||
attachment?: Pick<AttachmentType, 'contentType'>
|
||||
): boolean {
|
||||
return Boolean(
|
||||
attachment &&
|
||||
isImageAttachment(attachment) &&
|
||||
|
|
|
@ -6,6 +6,9 @@ export type MIMEType = string & { _mimeTypeBrand: never };
|
|||
export const stringToMIMEType = (value: string): MIMEType => {
|
||||
return value as MIMEType;
|
||||
};
|
||||
export const MIMETypeToString = (value: MIMEType): string => {
|
||||
return value as string;
|
||||
};
|
||||
|
||||
export const APPLICATION_OCTET_STREAM = stringToMIMEType(
|
||||
'application/octet-stream'
|
||||
|
|
|
@ -11,6 +11,9 @@ import { makeLookup } from '../util/makeLookup';
|
|||
import { maybeParseUrl } from '../util/url';
|
||||
import * as Bytes from '../Bytes';
|
||||
import { deriveStickerPackKey, decryptAttachment } from '../Crypto';
|
||||
import { IMAGE_WEBP, MIMEType } from './MIME';
|
||||
import { sniffImageMimeType } from '../util/sniffImageMimeType';
|
||||
import type { AttachmentType } from './Attachment';
|
||||
import type {
|
||||
StickerType,
|
||||
StickerPackType,
|
||||
|
@ -749,21 +752,41 @@ export function getSticker(
|
|||
export async function copyStickerToAttachments(
|
||||
packId: string,
|
||||
stickerId: number
|
||||
): Promise<StickerType | undefined> {
|
||||
): Promise<AttachmentType> {
|
||||
const sticker = getSticker(packId, stickerId);
|
||||
if (!sticker) {
|
||||
return undefined;
|
||||
throw new Error(
|
||||
`copyStickerToAttachments: Failed to find sticker ${packId}/${stickerId}`
|
||||
);
|
||||
}
|
||||
|
||||
const { path } = sticker;
|
||||
const absolutePath = window.Signal.Migrations.getAbsoluteStickerPath(path);
|
||||
const newPath = await window.Signal.Migrations.copyIntoAttachmentsDirectory(
|
||||
absolutePath
|
||||
const { path: stickerPath } = sticker;
|
||||
const absolutePath = window.Signal.Migrations.getAbsoluteStickerPath(
|
||||
stickerPath
|
||||
);
|
||||
const {
|
||||
path,
|
||||
size,
|
||||
} = await window.Signal.Migrations.copyIntoAttachmentsDirectory(absolutePath);
|
||||
|
||||
const data = window.Signal.Migrations.loadAttachmentData(path);
|
||||
|
||||
let contentType: MIMEType;
|
||||
const sniffedMimeType = sniffImageMimeType(data);
|
||||
if (sniffedMimeType) {
|
||||
contentType = sniffedMimeType;
|
||||
} else {
|
||||
log.warn(
|
||||
'copyStickerToAttachments: Unable to sniff sticker MIME type; falling back to WebP'
|
||||
);
|
||||
contentType = IMAGE_WEBP;
|
||||
}
|
||||
|
||||
return {
|
||||
...sticker,
|
||||
path: newPath,
|
||||
contentType,
|
||||
path,
|
||||
size,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,6 @@ export type LinkPreviewType = {
|
|||
domain: string;
|
||||
url: string;
|
||||
isStickerPack: boolean;
|
||||
image?: AttachmentType;
|
||||
image?: Readonly<AttachmentType>;
|
||||
date?: number;
|
||||
};
|
||||
|
|
|
@ -114,19 +114,21 @@ export async function getProfile(
|
|||
});
|
||||
}
|
||||
|
||||
const identityKey = Bytes.fromBase64(profile.identityKey);
|
||||
const changed = await window.textsecure.storage.protocol.saveIdentity(
|
||||
new Address(targetUuid, 1),
|
||||
identityKey,
|
||||
false
|
||||
);
|
||||
if (changed) {
|
||||
// save identity will close all sessions except for .1, so we
|
||||
// must close that one manually.
|
||||
const ourUuid = window.textsecure.storage.user.getCheckedUuid();
|
||||
await window.textsecure.storage.protocol.archiveSession(
|
||||
new QualifiedAddress(ourUuid, new Address(targetUuid, 1))
|
||||
if (profile.identityKey) {
|
||||
const identityKey = Bytes.fromBase64(profile.identityKey);
|
||||
const changed = await window.textsecure.storage.protocol.saveIdentity(
|
||||
new Address(targetUuid, 1),
|
||||
identityKey,
|
||||
false
|
||||
);
|
||||
if (changed) {
|
||||
// save identity will close all sessions except for .1, so we
|
||||
// must close that one manually.
|
||||
const ourUuid = window.textsecure.storage.user.getCheckedUuid();
|
||||
await window.textsecure.storage.protocol.archiveSession(
|
||||
new QualifiedAddress(ourUuid, new Address(targetUuid, 1))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const accessKey = c.get('accessKey');
|
||||
|
@ -238,15 +240,22 @@ export async function getProfile(
|
|||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await c.setEncryptedProfileName(profile.name);
|
||||
} catch (error) {
|
||||
log.warn(
|
||||
'getProfile decryption failure:',
|
||||
c.idForLogging(),
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
await c.set({
|
||||
if (profile.name) {
|
||||
try {
|
||||
await c.setEncryptedProfileName(profile.name);
|
||||
} catch (error) {
|
||||
log.warn(
|
||||
'getProfile decryption failure:',
|
||||
c.idForLogging(),
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
await c.set({
|
||||
profileName: undefined,
|
||||
profileFamilyName: undefined,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
c.set({
|
||||
profileName: undefined,
|
||||
profileFamilyName: undefined,
|
||||
});
|
||||
|
|
|
@ -25,6 +25,7 @@ export function getPendingAttachment(file: File): AttachmentType | undefined {
|
|||
return {
|
||||
contentType: fileType,
|
||||
fileName,
|
||||
size: file.size,
|
||||
path: file.name,
|
||||
pending: true,
|
||||
};
|
||||
|
|
|
@ -20,6 +20,7 @@ import {
|
|||
MIMEType,
|
||||
stringToMIMEType,
|
||||
} from '../types/MIME';
|
||||
import { sniffImageMimeType } from '../util/sniffImageMimeType';
|
||||
import { ConversationModel } from '../models/conversations';
|
||||
import {
|
||||
GroupV2PendingMemberType,
|
||||
|
@ -3499,6 +3500,17 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
|
|||
return null;
|
||||
}
|
||||
|
||||
let contentType: MIMEType;
|
||||
const sniffedMimeType = sniffImageMimeType(data);
|
||||
if (sniffedMimeType) {
|
||||
contentType = sniffedMimeType;
|
||||
} else {
|
||||
log.warn(
|
||||
'getStickerPackPreview: Unable to sniff sticker MIME type; falling back to WebP'
|
||||
);
|
||||
contentType = IMAGE_WEBP;
|
||||
}
|
||||
|
||||
return {
|
||||
date: null,
|
||||
description: null,
|
||||
|
@ -3506,7 +3518,7 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
|
|||
...sticker,
|
||||
data,
|
||||
size: data.byteLength,
|
||||
contentType: IMAGE_WEBP,
|
||||
contentType,
|
||||
},
|
||||
title,
|
||||
url,
|
||||
|
|
|
@ -329,7 +329,9 @@ declare global {
|
|||
width: number;
|
||||
height: number;
|
||||
};
|
||||
copyIntoAttachmentsDirectory: (path: string) => Promise<string>;
|
||||
copyIntoAttachmentsDirectory: (
|
||||
path: string
|
||||
) => Promise<{ path: string; size: number }>;
|
||||
upgradeMessageSchema: (attributes: unknown) => WhatIsThis;
|
||||
processNewAttachment: (
|
||||
attachment: DownloadedAttachmentType
|
||||
|
|
Loading…
Reference in New Issue