Implement Attachment.save
This commit is contained in:
parent
3727205606
commit
4a5e61eaf4
2 changed files with 116 additions and 0 deletions
60
ts/test/types/Attachment_test.ts
Normal file
60
ts/test/types/Attachment_test.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* @prettier
|
||||
*/
|
||||
import 'mocha';
|
||||
import { assert } from 'chai';
|
||||
|
||||
import * as Attachment from '../../types/Attachment';
|
||||
import { MIMEType } from '../../types/MIME';
|
||||
// @ts-ignore
|
||||
import { stringToArrayBuffer } from '../../../js/modules/string_to_array_buffer';
|
||||
|
||||
describe('Attachment', () => {
|
||||
describe('getFileExtension', () => {
|
||||
it('should return file extension from content type', () => {
|
||||
const input: Attachment.Attachment = {
|
||||
data: stringToArrayBuffer('foo'),
|
||||
contentType: 'image/gif' as MIMEType,
|
||||
};
|
||||
assert.strictEqual(Attachment.getFileExtension(input), 'gif');
|
||||
});
|
||||
|
||||
it('should return file extension for QuickTime videos', () => {
|
||||
const input: Attachment.Attachment = {
|
||||
data: stringToArrayBuffer('foo'),
|
||||
contentType: 'video/quicktime' as MIMEType,
|
||||
};
|
||||
assert.strictEqual(Attachment.getFileExtension(input), 'mov');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSuggestedFilename', () => {
|
||||
context('for attachment with filename', () => {
|
||||
it('should return existing filename if present', () => {
|
||||
const attachment: Attachment.Attachment = {
|
||||
fileName: 'funny-cat.mov',
|
||||
data: stringToArrayBuffer('foo'),
|
||||
contentType: 'video/quicktime' as MIMEType,
|
||||
};
|
||||
const actual = Attachment.getSuggestedFilename({ attachment });
|
||||
const expected = 'funny-cat.mov';
|
||||
assert.strictEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
context('for attachment without filename', () => {
|
||||
it('should generate a filename based on timestamp', () => {
|
||||
const attachment: Attachment.Attachment = {
|
||||
data: stringToArrayBuffer('foo'),
|
||||
contentType: 'video/quicktime' as MIMEType,
|
||||
};
|
||||
const timestamp = new Date(new Date(0).getTimezoneOffset() * 60 * 1000);
|
||||
const actual = Attachment.getSuggestedFilename({
|
||||
attachment,
|
||||
timestamp,
|
||||
});
|
||||
const expected = 'signal-attachment-1970-01-01-000000.mov';
|
||||
assert.strictEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -2,8 +2,10 @@
|
|||
* @prettier
|
||||
*/
|
||||
import is from '@sindresorhus/is';
|
||||
import moment from 'moment';
|
||||
|
||||
import * as GoogleChrome from '../util/GoogleChrome';
|
||||
import { arrayBufferToObjectURL } from '../util/arrayBufferToObjectURL';
|
||||
import { MIMEType } from './MIME';
|
||||
|
||||
export interface Attachment {
|
||||
|
@ -23,6 +25,8 @@ export interface Attachment {
|
|||
// flags?: number;
|
||||
}
|
||||
|
||||
const SAVE_CONTENT_TYPE = 'application/octet-stream' as MIMEType;
|
||||
|
||||
export const isVisualMedia = (attachment: Attachment): boolean => {
|
||||
const { contentType } = attachment;
|
||||
|
||||
|
@ -34,3 +38,55 @@ export const isVisualMedia = (attachment: Attachment): boolean => {
|
|||
const isSupportedVideoType = GoogleChrome.isVideoTypeSupported(contentType);
|
||||
return isSupportedImageType || isSupportedVideoType;
|
||||
};
|
||||
|
||||
export const save = ({
|
||||
attachment,
|
||||
timestamp,
|
||||
}: {
|
||||
attachment: Attachment;
|
||||
timestamp?: number;
|
||||
}): void => {
|
||||
const url = arrayBufferToObjectURL({
|
||||
data: attachment.data,
|
||||
type: SAVE_CONTENT_TYPE,
|
||||
});
|
||||
const anchorElement = document.createElement('a');
|
||||
anchorElement.href = url;
|
||||
anchorElement.download = getSuggestedFilename({ attachment, timestamp });
|
||||
anchorElement.click();
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
|
||||
export const getSuggestedFilename = ({
|
||||
attachment,
|
||||
timestamp,
|
||||
}: {
|
||||
attachment: Attachment;
|
||||
timestamp?: number | Date;
|
||||
}): string => {
|
||||
if (attachment.fileName) {
|
||||
return attachment.fileName;
|
||||
}
|
||||
|
||||
const prefix = 'signal-attachment';
|
||||
const suffix = timestamp
|
||||
? moment(timestamp).format('-YYYY-MM-DD-HHmmss')
|
||||
: '';
|
||||
const fileType = getFileExtension(attachment);
|
||||
const extension = fileType ? `.${fileType}` : '';
|
||||
return `${prefix}${suffix}${extension}`;
|
||||
};
|
||||
|
||||
export const getFileExtension = (attachment: Attachment): string | null => {
|
||||
if (!attachment.contentType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (attachment.contentType) {
|
||||
case 'video/quicktime':
|
||||
return 'mov';
|
||||
default:
|
||||
// TODO: Use better MIME --> file extension mapping:
|
||||
return attachment.contentType.split('/')[1];
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue