Display attachments from disk
This commit is contained in:
parent
407c77395b
commit
e1b620602d
6 changed files with 70 additions and 35 deletions
|
@ -180,6 +180,7 @@
|
|||
Signal.Types.AttachmentTS.save({
|
||||
attachment: this.model,
|
||||
document,
|
||||
getAbsolutePath: Signal.Migrations.getAbsoluteAttachmentPath,
|
||||
timestamp: this.timestamp,
|
||||
});
|
||||
},
|
||||
|
|
|
@ -282,8 +282,8 @@
|
|||
if (this.quoteView) {
|
||||
this.quoteView.remove();
|
||||
}
|
||||
if (this.lightboxView) {
|
||||
this.lightboxView.remove();
|
||||
if (this.lightboxGalleryView) {
|
||||
this.lightboxGalleryView.remove();
|
||||
}
|
||||
if (this.panels && this.panels.length) {
|
||||
for (let i = 0, max = this.panels.length; i < max; i += 1) {
|
||||
|
@ -598,6 +598,7 @@
|
|||
WhisperMessageCollection,
|
||||
});
|
||||
|
||||
// NOTE: Could we show grid previews from disk as well?
|
||||
const loadMessages = Signal.Components.Types.Message
|
||||
.loadWithObjectURL(Signal.Migrations.loadMessage);
|
||||
const media = await loadMessages(rawMedia);
|
||||
|
@ -605,30 +606,36 @@
|
|||
const saveAttachment = async ({ message } = {}) => {
|
||||
const attachment = message.attachments[0];
|
||||
const timestamp = message.received_at;
|
||||
Signal.Types.AttachmentTS.save({ attachment, timestamp });
|
||||
Signal.Types.AttachmentTS.save({
|
||||
attachment,
|
||||
document,
|
||||
getAbsolutePath: Signal.Migrations.getAbsoluteAttachmentPath,
|
||||
timestamp,
|
||||
});
|
||||
};
|
||||
|
||||
const onItemClick = async ({ message, type }) => {
|
||||
const loadedMessage = Signal.Components.Types.Message
|
||||
.withObjectURL(await Signal.Migrations.loadMessage(message));
|
||||
switch (type) {
|
||||
case 'documents': {
|
||||
saveAttachment({ message: loadedMessage });
|
||||
saveAttachment({ message });
|
||||
break;
|
||||
}
|
||||
|
||||
case 'media': {
|
||||
const attachment = loadedMessage.attachments[0];
|
||||
this.lightboxView = new Whisper.ReactWrapperView({
|
||||
Component: Signal.Components.Lightbox,
|
||||
const selectedIndex = media.findIndex(mediaMessage =>
|
||||
mediaMessage.id === message.id);
|
||||
const { getAbsoluteAttachmentPath } = Signal.Migrations;
|
||||
this.lightboxGalleryView = new Whisper.ReactWrapperView({
|
||||
Component: Signal.Components.LightboxGallery,
|
||||
props: {
|
||||
objectURL: loadedMessage.objectURL,
|
||||
contentType: attachment.contentType,
|
||||
onSave: () => saveAttachment({ message: loadedMessage }),
|
||||
getAbsoluteAttachmentPath,
|
||||
messages: media,
|
||||
onSave: () => saveAttachment({ message }),
|
||||
selectedIndex,
|
||||
},
|
||||
onClose: () => Signal.Backbone.Views.Lightbox.hide(),
|
||||
});
|
||||
Signal.Backbone.Views.Lightbox.show(this.lightboxView.el);
|
||||
Signal.Backbone.Views.Lightbox.show(this.lightboxGalleryView.el);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -166,6 +166,7 @@ window.Signal.Logs = require('./js/modules/logs');
|
|||
|
||||
// React components
|
||||
const { Lightbox } = require('./ts/components/Lightbox');
|
||||
const { LightboxGallery } = require('./ts/components/LightboxGallery');
|
||||
const { MediaGallery } =
|
||||
require('./ts/components/conversation/media-gallery/MediaGallery');
|
||||
const { Quote } = require('./ts/components/conversation/Quote');
|
||||
|
@ -175,6 +176,7 @@ const MediaGalleryMessage =
|
|||
|
||||
window.Signal.Components = {
|
||||
Lightbox,
|
||||
LightboxGallery,
|
||||
MediaGallery,
|
||||
Types: {
|
||||
Message: MediaGalleryMessage,
|
||||
|
|
|
@ -117,7 +117,7 @@ export class Lightbox extends React.Component<Props, {}> {
|
|||
}
|
||||
|
||||
public render() {
|
||||
const { contentType, objectURL } = this.props;
|
||||
const { contentType, objectURL, onNext, onPrevious, onSave } = this.props;
|
||||
return (
|
||||
<div
|
||||
style={styles.container}
|
||||
|
@ -132,23 +132,23 @@ export class Lightbox extends React.Component<Props, {}> {
|
|||
</div>
|
||||
<div style={styles.controls}>
|
||||
<IconButton type="close" onClick={this.onClose} />
|
||||
{this.props.onSave ? (
|
||||
{onSave ? (
|
||||
<IconButton
|
||||
type="save"
|
||||
onClick={this.props.onSave}
|
||||
onClick={onSave}
|
||||
style={styles.saveButton}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div style={styles.navigationContainer}>
|
||||
{this.props.onPrevious ? (
|
||||
<IconButton type="previous" onClick={this.props.onPrevious} />
|
||||
{onPrevious ? (
|
||||
<IconButton type="previous" onClick={onPrevious} />
|
||||
) : (
|
||||
<IconButtonPlaceholder />
|
||||
)}
|
||||
{this.props.onNext ? (
|
||||
<IconButton type="next" onClick={this.props.onNext} />
|
||||
{onNext ? (
|
||||
<IconButton type="next" onClick={onNext} />
|
||||
) : (
|
||||
<IconButtonPlaceholder />
|
||||
)}
|
||||
|
|
|
@ -5,18 +5,18 @@ import React from 'react';
|
|||
|
||||
import * as MIME from '../types/MIME';
|
||||
import { Lightbox } from './Lightbox';
|
||||
import { Message } from './conversation/media-gallery/types/Message';
|
||||
|
||||
interface Item {
|
||||
objectURL: string;
|
||||
objectURL?: string;
|
||||
contentType: MIME.MIMEType | undefined;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
close: () => void;
|
||||
items: Array<Item>;
|
||||
// onNext?: () => void;
|
||||
// onPrevious?: () => void;
|
||||
onSave?: () => void;
|
||||
getAbsoluteAttachmentPath: (relativePath: string) => string;
|
||||
messages: Array<Message>;
|
||||
onSave?: ({ message }: { message: Message }) => void;
|
||||
selectedIndex: number;
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,11 @@ interface State {
|
|||
selectedIndex: number;
|
||||
}
|
||||
|
||||
const messageToItem = (message: Message): Item => ({
|
||||
objectURL: message.attachments[0].path,
|
||||
contentType: message.attachments[0].contentType,
|
||||
});
|
||||
|
||||
export class LightboxGallery extends React.Component<Props, State> {
|
||||
public static defaultProps: Partial<Props> = {
|
||||
selectedIndex: 0,
|
||||
|
@ -38,25 +43,30 @@ export class LightboxGallery extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
public render() {
|
||||
const { close, items, onSave } = this.props;
|
||||
const { close, getAbsoluteAttachmentPath, messages, onSave } = this.props;
|
||||
const { selectedIndex } = this.state;
|
||||
|
||||
const selectedItem: Item = items[selectedIndex];
|
||||
const selectedMessage: Message = messages[selectedIndex];
|
||||
const selectedItem = messageToItem(selectedMessage);
|
||||
|
||||
const firstIndex = 0;
|
||||
const onPrevious =
|
||||
selectedIndex > firstIndex ? this.handlePrevious : undefined;
|
||||
|
||||
const lastIndex = items.length - 1;
|
||||
const lastIndex = messages.length - 1;
|
||||
const onNext = selectedIndex < lastIndex ? this.handleNext : undefined;
|
||||
|
||||
const objectURL = selectedItem.objectURL
|
||||
? getAbsoluteAttachmentPath(selectedItem.objectURL)
|
||||
: 'images/video.svg';
|
||||
|
||||
return (
|
||||
<Lightbox
|
||||
close={close}
|
||||
onPrevious={onPrevious}
|
||||
onNext={onNext}
|
||||
onSave={onSave}
|
||||
objectURL={selectedItem.objectURL}
|
||||
onSave={onSave ? this.handleSave : undefined}
|
||||
objectURL={objectURL}
|
||||
contentType={selectedItem.contentType}
|
||||
/>
|
||||
);
|
||||
|
@ -72,8 +82,19 @@ export class LightboxGallery extends React.Component<Props, State> {
|
|||
this.setState((prevState, props) => ({
|
||||
selectedIndex: Math.min(
|
||||
prevState.selectedIndex + 1,
|
||||
props.items.length - 1
|
||||
props.messages.length - 1
|
||||
),
|
||||
}));
|
||||
};
|
||||
|
||||
private handleSave = () => {
|
||||
const { messages, onSave } = this.props;
|
||||
if (!onSave) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { selectedIndex } = this.state;
|
||||
const message = messages[selectedIndex];
|
||||
onSave({ message });
|
||||
};
|
||||
}
|
||||
|
|
|
@ -47,16 +47,20 @@ export const isVisualMedia = (attachment: Attachment): boolean => {
|
|||
export const save = ({
|
||||
attachment,
|
||||
document,
|
||||
getAbsolutePath,
|
||||
timestamp,
|
||||
}: {
|
||||
attachment: Attachment;
|
||||
document: Document;
|
||||
getAbsolutePath: (relativePath: string) => string;
|
||||
timestamp?: number;
|
||||
}): void => {
|
||||
const url = arrayBufferToObjectURL({
|
||||
data: attachment.data,
|
||||
type: SAVE_CONTENT_TYPE,
|
||||
});
|
||||
const url = !is.undefined(attachment.path)
|
||||
? getAbsolutePath(attachment.path)
|
||||
: arrayBufferToObjectURL({
|
||||
data: attachment.data,
|
||||
type: SAVE_CONTENT_TYPE,
|
||||
});
|
||||
const filename = getSuggestedFilename({ attachment, timestamp });
|
||||
saveURLAsFile({ url, filename, document });
|
||||
URL.revokeObjectURL(url);
|
||||
|
|
Loading…
Add table
Reference in a new issue