View All Media: Listen for updates to conversation, re-render
This commit is contained in:
parent
d4eacda649
commit
9afea3ae2b
1 changed files with 125 additions and 106 deletions
|
@ -767,125 +767,141 @@
|
||||||
const DEFAULT_DOCUMENTS_FETCH_COUNT = 150;
|
const DEFAULT_DOCUMENTS_FETCH_COUNT = 150;
|
||||||
|
|
||||||
const conversationId = this.model.get('id');
|
const conversationId = this.model.get('id');
|
||||||
const rawMedia = await Signal.Data.getMessagesWithVisualMediaAttachments(
|
|
||||||
conversationId,
|
|
||||||
{
|
|
||||||
limit: DEFAULT_MEDIA_FETCH_COUNT,
|
|
||||||
MessageCollection: Whisper.MessageCollection,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const rawDocuments = await Signal.Data.getMessagesWithFileAttachments(
|
|
||||||
conversationId,
|
|
||||||
{
|
|
||||||
limit: DEFAULT_DOCUMENTS_FETCH_COUNT,
|
|
||||||
MessageCollection: Whisper.MessageCollection,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// First we upgrade these messages to ensure that they have thumbnails
|
const getProps = async () => {
|
||||||
for (let max = rawMedia.length, i = 0; i < max; i += 1) {
|
const rawMedia = await Signal.Data.getMessagesWithVisualMediaAttachments(
|
||||||
const message = rawMedia[i];
|
conversationId,
|
||||||
const { schemaVersion } = message;
|
{
|
||||||
|
limit: DEFAULT_MEDIA_FETCH_COUNT,
|
||||||
|
MessageCollection: Whisper.MessageCollection,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const rawDocuments = await Signal.Data.getMessagesWithFileAttachments(
|
||||||
|
conversationId,
|
||||||
|
{
|
||||||
|
limit: DEFAULT_DOCUMENTS_FETCH_COUNT,
|
||||||
|
MessageCollection: Whisper.MessageCollection,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (schemaVersion < Message.VERSION_NEEDED_FOR_DISPLAY) {
|
// First we upgrade these messages to ensure that they have thumbnails
|
||||||
// Yep, we really do want to wait for each of these
|
for (let max = rawMedia.length, i = 0; i < max; i += 1) {
|
||||||
// eslint-disable-next-line no-await-in-loop
|
const message = rawMedia[i];
|
||||||
rawMedia[i] = await upgradeMessageSchema(message);
|
const { schemaVersion } = message;
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
await window.Signal.Data.saveMessage(rawMedia[i], {
|
|
||||||
Message: Whisper.Message,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const media = _.flatten(
|
if (schemaVersion < Message.VERSION_NEEDED_FOR_DISPLAY) {
|
||||||
rawMedia.map(message => {
|
// Yep, we really do want to wait for each of these
|
||||||
const { attachments } = message;
|
// eslint-disable-next-line no-await-in-loop
|
||||||
return (attachments || [])
|
rawMedia[i] = await upgradeMessageSchema(message);
|
||||||
.filter(
|
// eslint-disable-next-line no-await-in-loop
|
||||||
attachment =>
|
await window.Signal.Data.saveMessage(rawMedia[i], {
|
||||||
attachment.thumbnail && !attachment.pending && !attachment.error
|
Message: Whisper.Message,
|
||||||
)
|
|
||||||
.map((attachment, index) => {
|
|
||||||
const { thumbnail } = attachment;
|
|
||||||
|
|
||||||
return {
|
|
||||||
objectURL: getAbsoluteAttachmentPath(attachment.path),
|
|
||||||
thumbnailObjectUrl: thumbnail
|
|
||||||
? getAbsoluteAttachmentPath(thumbnail.path)
|
|
||||||
: null,
|
|
||||||
contentType: attachment.contentType,
|
|
||||||
index,
|
|
||||||
attachment,
|
|
||||||
message,
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
})
|
}
|
||||||
);
|
}
|
||||||
|
|
||||||
// Unlike visual media, only one non-image attachment is supported
|
const media = _.flatten(
|
||||||
const documents = rawDocuments.map(message => {
|
rawMedia.map(message => {
|
||||||
const attachments = message.attachments || [];
|
const { attachments } = message;
|
||||||
const attachment = attachments[0];
|
return (attachments || [])
|
||||||
return {
|
.filter(
|
||||||
contentType: attachment.contentType,
|
attachment =>
|
||||||
index: 0,
|
attachment.thumbnail &&
|
||||||
attachment,
|
!attachment.pending &&
|
||||||
message,
|
!attachment.error
|
||||||
};
|
)
|
||||||
});
|
.map((attachment, index) => {
|
||||||
|
const { thumbnail } = attachment;
|
||||||
|
|
||||||
const saveAttachment = async ({ attachment, message } = {}) => {
|
return {
|
||||||
const timestamp = message.received_at;
|
objectURL: getAbsoluteAttachmentPath(attachment.path),
|
||||||
Signal.Types.Attachment.save({
|
thumbnailObjectUrl: thumbnail
|
||||||
attachment,
|
? getAbsoluteAttachmentPath(thumbnail.path)
|
||||||
document,
|
: null,
|
||||||
getAbsolutePath: getAbsoluteAttachmentPath,
|
contentType: attachment.contentType,
|
||||||
timestamp,
|
index,
|
||||||
|
attachment,
|
||||||
|
message,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Unlike visual media, only one non-image attachment is supported
|
||||||
|
const documents = rawDocuments.map(message => {
|
||||||
|
const attachments = message.attachments || [];
|
||||||
|
const attachment = attachments[0];
|
||||||
|
return {
|
||||||
|
contentType: attachment.contentType,
|
||||||
|
index: 0,
|
||||||
|
attachment,
|
||||||
|
message,
|
||||||
|
};
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
const onItemClick = async ({ message, attachment, type }) => {
|
const saveAttachment = async ({ attachment, message } = {}) => {
|
||||||
switch (type) {
|
const timestamp = message.received_at;
|
||||||
case 'documents': {
|
Signal.Types.Attachment.save({
|
||||||
saveAttachment({ message, attachment });
|
attachment,
|
||||||
break;
|
document,
|
||||||
|
getAbsolutePath: getAbsoluteAttachmentPath,
|
||||||
|
timestamp,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onItemClick = async ({ message, attachment, type }) => {
|
||||||
|
switch (type) {
|
||||||
|
case 'documents': {
|
||||||
|
saveAttachment({ message, attachment });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'media': {
|
||||||
|
const selectedIndex = media.findIndex(
|
||||||
|
mediaMessage => mediaMessage.attachment.path === attachment.path
|
||||||
|
);
|
||||||
|
this.lightboxGalleryView = new Whisper.ReactWrapperView({
|
||||||
|
className: 'lightbox-wrapper',
|
||||||
|
Component: Signal.Components.LightboxGallery,
|
||||||
|
props: {
|
||||||
|
media,
|
||||||
|
onSave: saveAttachment,
|
||||||
|
selectedIndex,
|
||||||
|
},
|
||||||
|
onClose: () => Signal.Backbone.Views.Lightbox.hide(),
|
||||||
|
});
|
||||||
|
Signal.Backbone.Views.Lightbox.show(this.lightboxGalleryView.el);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new TypeError(`Unknown attachment type: '${type}'`);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
case 'media': {
|
return {
|
||||||
const selectedIndex = media.findIndex(
|
documents,
|
||||||
mediaMessage => mediaMessage.attachment.path === attachment.path
|
media,
|
||||||
);
|
onItemClick,
|
||||||
this.lightboxGalleryView = new Whisper.ReactWrapperView({
|
};
|
||||||
className: 'lightbox-wrapper',
|
|
||||||
Component: Signal.Components.LightboxGallery,
|
|
||||||
props: {
|
|
||||||
media,
|
|
||||||
onSave: saveAttachment,
|
|
||||||
selectedIndex,
|
|
||||||
},
|
|
||||||
onClose: () => Signal.Backbone.Views.Lightbox.hide(),
|
|
||||||
});
|
|
||||||
Signal.Backbone.Views.Lightbox.show(this.lightboxGalleryView.el);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new TypeError(`Unknown attachment type: '${type}'`);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const view = new Whisper.ReactWrapperView({
|
const view = new Whisper.ReactWrapperView({
|
||||||
className: 'panel-wrapper',
|
className: 'panel-wrapper',
|
||||||
Component: Signal.Components.MediaGallery,
|
Component: Signal.Components.MediaGallery,
|
||||||
props: {
|
props: await getProps(),
|
||||||
documents,
|
onClose: () => {
|
||||||
media,
|
this.stopListening(this.model.messageCollection, 'remove', update);
|
||||||
onItemClick,
|
this.resetPanel();
|
||||||
},
|
},
|
||||||
onClose: () => this.resetPanel(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const update = async () => {
|
||||||
|
view.update(await getProps());
|
||||||
|
};
|
||||||
|
|
||||||
|
this.listenTo(this.model.messageCollection, 'remove', update);
|
||||||
|
|
||||||
this.listenBack(view);
|
this.listenBack(view);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1294,20 +1310,23 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
showMessageDetail(message) {
|
showMessageDetail(message) {
|
||||||
|
const onClose = () => {
|
||||||
|
this.stopListening(message, 'change', update);
|
||||||
|
this.resetPanel();
|
||||||
|
this.updateHeader();
|
||||||
|
};
|
||||||
|
|
||||||
const props = message.getPropsForMessageDetail();
|
const props = message.getPropsForMessageDetail();
|
||||||
const view = new Whisper.ReactWrapperView({
|
const view = new Whisper.ReactWrapperView({
|
||||||
className: 'message-detail-wrapper',
|
className: 'message-detail-wrapper',
|
||||||
Component: Signal.Components.MessageDetail,
|
Component: Signal.Components.MessageDetail,
|
||||||
props,
|
props,
|
||||||
onClose: () => {
|
onClose,
|
||||||
this.stopListening(message, 'change', update);
|
|
||||||
this.resetPanel();
|
|
||||||
this.updateHeader();
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const update = () => view.update(message.getPropsForMessageDetail());
|
const update = () => view.update(message.getPropsForMessageDetail());
|
||||||
this.listenTo(message, 'change', update);
|
this.listenTo(message, 'change', update);
|
||||||
|
this.listenTo(message, 'expired', onClose);
|
||||||
// We could listen to all involved contacts, but we'll call that overkill
|
// We could listen to all involved contacts, but we'll call that overkill
|
||||||
|
|
||||||
this.listenBack(view);
|
this.listenBack(view);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue