Skip loading videos into memory for performance

This commit is contained in:
Daniel Gasienica 2018-04-14 21:09:02 -04:00
parent c6904476f4
commit 5d0469adef

View file

@ -2,7 +2,9 @@
* @prettier
*/
import is from '@sindresorhus/is';
import { partition, sortBy } from 'lodash';
import * as MIME from '../../../../types/MIME';
import { arrayBufferToObjectURL } from '../../../../util/arrayBufferToObjectURL';
import { Attachment } from '../../../../types/Attachment';
import { MapAsync } from '../../../../types/MapAsync';
@ -16,24 +18,55 @@ export type Message = {
const DEFAULT_CONTENT_TYPE: MIMEType = 'application/octet-stream' as MIMEType;
export const loadWithObjectURL = (loadMessage: MapAsync<Message>) => async (
media: Array<Message>
messages: Array<Message>
): Promise<Array<Message>> => {
if (!is.function_(loadMessage)) {
throw new TypeError("'loadMessage' must be a function");
}
if (!is.array(media)) {
throw new TypeError("'media' must be a function");
if (!is.array(messages)) {
throw new TypeError("'messages' must be an array");
}
const mediaWithAttachmentData = await Promise.all(media.map(loadMessage));
return mediaWithAttachmentData.map(withObjectURL);
// Messages with video are too expensive to load into memory, so we dont:
const [messagesWithVideo, messagesWithoutVideo] = partition(
messages,
hasVideoAttachment
);
const loadedMessagesWithoutVideo = await Promise.all(
messagesWithoutVideo.map(loadMessage)
);
const loadedMessages = sortBy(
[...messagesWithVideo, ...loadedMessagesWithoutVideo],
message => -message.received_at
);
return loadedMessages.map(withObjectURL);
};
const hasVideoAttachment = (message: Message): boolean =>
message.attachments.some(
attachment =>
!is.undefined(attachment.contentType) &&
MIME.isVideo(attachment.contentType)
);
const withObjectURL = (message: Message): Message => {
if (message.attachments.length === 0) {
throw new TypeError('`message.attachments` cannot be empty');
}
const attachment = message.attachments[0];
if (typeof attachment.contentType === 'undefined') {
throw new TypeError('`attachment.contentType` is required');
}
if (MIME.isVideo(attachment.contentType)) {
return {
...message,
objectURL: 'images/video.svg',
};
}
const objectURL = arrayBufferToObjectURL({
data: attachment.data,
type: attachment.contentType || DEFAULT_CONTENT_TYPE,