WIP improve export
This commit is contained in:
parent
9a124c5ab9
commit
94bf35875a
3 changed files with 174 additions and 169 deletions
|
|
@ -27,12 +27,12 @@
|
|||
<div v-if="!event.isRelation() && !event.isRedacted() && !event.isRedaction()" :ref="event.getId()">
|
||||
<div class="message-wrapper">
|
||||
<component
|
||||
:is="componentForEvent(event, true)"
|
||||
:is="componentForEventForExport(event, true)"
|
||||
:room="room"
|
||||
:originalEvent="event"
|
||||
:nextEvent="events[index + 1]"
|
||||
:timelineSet="timelineSet"
|
||||
:componentFn="componentForEvent"
|
||||
:componentFn="componentForEventForExport"
|
||||
ref="exportedEvent"
|
||||
v-on:layout-change="onLayoutChange"
|
||||
/>
|
||||
|
|
@ -153,6 +153,7 @@ export default {
|
|||
return {
|
||||
timelineSet: null,
|
||||
events: [],
|
||||
exportComponents: [],
|
||||
fetchedEvents: 0,
|
||||
totalEvents: 0,
|
||||
processedEvents: 0,
|
||||
|
|
@ -179,6 +180,22 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
componentForEventForExport(event, forExport) {
|
||||
const comp = this.componentForEvent(event, forExport);
|
||||
const self = this;
|
||||
if (comp) {
|
||||
if (!comp.mixins) {
|
||||
comp.mixins = [];
|
||||
}
|
||||
comp.mixins.push({
|
||||
created: function() {
|
||||
console.error("Created", this.name);
|
||||
self.exportComponents.push(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
return comp;
|
||||
},
|
||||
cancelExport() {
|
||||
this.cancelled = true;
|
||||
},
|
||||
|
|
@ -230,6 +247,8 @@ export default {
|
|||
var currentMediaSize = 0;
|
||||
var maxMediaSize = 1024 * 1024 * 1024; // 1GB
|
||||
|
||||
this.exportComponents = [];
|
||||
|
||||
this.getEvents()
|
||||
.then((events) => {
|
||||
var decryptionPromises = [];
|
||||
|
|
@ -282,6 +301,8 @@ export default {
|
|||
});
|
||||
})
|
||||
.then(() => {
|
||||
this.totalEvents = this.exportComponents.length;
|
||||
|
||||
// UI updated, start processing events
|
||||
zip = new JSZip();
|
||||
var avatarFolder = zip.folder("avatars");
|
||||
|
|
@ -291,186 +312,173 @@ export default {
|
|||
var filesFolder = zip.folder("files");
|
||||
|
||||
var downloadPromises = [];
|
||||
let components = this.$refs.exportedEvent;
|
||||
for (const parentComp of components) {
|
||||
let childComponents = [parentComp];
|
||||
|
||||
// Some components, i.e. the media threads, have subcomponents
|
||||
// that we want to export. So pickup subcomponents here as well.
|
||||
if (parentComp.$refs && parentComp.$refs.exportedEvent) {
|
||||
if (Array.isArray(parentComp.$refs.exportedEvent)) {
|
||||
for (const child of parentComp.$refs.exportedEvent) {
|
||||
childComponents.push(child);
|
||||
}
|
||||
} else {
|
||||
childComponents.push(parentComp.$refs.exportedEvent);
|
||||
}
|
||||
}
|
||||
for (const comp of childComponents.filter((c) => c.event != undefined)) {
|
||||
// Avatars need downloading?
|
||||
if (comp.$el && comp.$el.nodeType == 1) {
|
||||
const avatars = comp.$el.getElementsByClassName("v-avatar");
|
||||
if (avatars && avatars.length > 0) {
|
||||
const member = this.room.getMember(comp.event.getSender());
|
||||
if (member) {
|
||||
const fileName = comp.event.getSender() + ".png";
|
||||
for (const comp of this.exportComponents.filter((c) => c.event != undefined)) {
|
||||
// Avatars need downloading?
|
||||
if (comp.$el && comp.$el.nodeType == 1) {
|
||||
const avatars = comp.$el.getElementsByClassName("v-avatar");
|
||||
if (avatars && avatars.length > 0) {
|
||||
const member = this.room.getMember(comp.event.getSender());
|
||||
if (member) {
|
||||
const fileName = comp.event.getSender() + ".png";
|
||||
|
||||
const setSource = (fileName) => {
|
||||
for (let avatarIndex = 0; avatarIndex < avatars.length; avatarIndex++) {
|
||||
const avatarElement = avatars[avatarIndex];
|
||||
const images = avatarElement.getElementsByTagName("img");
|
||||
for (let imageIndex = 0; imageIndex < images.length; imageIndex++) {
|
||||
const img = images[imageIndex];
|
||||
img.onerror = undefined;
|
||||
img.removeAttribute("src");
|
||||
img.setAttribute("data-exported-src", "./avatars/" + fileName);
|
||||
}
|
||||
const setSource = (fileName) => {
|
||||
for (let avatarIndex = 0; avatarIndex < avatars.length; avatarIndex++) {
|
||||
const avatarElement = avatars[avatarIndex];
|
||||
const images = avatarElement.getElementsByTagName("img");
|
||||
for (let imageIndex = 0; imageIndex < images.length; imageIndex++) {
|
||||
const img = images[imageIndex];
|
||||
img.onerror = undefined;
|
||||
img.removeAttribute("src");
|
||||
img.setAttribute("data-exported-src", "./avatars/" + fileName);
|
||||
}
|
||||
};
|
||||
|
||||
if (!avatarFolder.file(fileName)) {
|
||||
const url = member.getAvatarUrl(
|
||||
this.$matrix.matrixClient.getHomeserverUrl(),
|
||||
40,
|
||||
40,
|
||||
"scale",
|
||||
true,
|
||||
false,
|
||||
this.$matrix.useAuthedMedia
|
||||
);
|
||||
if (url) {
|
||||
avatarFolder.file(fileName, "empty");
|
||||
downloadPromises.push(
|
||||
axios
|
||||
.get(url, {
|
||||
responseType: "blob",
|
||||
headers: this.$matrix.useAuthedMedia
|
||||
? {
|
||||
Authorization: `Bearer ${this.$matrix.matrixClient.getAccessToken()}`,
|
||||
}
|
||||
: undefined,
|
||||
})
|
||||
.then((result) => {
|
||||
if (result.data) {
|
||||
avatarFolder.file(fileName, result.data);
|
||||
setSource(fileName);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Download error: ", err);
|
||||
avatarFolder.remove(fileName);
|
||||
})
|
||||
);
|
||||
}
|
||||
} else {
|
||||
setSource(fileName);
|
||||
}
|
||||
};
|
||||
|
||||
if (!avatarFolder.file(fileName)) {
|
||||
const url = member.getAvatarUrl(
|
||||
this.$matrix.matrixClient.getHomeserverUrl(),
|
||||
40,
|
||||
40,
|
||||
"scale",
|
||||
true,
|
||||
false,
|
||||
this.$matrix.useAuthedMedia
|
||||
);
|
||||
if (url) {
|
||||
avatarFolder.file(fileName, "empty");
|
||||
downloadPromises.push(
|
||||
axios
|
||||
.get(url, {
|
||||
responseType: "blob",
|
||||
headers: this.$matrix.useAuthedMedia
|
||||
? {
|
||||
Authorization: `Bearer ${this.$matrix.matrixClient.getAccessToken()}`,
|
||||
}
|
||||
: undefined,
|
||||
})
|
||||
.then((result) => {
|
||||
if (result.data) {
|
||||
avatarFolder.file(fileName, result.data);
|
||||
setSource(fileName);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Download error: ", err);
|
||||
avatarFolder.remove(fileName);
|
||||
})
|
||||
);
|
||||
}
|
||||
} else {
|
||||
setSource(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let componentClass = comp.$options
|
||||
? comp.$options.__file.split("/").reverse()[0].split(".")[0]
|
||||
: "invalid_component";
|
||||
let attachment =
|
||||
comp.event && comp.event.getId
|
||||
? this.$matrix.attachmentManager.getEventAttachment(comp.event)
|
||||
: undefined;
|
||||
let attachment =
|
||||
comp.event && comp.event.getId
|
||||
? this.$matrix.attachmentManager.getEventAttachment(comp.event)
|
||||
: undefined;
|
||||
let componentClass = comp.$options
|
||||
? comp.$options.__file.split("/").reverse()[0].split(".")[0]
|
||||
: "invalid_component";
|
||||
console.error("Processi", componentClass, comp.event, comp.originalEvent, attachment);
|
||||
|
||||
if (attachment && (attachment.srcSize = 0 || currentMediaSize + attachment.srcSize <= maxMediaSize)) {
|
||||
downloadPromises.push(
|
||||
attachment
|
||||
.loadSrc({ asBlob: true })
|
||||
.then((res) => {
|
||||
const blob = res.data;
|
||||
if (currentMediaSize + blob.size <= maxMediaSize) {
|
||||
currentMediaSize += blob.size;
|
||||
|
||||
switch (componentClass) {
|
||||
case "MessageIncomingImageExport":
|
||||
case "MessageOutgoingImageExport":
|
||||
{
|
||||
let mime = blob.type;
|
||||
var extension = ".png";
|
||||
switch (mime) {
|
||||
case "image/jpeg":
|
||||
case "image/jpg":
|
||||
extension = ".jpg";
|
||||
break;
|
||||
case "image/gif":
|
||||
extension = ".gif";
|
||||
}
|
||||
if (attachment && (attachment.srcSize = 0 || currentMediaSize + attachment.srcSize <= maxMediaSize)) {
|
||||
downloadPromises.push(
|
||||
attachment
|
||||
.loadSrc({ asBlob: true })
|
||||
.then((res) => {
|
||||
const blob = res.data;
|
||||
if (currentMediaSize + blob.size <= maxMediaSize) {
|
||||
currentMediaSize += blob.size;
|
||||
|
||||
let fileName = comp.event.getId() + extension;
|
||||
imageFolder.file(fileName, blob); // TODO calc bytes
|
||||
|
||||
// Update source
|
||||
const images = comp.$el.getElementsByTagName("img");
|
||||
for (let imageIndex = 0; imageIndex < images.length; imageIndex++) {
|
||||
const img = images[imageIndex];
|
||||
img.removeAttribute("src");
|
||||
img.setAttribute("data-exported-src", "./images/" + fileName);
|
||||
}
|
||||
this.processedEvents += 1;
|
||||
switch (componentClass) {
|
||||
case "MessageIncomingImageExport":
|
||||
case "MessageOutgoingImageExport":
|
||||
{
|
||||
let mime = blob.type;
|
||||
var extension = ".png";
|
||||
switch (mime) {
|
||||
case "image/jpeg":
|
||||
case "image/jpg":
|
||||
extension = ".jpg";
|
||||
break;
|
||||
case "image/gif":
|
||||
extension = ".gif";
|
||||
}
|
||||
break;
|
||||
|
||||
case "MessageIncomingAudioExport":
|
||||
case "MessageOutgoingAudioExport":
|
||||
{
|
||||
var extension = ".webm";
|
||||
let fileName = comp.event.getId() + extension;
|
||||
audioFolder.file(fileName, blob); // TODO calc bytes
|
||||
let elements = comp.$el.getElementsByTagName("audio");
|
||||
let element = elements && elements[0];
|
||||
if (element) {
|
||||
element.setAttribute("data-exported-src", "./audio/" + fileName);
|
||||
}
|
||||
this.processedEvents += 1;
|
||||
}
|
||||
break;
|
||||
let fileName = comp.event.getId() + extension;
|
||||
imageFolder.file(fileName, blob); // TODO calc bytes
|
||||
|
||||
case "MessageIncomingVideoExport":
|
||||
case "MessageOutgoingVideoExport":
|
||||
{
|
||||
var extension = ".mp4";
|
||||
let fileName = comp.event.getId() + extension;
|
||||
videoFolder.file(fileName, blob); // TODO calc bytes
|
||||
// comp.src = "./video/" + fileName;
|
||||
let elements = comp.$el.getElementsByTagName("video");
|
||||
let element = elements && elements[0];
|
||||
if (element) {
|
||||
element.setAttribute("data-exported-src", "./video/" + fileName);
|
||||
}
|
||||
this.processedEvents += 1;
|
||||
// Update source
|
||||
const images = comp.$el.getElementsByTagName("img");
|
||||
for (let imageIndex = 0; imageIndex < images.length; imageIndex++) {
|
||||
const img = images[imageIndex];
|
||||
img.removeAttribute("src");
|
||||
img.setAttribute("data-exported-src", "./images/" + fileName);
|
||||
}
|
||||
break;
|
||||
this.processedEvents += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case "MessageIncomingFileExport":
|
||||
case "MessageOutgoingFileExport":
|
||||
{
|
||||
var extension = util.getFileExtension(comp.event);
|
||||
let fileName = comp.event.getId() + extension;
|
||||
filesFolder.file(fileName, blob);
|
||||
comp.href = "./files/" + fileName;
|
||||
this.processedEvents += 1;
|
||||
case "MessageIncomingAudioExport":
|
||||
case "MessageOutgoingAudioExport":
|
||||
{
|
||||
var extension = ".webm";
|
||||
let fileName = comp.event.getId() + extension;
|
||||
audioFolder.file(fileName, blob); // TODO calc bytes
|
||||
let elements = comp.$el.getElementsByTagName("audio");
|
||||
let element = elements && elements[0];
|
||||
if (element) {
|
||||
element.setAttribute("data-exported-src", "./audio/" + fileName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
this.processedEvents += 1;
|
||||
return true;
|
||||
} else {
|
||||
this.processedEvents += 1;
|
||||
return false;
|
||||
this.processedEvents += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case "MessageIncomingVideoExport":
|
||||
case "MessageOutgoingVideoExport":
|
||||
{
|
||||
var extension = ".mp4";
|
||||
let fileName = comp.event.getId() + extension;
|
||||
videoFolder.file(fileName, blob); // TODO calc bytes
|
||||
// comp.src = "./video/" + fileName;
|
||||
let elements = comp.$el.getElementsByTagName("video");
|
||||
let element = elements && elements[0];
|
||||
if (element) {
|
||||
element.setAttribute("data-exported-src", "./video/" + fileName);
|
||||
}
|
||||
this.processedEvents += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case "MessageIncomingFileExport":
|
||||
case "MessageOutgoingFileExport":
|
||||
{
|
||||
var extension = util.getFileExtension(comp.event);
|
||||
let fileName = comp.event.getId() + extension;
|
||||
filesFolder.file(fileName, blob);
|
||||
comp.href = "./files/" + fileName;
|
||||
this.processedEvents += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
})
|
||||
.catch((ignoredErr) => {
|
||||
this.processedEvents += 1;
|
||||
})
|
||||
);
|
||||
} else {
|
||||
this.processedEvents += 1;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
this.processedEvents += 1;
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.catch((ignoredErr) => {
|
||||
this.processedEvents += 1;
|
||||
})
|
||||
);
|
||||
} else {
|
||||
this.processedEvents += 1;
|
||||
}
|
||||
}
|
||||
return Promise.all(downloadPromises);
|
||||
|
|
|
|||
|
|
@ -32,9 +32,6 @@ import { MatrixEvent, MatrixEventEvent } from "matrix-js-sdk";
|
|||
const { t } = useI18n();
|
||||
const $matrix: any = inject("globalMatrix");
|
||||
|
||||
type RootType = InstanceType<typeof MessageOutgoing | typeof MessageIncoming>;
|
||||
const rootRef = useTemplateRef<RootType>("root");
|
||||
|
||||
const emits = defineEmits<
|
||||
MessageEmits & { (event: "layout-change", value: { element: Element | undefined; action: () => void }): void }
|
||||
>();
|
||||
|
|
@ -44,8 +41,7 @@ const props = defineProps<MessageProps>();
|
|||
|
||||
const processThread = () => {
|
||||
if (!event.value?.isRedacted()) {
|
||||
const el = rootRef.value?.$el;
|
||||
emits("layout-change", { element: el, action: _processThread });
|
||||
_processThread();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -149,9 +149,10 @@ export class AttachmentManager {
|
|||
attachment.loadSrc = (options?: EventAttachmentLoadSrcOptions) => {
|
||||
if (attachment.src && !options?.asBlob) {
|
||||
return Promise.resolve({data: attachment.src, type: "src"});
|
||||
} else if (attachment.srcPromise) {
|
||||
} else if (attachment.srcPromise && !options?.asBlob) {
|
||||
return attachment.srcPromise;
|
||||
}
|
||||
Implement loadBlob somewhere here!
|
||||
attachment.srcPromise = this._loadEventAttachmentOrThumbnail(event, false, !!options?.asBlob, (percent) => {
|
||||
attachment.srcProgress = percent;
|
||||
}).then((res) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue