diff --git a/src/services/exportService.ts b/src/services/exportService.ts index c4e4a7a53..fbdae33b2 100644 --- a/src/services/exportService.ts +++ b/src/services/exportService.ts @@ -59,7 +59,10 @@ import { ElectronAPIs } from 'types/electron'; import { CustomError } from 'utils/error'; import { addLocalLog, addLogLine } from 'utils/logging'; import { eventBus, Events } from './events'; -import { getCollectionNameMap } from 'utils/collection'; +import { + getCollectionNameMap, + getNonEmptyPersonalCollections, +} from 'utils/collection'; const EXPORT_RECORD_FILE_NAME = 'export_status.json'; @@ -166,7 +169,16 @@ class ExportService { getFileExportStats = async (): Promise => { try { const exportRecord = await this.getExportRecord(); - const userPersonalFiles = await getPersonalFiles(); + const user: User = getData(LS_KEYS.USER); + const files = await getLocalFiles(); + const collections = await getLocalCollections(); + const userPersonalFiles = await getPersonalFiles(files, user); + const userNonEmptyPersonalCollections = + await getNonEmptyPersonalCollections( + collections, + userPersonalFiles, + user + ); const unExportedFiles = getUnExportedFiles( userPersonalFiles, exportRecord @@ -175,10 +187,21 @@ class ExportService { userPersonalFiles, exportRecord ); + const renamedCollections = getRenamedCollections( + userNonEmptyPersonalCollections, + exportRecord + ); + const deletedCollections = getDeletedExportedCollections( + userNonEmptyPersonalCollections, + exportRecord + ); return { totalCount: userPersonalFiles.length, pendingCount: - unExportedFiles.length + deletedExportedFiles.length, + unExportedFiles.length + + deletedExportedFiles.length + + renamedCollections.length + + deletedCollections.length, }; } catch (e) { logError(e, 'getUpdateFileLists failed'); @@ -249,61 +272,55 @@ class ExportService { return; } const user: User = getData(LS_KEYS.USER); - - const localFiles = await getLocalFiles(); - const userPersonalFiles = mergeMetadata( - localFiles - .filter((file) => file.ownerID === user?.id) - .sort((fileA, fileB) => fileA.id - fileB.id) - ); - + const files = await getLocalFiles(); const collections = await getLocalCollections(); - const nonEmptyCollections = getNonEmptyCollections( - collections, - userPersonalFiles - ); - const userCollections = nonEmptyCollections - .filter((collection) => collection.owner.id === user?.id) - .sort( - (collectionA, collectionB) => - collectionA.id - collectionB.id + const personalFiles = await getPersonalFiles(files, user); + const nonEmptyPersonalCollections = + await getNonEmptyPersonalCollections( + collections, + personalFiles, + user ); const exportRecord = await this.getExportRecord(exportDir); const collectionIDPathMap = convertCollectionIDPathObjectToMap( exportRecord.exportedCollectionPaths ); - const collectionIDNameMap = getCollectionNameMap(collections); + const collectionIDNameMap = getCollectionNameMap( + nonEmptyPersonalCollections + ); const renamedCollections = getRenamedCollections( - userCollections, + nonEmptyPersonalCollections, + exportRecord + ); + + const removedFileUIDs = getDeletedExportedFiles( + personalFiles, + exportRecord + ); + const filesToExport = getUnExportedFiles( + personalFiles, + exportRecord + ); + const deletedExportedCollections = getDeletedExportedCollections( + nonEmptyPersonalCollections, exportRecord ); if ( - renamedCollections?.length > 0 && - this.checkAllElectronAPIsExists() + removedFileUIDs.length > 0 || + filesToExport.length > 0 || + renamedCollections.length > 0 || + deletedExportedCollections.length > 0 ) { - addLogLine(`renaming ${renamedCollections.length} collections`); - this.collectionRenamer( - exportDir, - collectionIDPathMap, - renamedCollections - ); - } - - const removedFileUIDs = getDeletedExportedFiles( - userPersonalFiles, - exportRecord - ); - const filesToExport = getUnExportedFiles( - userPersonalFiles, - exportRecord - ); - - if (removedFileUIDs?.length > 0 || filesToExport?.length > 0) { let success = 0; let failed = 0; + this.uiUpdater.updateExportProgress({ + success: success, + failed: failed, + total: removedFileUIDs.length + filesToExport.length, + }); const incrementSuccess = () => { this.updateExportProgress({ success: ++success, @@ -318,6 +335,21 @@ class ExportService { total: removedFileUIDs.length + filesToExport.length, }); }; + if ( + renamedCollections?.length > 0 && + this.checkAllElectronAPIsExists() + ) { + addLogLine( + `renaming ${renamedCollections.length} collections` + ); + this.collectionRenamer( + exportDir, + collectionIDPathMap, + renamedCollections, + incrementSuccess, + incrementFailed + ); + } if (removedFileUIDs?.length > 0) { addLogLine(`removing ${removedFileUIDs.length} files`); @@ -339,21 +371,17 @@ class ExportService { incrementFailed ); } - } - - const deletedExportedCollections = getDeletedExportedCollections( - userCollections, - exportRecord - ); - - if (deletedExportedCollections?.length > 0) { - addLogLine( - `removing ${deletedExportedCollections.length} collections` - ); - await this.collectionRemover( - deletedExportedCollections, - exportDir - ); + if (deletedExportedCollections?.length > 0) { + addLogLine( + `removing ${deletedExportedCollections.length} collections` + ); + await this.collectionRemover( + deletedExportedCollections, + exportDir, + incrementSuccess, + incrementFailed + ); + } } } catch (e) { logError(e, 'runExport failed'); @@ -363,7 +391,9 @@ class ExportService { async collectionRenamer( exportFolder: string, collectionIDPathMap: Map, - renamedCollections: Collection[] + renamedCollections: Collection[], + incrementSuccess: () => void, + incrementFailed: () => void ) { try { for (const collection of renamedCollections) { @@ -396,7 +426,9 @@ class ExportService { collection.id, newCollectionFolderPath ); + incrementSuccess(); } catch (e) { + incrementFailed(); logError(e, 'collectionRenamer failed a collection'); if ( e.message === @@ -414,7 +446,9 @@ class ExportService { async collectionRemover( deletedExportedCollectionIDs: number[], - exportFolder: string + exportFolder: string, + incrementSuccess: () => void, + incrementFailed: () => void ) { try { const exportRecord = await this.getExportRecord(exportFolder); @@ -438,7 +472,9 @@ class ExportService { exportFolder, collectionID ); + incrementSuccess(); } catch (e) { + incrementFailed(); logError(e, 'collectionRemover failed a collection'); if ( e.message === @@ -459,8 +495,8 @@ class ExportService { collectionIDNameMap: Map, collectionIDPathMap: Map, exportDir: string, - incrementSuccess, - incrementFailed + incrementSuccess: () => void, + incrementFailed: () => void ): Promise { try { for (const file of files) { diff --git a/src/utils/collection/index.ts b/src/utils/collection/index.ts index de31444f5..9646e68ec 100644 --- a/src/utils/collection/index.ts +++ b/src/utils/collection/index.ts @@ -1,5 +1,6 @@ import { addToCollection, + getNonEmptyCollections, moveToCollection, removeFromCollection, restoreToCollection, @@ -272,3 +273,21 @@ export function getCollectionNameMap( collections.map((collection) => [collection.id, collection.name]) ); } + +export async function getNonEmptyPersonalCollections( + collections: Collection[], + personalFiles: EnteFile[], + user: User +): Promise { + if (!user?.id) { + throw Error('user missing'); + } + const nonEmptyCollections = getNonEmptyCollections( + collections, + personalFiles + ); + const personalCollections = nonEmptyCollections + .filter((collection) => collection.owner.id === user?.id) + .sort((collectionA, collectionB) => collectionA.id - collectionB.id); + return personalCollections; +} diff --git a/src/utils/file/index.ts b/src/utils/file/index.ts index af6df2796..ca1e885e9 100644 --- a/src/utils/file/index.ts +++ b/src/utils/file/index.ts @@ -31,7 +31,6 @@ import { addLogLine } from 'utils/logging'; import { CustomError } from 'utils/error'; import { convertBytesToHumanReadable } from './size'; import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker'; -import { getLocalFiles } from 'services/fileService'; const WAIT_TIME_IMAGE_CONVERSION = 30 * 1000; @@ -577,9 +576,7 @@ export function getLatestVersionFiles(files: EnteFile[]) { ); } -export async function getPersonalFiles() { - const files = await getLocalFiles(); - const user: User = getData(LS_KEYS.USER); +export async function getPersonalFiles(files: EnteFile[], user: User) { if (!user?.id) { throw Error('user missing'); }