diff --git a/js/views/attachment_view.js b/js/views/attachment_view.js
index c19e4ebf44..84d7fab35e 100644
--- a/js/views/attachment_view.js
+++ b/js/views/attachment_view.js
@@ -109,7 +109,8 @@
}
const props = {
- imageURL: this.objectUrl,
+ objectURL: this.objectUrl,
+ contentType: this.model.contentType,
onSave: () => this.saveFile(),
// implicit: `close`
};
diff --git a/js/views/conversation_view.js b/js/views/conversation_view.js
index 956a9ede16..aa5c738ec5 100644
--- a/js/views/conversation_view.js
+++ b/js/views/conversation_view.js
@@ -600,25 +600,28 @@
const media = await loadMessages(rawMedia);
const saveAttachment = async ({ message } = {}) => {
- const loadedMessage = await Signal.Migrations.loadMessage(message);
- const attachment = loadedMessage.attachments[0];
- const timestamp = loadedMessage.received_at;
+ const attachment = message.attachments[0];
+ const timestamp = message.received_at;
Signal.Types.AttachmentTS.save({ attachment, timestamp });
};
const onItemClick = async ({ message, type }) => {
+ const loadedMessage = Signal.Components.Types.Message
+ .withObjectURL(await Signal.Migrations.loadMessage(message));
switch (type) {
case 'documents': {
- saveAttachment({ message });
+ saveAttachment({ message: loadedMessage });
break;
}
case 'media': {
+ const attachment = loadedMessage.attachments[0];
this.lightboxView = new Whisper.ReactWrapperView({
Component: Signal.Components.Lightbox,
props: {
- imageURL: message.objectURL,
- onSave: () => saveAttachment({ message }),
+ objectURL: loadedMessage.objectURL,
+ contentType: attachment.contentType,
+ onSave: () => saveAttachment({ message: loadedMessage }),
},
onClose: () => Signal.Backbone.Views.Lightbox.hide(),
});
diff --git a/ts/components/Lightbox.md b/ts/components/Lightbox.md
index a5fbd148e6..4bc11546d2 100644
--- a/ts/components/Lightbox.md
+++ b/ts/components/Lightbox.md
@@ -3,7 +3,8 @@ const noop = () => {};
void;
- imageURL?: string;
+ objectURL: string;
+ contentType: MIME.MIMEType | undefined;
onNext?: () => void;
onPrevious?: () => void;
- onSave: () => void;
+ onSave?: () => void;
}
const styles = {
@@ -67,7 +72,7 @@ export class Lightbox extends React.Component {
}
public render() {
- const { imageURL } = this.props;
+ const { contentType, objectURL } = this.props;
return (
{
ref={this.setContainerRef}
>
-

+ {!is.undefined(contentType)
+ ? this.renderObject({ objectURL, contentType })
+ : null}
@@ -97,6 +100,38 @@ export class Lightbox extends React.Component
{
);
}
+ private renderObject = ({
+ objectURL,
+ contentType,
+ }: {
+ objectURL: string;
+ contentType: MIME.MIMEType;
+ }) => {
+ const isImage = GoogleChrome.isImageTypeSupported(contentType);
+ if (isImage) {
+ return (
+
+ );
+ }
+
+ const isVideo = GoogleChrome.isVideoTypeSupported(contentType);
+ if (isVideo) {
+ return (
+
+ );
+ }
+
+ // tslint:disable-next-line no-console
+ console.log('Lightbox: Unexpected content type', { contentType });
+ return null;
+ };
+
private setContainerRef = (value: HTMLDivElement) => {
this.containerRef = value;
};
@@ -125,7 +160,7 @@ export class Lightbox extends React.Component {
this.onClose();
};
- private onImageClick = (event: React.MouseEvent) => {
+ private onObjectClick = (event: React.MouseEvent) => {
event.stopPropagation();
this.onClose();
};
diff --git a/ts/components/conversation/media-gallery/types/Message.tsx b/ts/components/conversation/media-gallery/types/Message.tsx
index 73431ec59a..4b47504bd7 100644
--- a/ts/components/conversation/media-gallery/types/Message.tsx
+++ b/ts/components/conversation/media-gallery/types/Message.tsx
@@ -8,7 +8,6 @@ import * as MIME from '../../../../types/MIME';
import { arrayBufferToObjectURL } from '../../../../util/arrayBufferToObjectURL';
import { Attachment } from '../../../../types/Attachment';
import { MapAsync } from '../../../../types/MapAsync';
-import { MIMEType } from '../../../../types/MIME';
export type Message = {
id: string;
@@ -16,8 +15,6 @@ export type Message = {
received_at: number;
} & { objectURL?: string };
-const DEFAULT_CONTENT_TYPE: MIMEType = 'application/octet-stream' as MIMEType;
-
export const loadWithObjectURL = (loadMessage: MapAsync) => async (
messages: Array
): Promise> => {
@@ -51,17 +48,17 @@ const hasVideoAttachment = (message: Message): boolean =>
MIME.isVideo(attachment.contentType)
);
-const withObjectURL = (message: Message): Message => {
+export 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') {
+ if (is.undefined(attachment.contentType)) {
throw new TypeError('`attachment.contentType` is required');
}
- if (MIME.isVideo(attachment.contentType)) {
+ if (is.undefined(attachment.data) && MIME.isVideo(attachment.contentType)) {
return {
...message,
objectURL: 'images/video.svg',
@@ -70,7 +67,7 @@ const withObjectURL = (message: Message): Message => {
const objectURL = arrayBufferToObjectURL({
data: attachment.data,
- type: attachment.contentType || DEFAULT_CONTENT_TYPE,
+ type: attachment.contentType,
});
return {
...message,