mirror of
https://github.com/element-hq/element-web.git
synced 2024-12-14 18:41:30 +03:00
Display progress
This commit is contained in:
parent
08d886e9d1
commit
6ca664636e
5 changed files with 56 additions and 21 deletions
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue