ente/src/services/exportService.ts

97 lines
3.5 KiB
TypeScript
Raw Normal View History

2021-05-30 16:56:48 +00:00
import { runningInBrowser } from 'utils/common';
import { Collection } from './collectionService';
2021-03-29 05:15:08 +00:00
import downloadManager from './downloadManager';
2021-05-30 16:56:48 +00:00
import { File } from './fileService';
2021-03-29 05:15:08 +00:00
enum ExportNotification {
START = 'export started',
IN_PROGRESS = 'export already in progress',
FINISH = 'export finished',
2021-03-31 08:34:00 +00:00
ABORT = 'export aborted',
}
2021-03-29 05:15:08 +00:00
class ExportService {
2021-05-29 06:31:00 +00:00
ElectronAPIs: any = runningInBrowser() && window['ElectronAPIs'];
2021-05-29 06:27:52 +00:00
exportInProgress: Promise<void> = null;
2021-05-29 06:27:52 +00:00
2021-03-31 08:34:00 +00:00
abortExport: boolean = false;
async exportFiles(files: File[], collections: Collection[]) {
if (this.exportInProgress) {
this.ElectronAPIs.sendNotification(ExportNotification.IN_PROGRESS);
return this.exportInProgress;
}
this.exportInProgress = this.fileExporter(files, collections);
return this.exportInProgress;
}
2021-05-29 06:27:52 +00:00
async fileExporter(files: File[], collections: Collection[]) {
try {
const dir = await this.ElectronAPIs.selectRootDirectory();
if (!dir) {
// directory selector closed
return;
}
const exportedFiles: Set<string> = await this.ElectronAPIs.getExportedFiles(
2021-05-29 06:27:52 +00:00
dir,
);
2021-05-29 06:27:52 +00:00
this.ElectronAPIs.showOnTray('starting export');
2021-03-31 08:34:00 +00:00
this.ElectronAPIs.registerStopExportListener(
2021-05-29 06:27:52 +00:00
() => (this.abortExport = true),
2021-03-31 08:34:00 +00:00
);
const collectionIDMap = new Map<number, string>();
2021-05-29 06:27:52 +00:00
for (const collection of collections) {
const collectionFolderPath = `${dir}/${
collection.id
}_${this.sanitizeName(collection.name)}`;
await this.ElectronAPIs.checkExistsAndCreateCollectionDir(
2021-05-29 06:27:52 +00:00
collectionFolderPath,
);
collectionIDMap.set(collection.id, collectionFolderPath);
}
this.ElectronAPIs.sendNotification(ExportNotification.START);
2021-05-29 06:27:52 +00:00
for (const [index, file] of files.entries()) {
2021-03-31 08:34:00 +00:00
if (this.abortExport) {
break;
}
2021-04-04 08:34:42 +00:00
const uid = `${file.id}_${this.sanitizeName(
2021-05-29 06:27:52 +00:00
file.metadata.title,
)}`;
2021-05-29 06:27:52 +00:00
const filePath = `${collectionIDMap.get(file.collectionID)}/${uid}`;
if (!exportedFiles.has(filePath)) {
await this.downloadAndSave(file, filePath);
this.ElectronAPIs.updateExportRecord(dir, filePath);
}
2021-03-31 08:34:00 +00:00
this.ElectronAPIs.showOnTray(
2021-05-29 06:27:52 +00:00
`exporting file ${index + 1} / ${files.length}`,
2021-03-31 08:34:00 +00:00
);
}
2021-03-31 08:34:00 +00:00
this.ElectronAPIs.sendNotification(
2021-05-29 06:27:52 +00:00
this.abortExport ?
ExportNotification.ABORT :
ExportNotification.FINISH,
2021-03-31 08:34:00 +00:00
);
} catch (e) {
console.error(e);
2021-03-31 08:34:00 +00:00
} finally {
this.exportInProgress = null;
this.ElectronAPIs.showOnTray();
this.abortExport = false;
2021-03-29 05:15:08 +00:00
}
}
2021-03-29 11:29:19 +00:00
async downloadAndSave(file: File, path) {
2021-03-29 11:29:19 +00:00
const fileStream = await downloadManager.downloadFile(file);
2021-03-31 06:45:41 +00:00
this.ElectronAPIs.saveStreamToDisk(path, fileStream);
this.ElectronAPIs.saveFileToDisk(
`${path}.json`,
2021-05-29 06:27:52 +00:00
JSON.stringify(file.metadata, null, 2),
2021-03-31 06:45:41 +00:00
);
2021-03-29 11:29:19 +00:00
}
2021-05-29 06:27:52 +00:00
2021-04-04 08:23:00 +00:00
private sanitizeName(name) {
return name.replaceAll('/', '_').replaceAll(' ', '_');
}
2021-03-29 05:15:08 +00:00
}
export default new ExportService();