diff --git a/wowup-electron/ipc-events.ts b/wowup-electron/ipc-events.ts index 6aea993c..309d5cfa 100644 --- a/wowup-electron/ipc-events.ts +++ b/wowup-electron/ipc-events.ts @@ -22,6 +22,7 @@ import { RENAME_DIRECTORY_CHANNEL, READ_FILE_CHANNEL, GET_ASSET_FILE_PATH, + DELETE_FILE_CHANNEL, } from "./src/common/constants"; import { CurseGetScanResultsRequest } from "./src/common/curse/curse-get-scan-results-request"; import { CurseGetScanResultsResponse } from "./src/common/curse/curse-get-scan-results-response"; @@ -132,13 +133,10 @@ ipcMain.on(LIST_DIRECTORIES_CHANNEL, (evt, arg: ValueRequest) => { ipcMain.on(PATH_EXISTS_CHANNEL, (evt, arg: ValueRequest) => { const response: ValueResponse = { value: false }; - fs.open(arg.value, "r", (err, fid) => { + fs.access(arg.value, (err) => { if (err) { - if (err.code === "ENOENT") { - response.value = false; - } else { - response.error = err; - } + console.error(err); + response.value = true; } else { response.value = true; } @@ -243,6 +241,22 @@ ipcMain.on(DELETE_DIRECTORY_CHANNEL, (evt, arg: DeleteDirectoryRequest) => { }); }); +ipcMain.on(DELETE_FILE_CHANNEL, (evt, arg: ValueRequest) => { + console.log("Delete File", arg); + const response: ValueResponse = { + value: false, + }; + fs.unlink(arg.value, (err) => { + if (err) { + response.error = err; + } else { + response.value = true; + } + + evt.reply(arg.responseKey, response); + }); +}); + ipcMain.on(RENAME_DIRECTORY_CHANNEL, (evt, arg: CopyDirectoryRequest) => { console.log("Rename Dir", arg); fs.rename(arg.sourcePath, arg.destinationPath, (err) => { diff --git a/wowup-electron/src/app/services/addons/addon.service.ts b/wowup-electron/src/app/services/addons/addon.service.ts index 219fd9f1..93dd26c8 100644 --- a/wowup-electron/src/app/services/addons/addon.service.ts +++ b/wowup-electron/src/app/services/addons/addon.service.ts @@ -224,12 +224,20 @@ export class AddonService { // TODO track error } finally { - if (fs.existsSync(unzippedDirectory)) { + const unzippedDirectoryExists = await this._fileService.pathExists( + unzippedDirectory + ); + + const downloadedFilePathExists = await this._fileService.pathExists( + downloadedFilePath + ); + + if (unzippedDirectoryExists) { await this._fileService.deleteDirectory(unzippedDirectory); } - if (fs.existsSync(downloadedFilePath)) { - fs.unlinkSync(downloadedFilePath); + if (downloadedFilePathExists) { + await this._fileService.deleteFile(downloadedFilePath); } } diff --git a/wowup-electron/src/app/services/files/file.service.ts b/wowup-electron/src/app/services/files/file.service.ts index 909a696d..30f0a15e 100644 --- a/wowup-electron/src/app/services/files/file.service.ts +++ b/wowup-electron/src/app/services/files/file.service.ts @@ -2,6 +2,7 @@ import { Injectable } from "@angular/core"; import { COPY_DIRECTORY_CHANNEL, DELETE_DIRECTORY_CHANNEL, + DELETE_FILE_CHANNEL, GET_ASSET_FILE_PATH, LIST_DIRECTORIES_CHANNEL, LIST_FILES_CHANNEL, @@ -53,7 +54,11 @@ export class FileService { }); } - public pathExists(sourcePath: string) { + public pathExists(sourcePath: string): Promise { + if (!sourcePath) { + return Promise.resolve(false); + } + return new Promise((resolve, reject) => { const eventHandler = (_evt: any, arg: ValueResponse) => { if (arg.error) { @@ -91,6 +96,25 @@ export class FileService { }); } + public deleteFile(sourcePath: string): Promise { + return new Promise((resolve, reject) => { + const eventHandler = (_evt: any, arg: ValueResponse) => { + if (arg.error) { + return reject(arg.error); + } + resolve(arg.value); + }; + + const request: ValueRequest = { + value: sourcePath, + responseKey: uuidv4(), + }; + + this._electronService.ipcRenderer.once(request.responseKey, eventHandler); + this._electronService.ipcRenderer.send(DELETE_FILE_CHANNEL, request); + }); + } + public copyDirectory(sourcePath: string, destinationPath: string) { return new Promise((resolve, reject) => { const eventHandler = (_evt: any, arg: Error) => { @@ -173,6 +197,14 @@ export class FileService { }); } + public listEntries(sourcePath: string, filter: string) { + const globFilter = globrex(filter); + + return fs + .readdirSync(sourcePath, { withFileTypes: true }) + .filter((entry) => !!globFilter.regex.test(entry.name)); + } + public listFiles(sourcePath: string, filter: string) { const globFilter = globrex(filter); diff --git a/wowup-electron/src/app/services/wowup/wowup.service.ts b/wowup-electron/src/app/services/wowup/wowup.service.ts index be255680..321b1d9e 100644 --- a/wowup-electron/src/app/services/wowup/wowup.service.ts +++ b/wowup-electron/src/app/services/wowup/wowup.service.ts @@ -68,6 +68,8 @@ export class WowUpService { this.applicationVersion = _electronService.remote.app.getVersion(); this.isBetaBuild = this.applicationVersion.toLowerCase().indexOf("beta") != -1; + + this.cleanupDownloads(); } public get updaterExists() { @@ -308,4 +310,28 @@ export class WowUpService { ? WowUpReleaseChannelType.Beta : WowUpReleaseChannelType.Stable; } + + /** + * Clean up lost downloads in the download folder + */ + private async cleanupDownloads() { + const downloadFiles = this._fileService.listEntries( + this.applicationDownloadsFolderPath, + "*" + ); + + for (let entry of downloadFiles) { + const path = join(this.applicationDownloadsFolderPath, entry.name); + try { + if (entry.isDirectory()) { + await this._fileService.deleteDirectory(path); + } else { + await this._fileService.deleteFile(path); + } + } catch (e) { + console.error("Failed to delete download entry", path); + console.error(e); + } + } + } } diff --git a/wowup-electron/src/common/constants.ts b/wowup-electron/src/common/constants.ts index b98d2094..f83cd8b5 100644 --- a/wowup-electron/src/common/constants.ts +++ b/wowup-electron/src/common/constants.ts @@ -1,6 +1,7 @@ export const DOWNLOAD_FILE_CHANNEL = "download-file"; export const COPY_DIRECTORY_CHANNEL = "copy-directory"; export const DELETE_DIRECTORY_CHANNEL = "delete-directory"; +export const DELETE_FILE_CHANNEL = "delete-file"; export const RENAME_DIRECTORY_CHANNEL = "rename-directory"; export const STAT_DIRECTORY_CHANNEL = "stat-directory"; export const LIST_DIRECTORIES_CHANNEL = "list-directories";