ConversationView: some simple type improvements
This commit is contained in:
parent
b72d7b436e
commit
5075fa241f
1 changed files with 89 additions and 53 deletions
|
@ -1,8 +1,6 @@
|
||||||
// Copyright 2020-2021 Signal Messenger, LLC
|
// Copyright 2020-2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
|
|
||||||
import nodePath from 'path';
|
import nodePath from 'path';
|
||||||
import { unstable_batchedUpdates as batchedUpdates } from 'react-dom';
|
import { unstable_batchedUpdates as batchedUpdates } from 'react-dom';
|
||||||
|
|
||||||
|
@ -66,6 +64,7 @@ import {
|
||||||
import { ReadStatus } from '../messages/MessageReadStatus';
|
import { ReadStatus } from '../messages/MessageReadStatus';
|
||||||
import { markViewed } from '../services/MessageUpdater';
|
import { markViewed } from '../services/MessageUpdater';
|
||||||
import { viewSyncJobQueue } from '../jobs/viewSyncJobQueue';
|
import { viewSyncJobQueue } from '../jobs/viewSyncJobQueue';
|
||||||
|
import type { ContactType } from '../types/Contact';
|
||||||
import type { WhatIsThis } from '../window.d';
|
import type { WhatIsThis } from '../window.d';
|
||||||
|
|
||||||
type AttachmentOptions = {
|
type AttachmentOptions = {
|
||||||
|
@ -269,7 +268,7 @@ Whisper.DecryptionErrorToast = Whisper.ToastView.extend({
|
||||||
|
|
||||||
Whisper.FileSavedToast = Whisper.ToastView.extend({
|
Whisper.FileSavedToast = Whisper.ToastView.extend({
|
||||||
className: 'toast toast-clickable',
|
className: 'toast toast-clickable',
|
||||||
initialize(options: any) {
|
initialize(options: Readonly<{ fullPath: string }>) {
|
||||||
if (!options.fullPath) {
|
if (!options.fullPath) {
|
||||||
throw new Error('FileSavedToast: name option was not provided!');
|
throw new Error('FileSavedToast: name option was not provided!');
|
||||||
}
|
}
|
||||||
|
@ -841,13 +840,18 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
const showContactModal = (contactId: string) => {
|
const showContactModal = (contactId: string) => {
|
||||||
this.showContactModal(contactId);
|
this.showContactModal(contactId);
|
||||||
};
|
};
|
||||||
const openConversation = (conversationId: string, messageId: any) => {
|
const openConversation = (conversationId: string, messageId: string) => {
|
||||||
this.openConversation(conversationId, messageId);
|
this.openConversation(conversationId, messageId);
|
||||||
};
|
};
|
||||||
const showContactDetail = (options: any) => {
|
const showContactDetail = (options: {
|
||||||
|
contact: ContactType;
|
||||||
|
signalAccount?: string;
|
||||||
|
}) => {
|
||||||
this.showContactDetail(options);
|
this.showContactDetail(options);
|
||||||
};
|
};
|
||||||
const kickOffAttachmentDownload = async (options: any) => {
|
const kickOffAttachmentDownload = async (
|
||||||
|
options: Readonly<{ messageId: string }>
|
||||||
|
) => {
|
||||||
const message = window.MessageController.getById(options.messageId);
|
const message = window.MessageController.getById(options.messageId);
|
||||||
if (!message) {
|
if (!message) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -894,7 +898,11 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
}) => {
|
}) => {
|
||||||
this.showLightbox(options);
|
this.showLightbox(options);
|
||||||
};
|
};
|
||||||
const downloadAttachment = (options: any) => {
|
const downloadAttachment = (options: {
|
||||||
|
attachment: AttachmentType;
|
||||||
|
timestamp: number;
|
||||||
|
isDangerous: boolean;
|
||||||
|
}) => {
|
||||||
this.downloadAttachment(options);
|
this.downloadAttachment(options);
|
||||||
};
|
};
|
||||||
const displayTapToViewMessage = (messageId: string) =>
|
const displayTapToViewMessage = (messageId: string) =>
|
||||||
|
@ -975,18 +983,24 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
this.navigateTo('https://support.signal.org/hc/articles/4404859745690');
|
this.navigateTo('https://support.signal.org/hc/articles/4404859745690');
|
||||||
};
|
};
|
||||||
|
|
||||||
const scrollToQuotedMessage = async (options: any) => {
|
const scrollToQuotedMessage = async (
|
||||||
|
options: Readonly<{
|
||||||
|
authorId: string;
|
||||||
|
sentAt: number;
|
||||||
|
}>
|
||||||
|
) => {
|
||||||
const { authorId, sentAt } = options;
|
const { authorId, sentAt } = options;
|
||||||
|
|
||||||
const conversationId = model.id;
|
const conversationId = model.id;
|
||||||
const messages = await getMessagesBySentAt(sentAt, {
|
const messages = await getMessagesBySentAt(sentAt, {
|
||||||
MessageCollection: Whisper.MessageCollection,
|
MessageCollection: Whisper.MessageCollection,
|
||||||
});
|
});
|
||||||
const message = messages.find(
|
const message = messages.find(item =>
|
||||||
item =>
|
Boolean(
|
||||||
item.get('conversationId') === conversationId &&
|
item.get('conversationId') === conversationId &&
|
||||||
authorId &&
|
authorId &&
|
||||||
item.getContactId() === authorId
|
item.getContactId() === authorId
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!message) {
|
if (!message) {
|
||||||
|
@ -1202,7 +1216,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
|
|
||||||
showToast(
|
showToast(
|
||||||
ToastView: typeof window.Whisper.ToastView,
|
ToastView: typeof window.Whisper.ToastView,
|
||||||
options: any,
|
options: WhatIsThis,
|
||||||
element: Element
|
element: Element
|
||||||
) {
|
) {
|
||||||
const toast = new ToastView(options);
|
const toast = new ToastView(options);
|
||||||
|
@ -1225,8 +1239,8 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
collection: MessageModelCollectionType | Array<MessageModel>
|
collection: MessageModelCollectionType | Array<MessageModel>
|
||||||
): Promise<Array<MessageModel>> {
|
): Promise<Array<MessageModel>> {
|
||||||
const result = collection
|
const result = collection
|
||||||
.filter((message: any) => Boolean(message.id))
|
.filter((message: MessageModel) => Boolean(message.id))
|
||||||
.map((message: any) =>
|
.map((message: MessageModel) =>
|
||||||
window.MessageController.register(message.id, message)
|
window.MessageController.register(message.id, message)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1601,15 +1615,15 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
this.remove();
|
this.remove();
|
||||||
},
|
},
|
||||||
|
|
||||||
navigateTo(url: any) {
|
navigateTo(url: string) {
|
||||||
window.location = url;
|
window.location.href = url;
|
||||||
},
|
},
|
||||||
|
|
||||||
downloadNewVersion() {
|
downloadNewVersion() {
|
||||||
(window as any).location = 'https://signal.org/download';
|
this.navigateTo('https://signal.org/download');
|
||||||
},
|
},
|
||||||
|
|
||||||
onDragOver(e: any) {
|
onDragOver(e: WhatIsThis) {
|
||||||
if (e.originalEvent.dataTransfer.types[0] !== 'Files') {
|
if (e.originalEvent.dataTransfer.types[0] !== 'Files') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1619,7 +1633,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
this.$el.addClass('dropoff');
|
this.$el.addClass('dropoff');
|
||||||
},
|
},
|
||||||
|
|
||||||
onDragLeave(e: any) {
|
onDragLeave(e: WhatIsThis) {
|
||||||
if (e.originalEvent.dataTransfer.types[0] !== 'Files') {
|
if (e.originalEvent.dataTransfer.types[0] !== 'Files') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1628,7 +1642,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
},
|
},
|
||||||
|
|
||||||
async onDrop(e: any) {
|
async onDrop(e: WhatIsThis) {
|
||||||
if (e.originalEvent.dataTransfer.types[0] !== 'Files') {
|
if (e.originalEvent.dataTransfer.types[0] !== 'Files') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1651,7 +1665,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onPaste(e: any) {
|
onPaste(e: WhatIsThis) {
|
||||||
const { items } = e.originalEvent.clipboardData;
|
const { items } = e.originalEvent.clipboardData;
|
||||||
let imgBlob = null;
|
let imgBlob = null;
|
||||||
for (let i = 0; i < items.length; i += 1) {
|
for (let i = 0; i < items.length; i += 1) {
|
||||||
|
@ -1699,7 +1713,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onClickAttachment(attachment: any) {
|
onClickAttachment(attachment: WhatIsThis) {
|
||||||
const getProps = () => ({
|
const getProps = () => ({
|
||||||
url: attachment.url,
|
url: attachment.url,
|
||||||
caption: attachment.caption,
|
caption: attachment.caption,
|
||||||
|
@ -1707,11 +1721,11 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
onSave,
|
onSave,
|
||||||
});
|
});
|
||||||
|
|
||||||
const onSave = (caption: any) => {
|
const onSave = (caption: WhatIsThis) => {
|
||||||
this.model.set({
|
this.model.set({
|
||||||
draftAttachments: this.model
|
draftAttachments: this.model
|
||||||
.get('draftAttachments')
|
.get('draftAttachments')
|
||||||
.map((item: any) => {
|
.map((item: WhatIsThis) => {
|
||||||
if (
|
if (
|
||||||
(item.path && item.path === attachment.path) ||
|
(item.path && item.path === attachment.path) ||
|
||||||
(item.screenshotPath &&
|
(item.screenshotPath &&
|
||||||
|
@ -1797,7 +1811,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
async onCloseAttachment(attachment: any) {
|
async onCloseAttachment(attachment: Pick<AttachmentType, 'path'>) {
|
||||||
const { model }: { model: ConversationModel } = this;
|
const { model }: { model: ConversationModel } = this;
|
||||||
const draftAttachments = model.get('draftAttachments') || [];
|
const draftAttachments = model.get('draftAttachments') || [];
|
||||||
|
|
||||||
|
@ -1860,7 +1874,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
return files;
|
return files;
|
||||||
},
|
},
|
||||||
|
|
||||||
async getFile(attachment: any) {
|
async getFile(attachment?: AttachmentType) {
|
||||||
if (!attachment) {
|
if (!attachment) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
@ -1888,7 +1902,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
arrayBufferFromFile(file: Blob): Promise<ArrayBuffer> {
|
arrayBufferFromFile(file: Blob): Promise<ArrayBuffer> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const FR = new FileReader();
|
const FR = new FileReader();
|
||||||
FR.onload = (e: any) => {
|
FR.onload = (e: WhatIsThis) => {
|
||||||
resolve(e.target.result);
|
resolve(e.target.result);
|
||||||
};
|
};
|
||||||
FR.onerror = reject;
|
FR.onerror = reject;
|
||||||
|
@ -1897,7 +1911,15 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
showFileSizeError({ limit, units, u }: any) {
|
showFileSizeError({
|
||||||
|
limit,
|
||||||
|
units,
|
||||||
|
u,
|
||||||
|
}: Readonly<{
|
||||||
|
limit: WhatIsThis;
|
||||||
|
units: WhatIsThis;
|
||||||
|
u: WhatIsThis;
|
||||||
|
}>) {
|
||||||
const toast = new Whisper.FileSizeToast({
|
const toast = new Whisper.FileSizeToast({
|
||||||
model: { limit, units: units[u] },
|
model: { limit, units: units[u] },
|
||||||
});
|
});
|
||||||
|
@ -1969,7 +1991,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
|
|
||||||
const haveNonImage = window._.any(
|
const haveNonImage = window._.any(
|
||||||
draftAttachments,
|
draftAttachments,
|
||||||
(attachment: any) => !MIME.isImage(attachment.contentType)
|
(attachment: WhatIsThis) => !MIME.isImage(attachment.contentType)
|
||||||
);
|
);
|
||||||
// You can't add another attachment if you already have a non-image staged
|
// You can't add another attachment if you already have a non-image staged
|
||||||
if (haveNonImage) {
|
if (haveNonImage) {
|
||||||
|
@ -2059,7 +2081,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
isSizeOkay(attachment: any) {
|
isSizeOkay(attachment: Readonly<AttachmentType>) {
|
||||||
const limitKb = window.Signal.Types.Attachment.getUploadSizeLimitKb(
|
const limitKb = window.Signal.Types.Attachment.getUploadSizeLimitKb(
|
||||||
attachment.contentType
|
attachment.contentType
|
||||||
);
|
);
|
||||||
|
@ -2081,7 +2103,9 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
async handleVideoAttachment(file: any): Promise<InMemoryAttachmentDraftType> {
|
async handleVideoAttachment(
|
||||||
|
file: Readonly<File>
|
||||||
|
): Promise<InMemoryAttachmentDraftType> {
|
||||||
const objectUrl = URL.createObjectURL(file);
|
const objectUrl = URL.createObjectURL(file);
|
||||||
if (!objectUrl) {
|
if (!objectUrl) {
|
||||||
throw new Error('Failed to create object url for video!');
|
throw new Error('Failed to create object url for video!');
|
||||||
|
@ -2103,7 +2127,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
screenshotContentType,
|
screenshotContentType,
|
||||||
screenshotData,
|
screenshotData,
|
||||||
screenshotSize: screenshotData.byteLength,
|
screenshotSize: screenshotData.byteLength,
|
||||||
contentType: file.type,
|
contentType: stringToMIMEType(file.type),
|
||||||
data,
|
data,
|
||||||
size: data.byteLength,
|
size: data.byteLength,
|
||||||
};
|
};
|
||||||
|
@ -2112,9 +2136,9 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
markAllAsVerifiedDefault(unverified: any) {
|
markAllAsVerifiedDefault(unverified: ReadonlyArray<ConversationModel>) {
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
unverified.map((contact: any) => {
|
unverified.map(contact => {
|
||||||
if (contact.isUnverified()) {
|
if (contact.isUnverified()) {
|
||||||
return contact.setVerifiedDefault();
|
return contact.setVerifiedDefault();
|
||||||
}
|
}
|
||||||
|
@ -2124,8 +2148,8 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
markAllAsApproved(untrusted: any) {
|
markAllAsApproved(untrusted: ReadonlyArray<ConversationModel>) {
|
||||||
return Promise.all(untrusted.map((contact: any) => contact.setApproved()));
|
return Promise.all(untrusted.map(contact => contact.setApproved()));
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleMicrophone() {
|
toggleMicrophone() {
|
||||||
|
@ -2541,10 +2565,10 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
const { attachments } = message;
|
const { attachments } = message;
|
||||||
return (attachments || [])
|
return (attachments || [])
|
||||||
.filter(
|
.filter(
|
||||||
(attachment: any) =>
|
(attachment: AttachmentType) =>
|
||||||
attachment.thumbnail && !attachment.pending && !attachment.error
|
attachment.thumbnail && !attachment.pending && !attachment.error
|
||||||
)
|
)
|
||||||
.map((attachment: any, index: number) => {
|
.map((attachment: WhatIsThis, index: number) => {
|
||||||
const { thumbnail } = attachment;
|
const { thumbnail } = attachment;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -2577,7 +2601,13 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const saveAttachment = async ({ attachment, message }: any = {}) => {
|
const saveAttachment = async ({
|
||||||
|
attachment,
|
||||||
|
message,
|
||||||
|
}: {
|
||||||
|
attachment: AttachmentType;
|
||||||
|
message: Pick<MessageAttributesType, 'sent_at'>;
|
||||||
|
}) => {
|
||||||
const timestamp = message.sent_at;
|
const timestamp = message.sent_at;
|
||||||
const fullPath = await window.Signal.Types.Attachment.save({
|
const fullPath = await window.Signal.Types.Attachment.save({
|
||||||
attachment,
|
attachment,
|
||||||
|
@ -2591,7 +2621,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onItemClick = async ({ message, attachment, type }: any) => {
|
const onItemClick = async ({ message, attachment, type }: WhatIsThis) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'documents': {
|
case 'documents': {
|
||||||
saveAttachment({ message, attachment });
|
saveAttachment({ message, attachment });
|
||||||
|
@ -2990,8 +3020,11 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: DESKTOP-1133 (DRY up these lightboxes)
|
// TODO: DESKTOP-1133 (DRY up these lightboxes)
|
||||||
showLightboxForMedia(selectedMediaItem: any, media: Array<any> = []) {
|
showLightboxForMedia(
|
||||||
const onSave = async (options: any = {}) => {
|
selectedMediaItem: WhatIsThis,
|
||||||
|
media: Array<WhatIsThis> = []
|
||||||
|
) {
|
||||||
|
const onSave = async (options: WhatIsThis = {}) => {
|
||||||
const fullPath = await window.Signal.Types.Attachment.save({
|
const fullPath = await window.Signal.Types.Attachment.save({
|
||||||
attachment: options.attachment,
|
attachment: options.attachment,
|
||||||
index: options.index + 1,
|
index: options.index + 1,
|
||||||
|
@ -3096,10 +3129,10 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
|
|
||||||
const selectedIndex = window._.findIndex(
|
const selectedIndex = window._.findIndex(
|
||||||
media,
|
media,
|
||||||
(item: any) => attachment.path === item.path
|
item => attachment.path === item.path
|
||||||
);
|
);
|
||||||
|
|
||||||
const onSave = async (options: any = {}) => {
|
const onSave = async (options: WhatIsThis = {}) => {
|
||||||
const fullPath = await window.Signal.Types.Attachment.save({
|
const fullPath = await window.Signal.Types.Attachment.save({
|
||||||
attachment: options.attachment,
|
attachment: options.attachment,
|
||||||
index: options.index + 1,
|
index: options.index + 1,
|
||||||
|
@ -3447,8 +3480,8 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
contact,
|
contact,
|
||||||
signalAccount,
|
signalAccount,
|
||||||
}: {
|
}: {
|
||||||
contact: any;
|
contact: ContactType;
|
||||||
signalAccount: any;
|
signalAccount?: string;
|
||||||
}) {
|
}) {
|
||||||
const view = new Whisper.ReactWrapperView({
|
const view = new Whisper.ReactWrapperView({
|
||||||
Component: window.Signal.Components.ContactDetail,
|
Component: window.Signal.Components.ContactDetail,
|
||||||
|
@ -3474,7 +3507,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
window.Whisper.events.trigger('showConversation', conversationId);
|
window.Whisper.events.trigger('showConversation', conversationId);
|
||||||
},
|
},
|
||||||
|
|
||||||
listenBack(view: any) {
|
listenBack(view: WhatIsThis) {
|
||||||
this.panels = this.panels || [];
|
this.panels = this.panels || [];
|
||||||
|
|
||||||
if (this.panels.length === 0) {
|
if (this.panels.length === 0) {
|
||||||
|
@ -3580,10 +3613,10 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
async setDisappearingMessages(seconds: any) {
|
async setDisappearingMessages(seconds: number) {
|
||||||
const { model }: { model: ConversationModel } = this;
|
const { model }: { model: ConversationModel } = this;
|
||||||
|
|
||||||
const valueToSet = seconds > 0 ? seconds : null;
|
const valueToSet = seconds > 0 ? seconds : undefined;
|
||||||
|
|
||||||
await this.longRunningTaskWrapper({
|
await this.longRunningTaskWrapper({
|
||||||
name: 'updateExpirationTimer',
|
name: 'updateExpirationTimer',
|
||||||
|
@ -3718,7 +3751,10 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
async sendReactionMessage(messageId: string, reaction: any) {
|
async sendReactionMessage(
|
||||||
|
messageId: string,
|
||||||
|
reaction: { emoji: string; remove: boolean }
|
||||||
|
) {
|
||||||
const messageModel = messageId
|
const messageModel = messageId
|
||||||
? await getMessageById(messageId, {
|
? await getMessageById(messageId, {
|
||||||
Message: Whisper.Message,
|
Message: Whisper.Message,
|
||||||
|
@ -4090,7 +4126,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
removeLinkPreview() {
|
removeLinkPreview() {
|
||||||
(this.preview || []).forEach((item: any) => {
|
(this.preview || []).forEach((item: WhatIsThis) => {
|
||||||
if (item.url) {
|
if (item.url) {
|
||||||
URL.revokeObjectURL(item.url);
|
URL.revokeObjectURL(item.url);
|
||||||
}
|
}
|
||||||
|
@ -4379,7 +4415,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
(this.preview || []).forEach((item: any) => {
|
(this.preview || []).forEach((item: WhatIsThis) => {
|
||||||
if (item.url) {
|
if (item.url) {
|
||||||
URL.revokeObjectURL(item.url);
|
URL.revokeObjectURL(item.url);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue