diff --git a/src/utils/exportUtils.js b/src/utils/exportUtils.js index e357ac6575..433600eac4 100644 --- a/src/utils/exportUtils.js +++ b/src/utils/exportUtils.js @@ -4,6 +4,8 @@ import { TimelineWindow } from "matrix-js-sdk/src/timeline-window"; import JSZip from "jszip"; import { textForEvent } from "../TextForEvent"; import streamSaver from "streamsaver"; +import { decryptFile } from "./DecryptFile"; +import { mediaFromContent, mediaFromMxc } from "../customisations/Media"; const wrapHTML = (content, room) => (` @@ -33,36 +35,6 @@ const wrapHTML = (content, room) => (` `); -const getTimelineConversation = (room) => { - if (!room) return; - - const cli = MatrixClientPeg.get(); - - const timelineSet = room.getUnfilteredTimelineSet(); - - const timelineWindow = new TimelineWindow( - cli, timelineSet, - {windowLimit: Number.MAX_VALUE}); - - timelineWindow.load(null, 20); - - const events = timelineWindow.getEvents(); - - // Clone and reverse the events so that we preserve the order - arrayFastClone(events) - .reverse() - .forEach(event => { - cli.decryptEventIfNeeded(event); - }); - - if (!timelineWindow.canPaginate('f')) { - events.push(...timelineSet.getPendingEvents()); - } - console.log(events); - return events; -}; - - const css = ` body { margin: 0; @@ -297,6 +269,37 @@ div.selected { } `; + +const getTimelineConversation = (room) => { + if (!room) return; + + const cli = MatrixClientPeg.get(); + + const timelineSet = room.getUnfilteredTimelineSet(); + + const timelineWindow = new TimelineWindow( + cli, timelineSet, + {windowLimit: Number.MAX_VALUE}); + + timelineWindow.load(null, 20); + + const events = timelineWindow.getEvents(); + + // Clone and reverse the events so that we preserve the order + arrayFastClone(events) + .reverse() + .forEach(event => { + cli.decryptEventIfNeeded(event); + }); + + if (!timelineWindow.canPaginate('f')) { + events.push(...timelineSet.getPendingEvents()); + } + console.log(events); + return events; +}; + + const userColors = [ "#64bf47", "#4f9cd9", @@ -307,41 +310,50 @@ const userColors = [ ]; -//Get a color associated with a string. This is to map userId to a specific color +//Get a color associated with string length. This is to map userId to a specific color const getUserColor = (userId) => { return userColors[userId.length % 4]; }; -const createMessageBody = (event, joined = false, isReply = false, replyId = null) => { - return ` -
- `; + +const getUserPic = async (event) => { + const member = event.sender; + if (!member.getMxcAvatarUrl()) { + return ` +
+ `;
+ const blob = await getImageData(event);
+ zip.file(`images/${event.getId()}.png`, blob);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return `
+
+ `;
+};
+
+
+const createHTML = async (events, room) => {
let content = "";
let prevEvent = null;
for (const event of events) {
content += dateSeparator(event, prevEvent);
+
if (event.getType() === "m.room.message") {
const replyTo = baseEventId(event);
const shouldBeJoined = prevEvent && prevEvent.getContent().msgtype === "m.text"
&& event.sender.userId === prevEvent.sender.userId && !dateSeparator(event, prevEvent) && !replyTo;
- const body = createMessageBody(event, shouldBeJoined, !!replyTo, replyTo);
+
+ const body = await createMessageBody(event, shouldBeJoined, !!replyTo, replyTo);
content += body;
} else {
content += `
@@ -387,22 +458,27 @@ const createHTML = (events, room) => {
};
+const avatars = new Map();
+let zip;
const exportConversationalHistory = async (room) => {
const res = getTimelineConversation(room);
- const zip = new JSZip();
- const html = createHTML(res, room);
- zip.file("css/style.css", css);
+ zip = new JSZip();
+
+ const html = await createHTML(res, room, avatars);
+
zip.file("index.html", html);
+ zip.file("css/style.css", css);
+
+ avatars.clear();
const filename = `matrix-export-${new Date().toISOString()}.zip`;
//Generate the zip file asynchronously
const blob = await zip.generateAsync({ type: "blob" });
+
//Create a writable stream to the directory
const fileStream = streamSaver.createWriteStream(filename, blob.size);
const writer = fileStream.getWriter();
- // console.log(blob.size);
-
// Here we chunk the blob into pieces of 10 MiB
const sliceSize = 10 * 1e6;
for (let fPointer = 0; fPointer < blob.size; fPointer += sliceSize) {