Include a file-safe room name and ISO date in chat exports (#9440)

* conversation export named after room

* sanitization added for exported file name

* sanitization added for exported file name

* sanitization added for exported file name

* sanitization added for exported file name=>lint error fixed

* sanitization added for exported file name=>lint error fixed

* sanitization added for exported file name=>redundancy removed

* sanitization added for exported file name=>redundancy removed

* reverted to previous commit

* sanitization added for exported file name=>redundancy removed

* exported chat date iso formatted

* conversation export named after room

* conversation export named after room

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>

* code refacto filename date format

* Add docs to fn

* Bring in a util library for sanitizing

* Extract file naming function and make consistent for all 3 types

Also use the library we dragged in

* Write tests & associated fixes

* Apply linters locally

* Include new date util in index

Co-authored-by: Sinharitik589 <sinharitik18112835@gmail.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
Co-authored-by: yaya-usman <yayaazeez222@gmail.com>
Co-authored-by: Sinharitik589 <67551927+Sinharitik589@users.noreply.github.com>
This commit is contained in:
Travis Ralston 2022-10-17 19:54:10 -06:00 committed by GitHub
parent ca8b1b04ef
commit 10a429c68d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 233 additions and 90 deletions

View file

@ -1,5 +1,5 @@
/*
Copyright 2021 The Matrix.org Foundation C.I.C.
Copyright 2021 - 2022 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -20,12 +20,13 @@ import { MatrixClient } from "matrix-js-sdk/src/client";
import { Direction } from "matrix-js-sdk/src/models/event-timeline";
import { saveAs } from "file-saver";
import { logger } from "matrix-js-sdk/src/logger";
import sanitizeFilename from "sanitize-filename";
import { MatrixClientPeg } from "../../MatrixClientPeg";
import { ExportType, IExportOptions } from "./exportUtils";
import { decryptFile } from "../DecryptFile";
import { mediaFromContent } from "../../customisations/Media";
import { formatFullDateNoDay } from "../../DateUtils";
import { formatFullDateNoDay, formatFullDateNoDayISO } from "../../DateUtils";
import { isVoiceMessage } from "../EventUtils";
import { IMediaEventContent } from "../../customisations/models/IMediaEventContent";
import { _t } from "../../languageHandler";
@ -57,6 +58,10 @@ export default abstract class Exporter {
window.addEventListener("beforeunload", this.onBeforeUnload);
}
public get destinationFileName(): string {
return this.makeFileNameNoExtension(SdkConfig.get().brand) + ".zip";
}
protected onBeforeUnload(e: BeforeUnloadEvent): string {
e.preventDefault();
return e.returnValue = _t("Are you sure you want to exit during this export?");
@ -75,10 +80,19 @@ export default abstract class Exporter {
this.files.push(file);
}
protected makeFileNameNoExtension(brand = "matrix"): string {
// First try to use the real name of the room, then a translated copy of a generic name,
// then finally hardcoded default to guarantee we'll have a name.
const safeRoomName = sanitizeFilename(this.room.name ?? _t("Unnamed Room")).trim() || "Unnamed Room";
const safeDate = formatFullDateNoDayISO(new Date())
.replace(/:/g, '-'); // ISO format automatically removes a lot of stuff for us
const safeBrand = sanitizeFilename(brand);
return `${safeBrand} - ${safeRoomName} - Chat Export - ${safeDate}`;
}
protected async downloadZIP(): Promise<string | void> {
const brand = SdkConfig.get().brand;
const filenameWithoutExt = `${brand} - Chat Export - ${formatFullDateNoDay(new Date())}`;
const filename = `${filenameWithoutExt}.zip`;
const filename = this.destinationFileName;
const filenameWithoutExt = filename.substring(0, filename.length - 4); // take off the .zip
const { default: JSZip } = await import('jszip');
const zip = new JSZip();