Display progress

This commit is contained in:
Jaiwanth 2021-07-02 10:23:25 +05:30
parent 08d886e9d1
commit 6ca664636e
5 changed files with 56 additions and 21 deletions

View file

@ -29,6 +29,7 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
const [exportType, setExportType] = useState(exportTypes.TIMELINE); const [exportType, setExportType] = useState(exportTypes.TIMELINE);
const [includeAttachments, setAttachments] = useState(false); const [includeAttachments, setAttachments] = useState(false);
const [isExporting, setExporting] = useState(false); const [isExporting, setExporting] = useState(false);
const [exportProgressText, setExportProgressText] = useState("");
const [numberOfMessages, setNumberOfMessages] = useState<number>(100); const [numberOfMessages, setNumberOfMessages] = useState<number>(100);
const [sizeLimit, setSizeLimit] = useState<number | null>(8); const [sizeLimit, setSizeLimit] = useState<number | null>(8);
const sizeLimitRef = useRef<Field>(); const sizeLimitRef = useRef<Field>();
@ -58,6 +59,7 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
room, room,
exportTypes[exportType], exportTypes[exportType],
exportOptions, exportOptions,
setExportProgressText,
), ),
); );
break; break;
@ -67,6 +69,7 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
room, room,
exportTypes[exportType], exportTypes[exportType],
exportOptions, exportOptions,
setExportProgressText,
), ),
); );
break; break;
@ -76,6 +79,7 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
room, room,
exportTypes[exportType], exportTypes[exportType],
exportOptions, exportOptions,
setExportProgressText,
), ),
); );
break; break;
@ -352,6 +356,7 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
onFinished={onFinished} onFinished={onFinished}
fixedWidth={true} fixedWidth={true}
> >
<p> { exportProgressText } </p>
<DialogButtons <DialogButtons
primaryButton={_t("Cancel")} primaryButton={_t("Cancel")}
primaryButtonClass="danger" primaryButtonClass="danger"

View file

@ -26,7 +26,8 @@ export default abstract class Exporter {
protected constructor( protected constructor(
protected room: Room, protected room: Room,
protected exportType: exportTypes, protected exportType: exportTypes,
protected exportOptions?: exportOptions, protected exportOptions: exportOptions,
protected setProgressText: React.Dispatch<React.SetStateAction<string>>,
) { ) {
this.cancelled = false; this.cancelled = false;
this.files = []; this.files = [];
@ -40,6 +41,11 @@ export default abstract class Exporter {
return e.returnValue = "Are you sure you want to exit during this export?"; return e.returnValue = "Are you sure you want to exit during this export?";
} }
protected updateProgress(progress: string, log = true, show = true): void {
if (log) console.log(progress);
if (show) this.setProgressText(progress);
}
protected addFile(filePath: string, blob: Blob): void { protected addFile(filePath: string, blob: Blob): void {
const file = { const file = {
name: filePath, name: filePath,
@ -57,7 +63,7 @@ export default abstract class Exporter {
// Create a writable stream to the directory // Create a writable stream to the directory
this.fileStream = streamSaver.createWriteStream(filename); this.fileStream = streamSaver.createWriteStream(filename);
if (!this.cancelled) console.info("Generating a ZIP..."); if (!this.cancelled) this.updateProgress("Generating a ZIP...");
else return this.cleanUp(); else return this.cleanUp();
this.writer = this.fileStream.getWriter(); this.writer = this.fileStream.getWriter();
@ -72,7 +78,7 @@ export default abstract class Exporter {
if (this.cancelled) return this.cleanUp(); if (this.cancelled) return this.cleanUp();
console.info("Writing to the file system..."); this.updateProgress("Writing to the file system...");
const reader = readableZipStream.getReader(); const reader = readableZipStream.getReader();
await this.pumpToFileStream(reader); await this.pumpToFileStream(reader);
@ -172,7 +178,11 @@ export default abstract class Exporter {
} }
events.push(mxEv); events.push(mxEv);
} }
console.log("Fetched " + events.length + " events so far."); this.updateProgress(
("Fetched " + events.length + " events ") + (this.exportType === exportTypes.LAST_N_MESSAGES
? `out of ${this.exportOptions.numberOfMessages}...`
: "so far..."),
);
prevToken = res.end; prevToken = res.end;
} }
// Reverse the events so that we preserve the order // Reverse the events so that we preserve the order

View file

@ -27,8 +27,13 @@ export default class HTMLExporter extends Exporter {
protected totalSize: number; protected totalSize: number;
protected mediaOmitText: string; protected mediaOmitText: string;
constructor(room: Room, exportType: exportTypes, exportOptions: exportOptions) { constructor(
super(room, exportType, exportOptions); room: Room,
exportType: exportTypes,
exportOptions: exportOptions,
setProgressText: React.Dispatch<React.SetStateAction<string>>,
) {
super(room, exportType, exportOptions, setProgressText);
this.avatars = new Map<string, boolean>(); this.avatars = new Map<string, boolean>();
this.permalinkCreator = new RoomPermalinkCreator(this.room); this.permalinkCreator = new RoomPermalinkCreator(this.room);
this.totalSize = 0; this.totalSize = 0;
@ -328,6 +333,7 @@ export default class HTMLExporter extends Exporter {
let prevEvent = null; let prevEvent = null;
for (let i = 0; i < events.length; i++) { for (let i = 0; i < events.length; i++) {
const event = events[i]; const event = events[i];
if (i % 100 == 0) this.updateProgress(`Processing event ${i ? i : 1} out of ${events.length}`, false, true);
if (this.cancelled) return this.cleanUp(); if (this.cancelled) return this.cleanUp();
if (!haveTileForEvent(event)) continue; if (!haveTileForEvent(event)) continue;
@ -343,16 +349,16 @@ export default class HTMLExporter extends Exporter {
} }
public async export() { public async export() {
console.info("Starting export process..."); this.updateProgress("Starting export process...", true, false);
console.info("Fetching events..."); this.updateProgress("Fetching events...");
const fetchStart = performance.now(); const fetchStart = performance.now();
const res = await this.getRequiredEvents(); const res = await this.getRequiredEvents();
const fetchEnd = performance.now(); const fetchEnd = performance.now();
console.log(`Fetched ${res.length} events in ${(fetchEnd - fetchStart)/1000}s`); this.updateProgress(`Fetched ${res.length} events in ${(fetchEnd - fetchStart)/1000}s`, true, false);
console.info("Creating HTML..."); this.updateProgress("Creating HTML...");
const html = await this.createHTML(res); const html = await this.createHTML(res);
this.addFile("index.html", new Blob([html])); this.addFile("index.html", new Blob([html]));
@ -370,8 +376,8 @@ export default class HTMLExporter extends Exporter {
if (this.cancelled) { if (this.cancelled) {
console.info("Export cancelled successfully"); console.info("Export cancelled successfully");
} else { } else {
console.info("Export successful!"); this.updateProgress("Export successful!");
console.log(`Exported ${res.length} events in ${(exportEnd - fetchStart)/1000} seconds`); this.updateProgress(`Exported ${res.length} events in ${(exportEnd - fetchStart)/1000} seconds`);
} }
this.cleanUp(); this.cleanUp();

View file

@ -11,8 +11,13 @@ export default class JSONExporter extends Exporter {
protected totalSize: number; protected totalSize: number;
protected messages: any[]; protected messages: any[];
constructor(room: Room, exportType: exportTypes, exportOptions: exportOptions) { constructor(
super(room, exportType, exportOptions); room: Room,
exportType: exportTypes,
exportOptions: exportOptions,
setProgressText: React.Dispatch<React.SetStateAction<string>>,
) {
super(room, exportType, exportOptions, setProgressText);
this.totalSize = 0; this.totalSize = 0;
this.messages = []; this.messages = [];
} }
@ -55,7 +60,9 @@ export default class JSONExporter extends Exporter {
} }
protected async createOutput(events: MatrixEvent[]) { protected async createOutput(events: MatrixEvent[]) {
for (const event of events) { for (let i = 0; i < events.length; i++) {
const event = events[i];
if (i % 100 == 0) this.updateProgress(`Processing event ${i ? i : 1} out of ${events.length}`, false, true);
if (this.cancelled) return this.cleanUp(); if (this.cancelled) return this.cleanUp();
if (!haveTileForEvent(event)) continue; if (!haveTileForEvent(event)) continue;
this.messages.push(await this.getJSONString(event)); this.messages.push(await this.getJSONString(event));

View file

@ -12,8 +12,13 @@ export default class PlainTextExporter extends Exporter {
protected totalSize: number; protected totalSize: number;
protected mediaOmitText: string; protected mediaOmitText: string;
constructor(room: Room, exportType: exportTypes, exportOptions: exportOptions) { constructor(
super(room, exportType, exportOptions); room: Room,
exportType: exportTypes,
exportOptions: exportOptions,
setProgressText: React.Dispatch<React.SetStateAction<string>>,
) {
super(room, exportType, exportOptions, setProgressText);
this.totalSize = 0; this.totalSize = 0;
this.mediaOmitText = !this.exportOptions.attachmentsIncluded this.mediaOmitText = !this.exportOptions.attachmentsIncluded
? _t("Media omitted") ? _t("Media omitted")
@ -79,7 +84,9 @@ export default class PlainTextExporter extends Exporter {
protected async createOutput(events: MatrixEvent[]) { protected async createOutput(events: MatrixEvent[]) {
let content = ""; let content = "";
for (const event of events) { for (let i = 0; i < events.length; i++) {
const event = events[i];
if (i % 100 == 0) this.updateProgress(`Processing event ${i ? i : 1} out of ${events.length}`, false, true);
if (this.cancelled) return this.cleanUp(); if (this.cancelled) return this.cleanUp();
if (!haveTileForEvent(event)) continue; if (!haveTileForEvent(event)) continue;
const textForEvent = await this._textForEvent(event); const textForEvent = await this._textForEvent(event);
@ -89,8 +96,8 @@ export default class PlainTextExporter extends Exporter {
} }
public async export() { public async export() {
console.info("Starting export process..."); this.updateProgress("Starting export process...");
console.info("Fetching events..."); this.updateProgress("Fetching events...");
const fetchStart = performance.now(); const fetchStart = performance.now();
const res = await this.getRequiredEvents(); const res = await this.getRequiredEvents();
@ -98,7 +105,7 @@ export default class PlainTextExporter extends Exporter {
console.log(`Fetched ${res.length} events in ${(fetchEnd - fetchStart)/1000}s`); console.log(`Fetched ${res.length} events in ${(fetchEnd - fetchStart)/1000}s`);
console.info("Creating output..."); this.updateProgress("Creating output...");
const text = await this.createOutput(res); const text = await this.createOutput(res);
if (this.files.length) { if (this.files.length) {