diff --git a/wowup-electron/app/controllers/addon.controller.ts b/wowup-electron/app/controllers/addon.controller.ts index cff47688..2bdec28b 100644 --- a/wowup-electron/app/controllers/addon.controller.ts +++ b/wowup-electron/app/controllers/addon.controller.ts @@ -3,7 +3,16 @@ import * as Store from "electron-store"; import * as log from "electron-log/main"; import { Addon } from "wowup-lib-core"; -import { IPC_ADDONS_SAVE_ALL } from "../../src/common/constants"; +import { + IPC_ADDONS_GET_ALL, + IPC_ADDONS_GET_ALL_FOR_INSTALLATION, + IPC_ADDONS_GET_ALL_FOR_PROVIDER, + IPC_ADDONS_GET_AUTO_UPDATE_ENABLED, + IPC_ADDONS_GET_AVAILABLE_FOR_UPDATE, + IPC_ADDONS_GET_BY_EXTERNAL_ID, + IPC_ADDONS_GET_BY_EXTERNAL_IDS, + IPC_ADDONS_SAVE_ALL, +} from "../../src/common/constants"; import { IpcController } from "./ipc-controller"; export class AddonController implements IpcController { @@ -11,6 +20,95 @@ export class AddonController implements IpcController { public register(): void { ipcMain.handle(IPC_ADDONS_SAVE_ALL, (_evt, addons: Addon[]) => this.saveAll(addons)); + ipcMain.handle(IPC_ADDONS_GET_ALL, () => this.getAll()); + ipcMain.handle(IPC_ADDONS_GET_ALL_FOR_INSTALLATION, (_evt, installationId: string) => this.getAllForInstallation(installationId)); + ipcMain.handle(IPC_ADDONS_GET_ALL_FOR_PROVIDER, (_evt, providerName: string) => this.getAllForProvider(providerName)); + ipcMain.handle(IPC_ADDONS_GET_BY_EXTERNAL_ID, (_evt, externalId: string, providerName: string, installationId: string) => this.getByExternalId(externalId, providerName, installationId)); + ipcMain.handle(IPC_ADDONS_GET_BY_EXTERNAL_IDS, (_evt, externalIds: string[]) => this.getByExternalIds(externalIds)); + ipcMain.handle(IPC_ADDONS_GET_AVAILABLE_FOR_UPDATE, (_evt, installationId?: string) => this.getAvailableForUpdate(installationId)); + ipcMain.handle(IPC_ADDONS_GET_AUTO_UPDATE_ENABLED, () => this.getAutoUpdateEnabled()); + } + + private getAll(): Addon[] { + return [...this.addonStore].map(([, addon]) => addon as Addon); + } + + private getAllForInstallation(installationId: string): Addon[] { + const addons: Addon[] = []; + for (const [, addon] of this.addonStore) { + if ((addon as Addon).installationId === installationId) { + addons.push(addon as Addon); + } + } + return addons; + } + + private getAllForProvider(providerName: string): Addon[] { + const addons: Addon[] = []; + for (const [, addon] of this.addonStore) { + if ((addon as Addon).providerName === providerName) { + addons.push(addon as Addon); + } + } + return addons; + } + + private getByExternalId(externalId: string, providerName: string, installationId: string): Addon | undefined { + for (const [, addon] of this.addonStore) { + const a = addon as Addon; + if (a.installationId === installationId && a.externalId === externalId && a.providerName === providerName) { + return a; + } + } + return undefined; + } + + private getByExternalIds(externalIds: string[]): Addon[] { + const addons: Addon[] = []; + for (const [, addon] of this.addonStore) { + const a = addon as Addon; + if (a.externalId && externalIds.includes(a.externalId)) { + addons.push(a); + } + } + return addons; + } + + private getAvailableForUpdate(installationId?: string): Addon[] { + const addons: Addon[] = []; + for (const [, addon] of this.addonStore) { + const a = addon as Addon; + if (installationId && a.installationId !== installationId) { + continue; + } + if (a.isIgnored !== true && this.needsUpdate(a)) { + addons.push(a); + } + } + return addons; + } + + private getAutoUpdateEnabled(): Addon[] { + const addons: Addon[] = []; + for (const [, addon] of this.addonStore) { + const a = addon as Addon; + if (a.isIgnored !== true && a.autoUpdateEnabled && !!a.installationId) { + addons.push(a); + } + } + return addons; + } + + private needsUpdate(addon: Addon): boolean { + if (addon.isIgnored) { + return false; + } + if (addon.externalLatestReleaseId && addon.externalLatestReleaseId !== addon.installedExternalReleaseId) { + return true; + } + const installedVer = (addon.installedVersion ?? "").replace(/^v/i, ""); + const latestVer = (addon.latestVersion ?? "").replace(/^v/i, ""); + return installedVer.length > 0 && installedVer !== latestVer; } private saveAll(addons: Addon[]): void { diff --git a/wowup-electron/app/ipc-events.ts b/wowup-electron/app/ipc-events.ts index 264a8137..a7f3d222 100644 --- a/wowup-electron/app/ipc-events.ts +++ b/wowup-electron/app/ipc-events.ts @@ -370,7 +370,7 @@ export function initializeIpcHandlers(window: BrowserWindow): void { try { await fsp.access(filePath); } catch (e) { - if (e.code !== "ENOENT") { + if ((e as NodeJS.ErrnoException).code !== "ENOENT") { log.error(e); } return false; @@ -739,7 +739,7 @@ export function initializeIpcHandlers(window: BrowserWindow): void { } catch (err) { log.error(err); status.type = DownloadStatusType.Error; - status.error = err; + status.error = err instanceof Error ? err : undefined; window.webContents.send(arg.responseKey, status); } } @@ -765,18 +765,19 @@ function handleZipFile(err: Error | null, zipfile: yauzl.ZipFile, targetDir: str if (/\/$/.test(entry.fileName)) { // directory file names end with '/' const dirPath = path.join(targetDir, entry.fileName); - fs.mkdir(dirPath, { recursive: true }, function () { - if (err) throw err; + fs.mkdir(dirPath, { recursive: true }, function (mkdirErr) { + if (mkdirErr) return reject(mkdirErr); zipfile.readEntry(); }); } else { // ensure parent directory exists const filePath = path.join(targetDir, entry.fileName); const parentPath = path.join(targetDir, path.dirname(entry.fileName)); - fs.mkdir(parentPath, { recursive: true }, function () { + fs.mkdir(parentPath, { recursive: true }, function (mkdirErr) { + if (mkdirErr) return reject(mkdirErr); zipfile.openReadStream(entry, (err, readStream) => { if (err) { - throw err; + return reject(err); } const filter = new Transform(); diff --git a/wowup-electron/app/main.ts b/wowup-electron/app/main.ts index e9657b36..6ac4e4cf 100644 --- a/wowup-electron/app/main.ts +++ b/wowup-electron/app/main.ts @@ -279,7 +279,7 @@ function createWindow(): BrowserWindow { transparent: false, resizable: true, backgroundColor: getBackgroundColor(), - title: "WowUp" + AppEnv.buildFlavor === "ow" ? " CF" : "", + title: "WowUp" + (AppEnv.buildFlavor === "ow" ? " CF" : ""), titleBarStyle: "hidden", webPreferences: { preload: join(__dirname, "preload.js"), @@ -327,8 +327,6 @@ function createWindow(): BrowserWindow { initializeStoreIpcHandlers(); registerControllers({ window: win, addonStore: getAddonStore() }); - - if (AppEnv.buildFlavor === "wago") { wagoHandler.initialize(win); } @@ -377,8 +375,6 @@ function createWindow(): BrowserWindow { if (["background-sync"].includes(permission)) { return true; } - - log.warn("[webview] setPermissionCheckHandler", permission, origin); return false; }); @@ -445,12 +441,10 @@ function createWindow(): BrowserWindow { } win?.webContents.session.setPermissionRequestHandler((contents, permission, callback) => { - log.warn("win setPermissionRequestHandler", permission); return callback(false); }); win?.webContents.session.setPermissionCheckHandler(() => { - // log.warn("win setPermissionCheckHandler", permission, origin); return false; }); diff --git a/wowup-electron/app/utils/gpu-cache-buster.ts b/wowup-electron/app/utils/gpu-cache-buster.ts index 995992d9..90c23fd3 100644 --- a/wowup-electron/app/utils/gpu-cache-buster.ts +++ b/wowup-electron/app/utils/gpu-cache-buster.ts @@ -30,8 +30,8 @@ export function validateGpuCache(app: Electron.App) { if (verFile === undefined) { removeDir(cacheDir); } else { - const verFile = readVersionFile(cacheDir); - if (verFile.version !== app.getVersion()) { + const verFileData = readVersionFile(cacheDir); + if (verFileData.version !== app.getVersion()) { removeDir(cacheDir); } else { return; @@ -39,7 +39,7 @@ export function validateGpuCache(app: Electron.App) { } } - fs.mkdirSync(cacheDir); + fs.mkdirSync(cacheDir, { recursive: true }); createVersionFile(app.getVersion(), cacheDir); } catch (e) { log.error("failed to validate GPU Cache", e); @@ -57,7 +57,7 @@ function fileExists(path: string) { return true; } catch (e) { log.warn(`File does not exist: ${path}`); - log.warn(e.message); + log.warn((e as Error).message); return false; } } diff --git a/wowup-electron/src/app/services/addons/addon.service.ts b/wowup-electron/src/app/services/addons/addon.service.ts index 4569e1e7..5139f16a 100644 --- a/wowup-electron/src/app/services/addons/addon.service.ts +++ b/wowup-electron/src/app/services/addons/addon.service.ts @@ -414,14 +414,8 @@ export class AddonService { : []; } - public async getAllAddonsAvailableForUpdate(wowInstallation?: WowInstallation): Promise { - return await this._addonStorage.queryAllAsync((addon) => { - if (typeof wowInstallation === "object" && wowInstallation.id !== addon.installationId) { - return false; - } - - return addon.isIgnored !== true && AddonUtils.needsUpdate(addon); - }); + public getAllAddonsAvailableForUpdate(wowInstallation?: WowInstallation): Promise { + return this._addonStorage.getAvailableForUpdate(wowInstallation?.id); } public async installDependencies( @@ -500,16 +494,12 @@ export class AddonService { return results.filter((res) => res !== undefined).map((res) => res as Addon); } - public async getAutoUpdateEnabledAddons(): Promise { - return await this._addonStorage.queryAllAsync((addon) => { - return addon.isIgnored !== true && addon.autoUpdateEnabled && !!addon.installationId; - }); + public getAutoUpdateEnabledAddons(): Promise { + return this._addonStorage.getAutoUpdateEnabled(); } - public async getAllByExternalAddonId(externalAddonIds: string[]): Promise { - return await this._addonStorage.queryAllAsync((addon) => { - return externalAddonIds.includes(addon.externalId); - }); + public getAllByExternalAddonId(externalAddonIds: string[]): Promise { + return this._addonStorage.getByExternalIds(externalAddonIds); } public async hasAnyWithExternalAddonIds(externalAddonIds: string[]): Promise { diff --git a/wowup-electron/src/app/services/storage/addon-storage.service.ts b/wowup-electron/src/app/services/storage/addon-storage.service.ts index 840c3e78..a71bb6fd 100644 --- a/wowup-electron/src/app/services/storage/addon-storage.service.ts +++ b/wowup-electron/src/app/services/storage/addon-storage.service.ts @@ -2,12 +2,18 @@ import { Injectable } from "@angular/core"; import { Addon } from "wowup-lib-core"; import { + IPC_ADDONS_GET_ALL, + IPC_ADDONS_GET_ALL_FOR_INSTALLATION, + IPC_ADDONS_GET_ALL_FOR_PROVIDER, + IPC_ADDONS_GET_AUTO_UPDATE_ENABLED, + IPC_ADDONS_GET_AVAILABLE_FOR_UPDATE, + IPC_ADDONS_GET_BY_EXTERNAL_ID, + IPC_ADDONS_GET_BY_EXTERNAL_IDS, IPC_ADDONS_SAVE_ALL, ADDON_STORE_NAME, IPC_STORE_SET_OBJECT, IPC_STORE_GET_OBJECT, IPC_STORE_REMOVE_OBJECT, - IPC_STORE_GET_ALL, } from "../../../common/constants"; import { ElectronService } from "../electron/electron.service"; @@ -16,30 +22,10 @@ import { ElectronService } from "../electron/electron.service"; }) export class AddonStorageService { public constructor(private _electronService: ElectronService) {} - private async getStore(): Promise { - return await this._electronService.invoke(IPC_STORE_GET_ALL, ADDON_STORE_NAME); - } - public async queryAsync(action: (store: Addon[]) => T): Promise { - const store = await this.getStore(); - return action(store); - } - - public async queryAllAsync(action: (item: Addon) => boolean): Promise { - const addons: Addon[] = []; - const store = await this.getStore(); - for (const addon of store) { - if (action(addon)) { - addons.push(addon); - } - } - - return addons; - } - - public async saveAll(addons: Addon[]): Promise { + public saveAll(addons: Addon[]): Promise { console.debug(`[addon-storage] save all: ${addons?.length ?? 0}`); - await this._electronService.invoke(IPC_ADDONS_SAVE_ALL, addons); + return this._electronService.invoke(IPC_ADDONS_SAVE_ALL, addons); } public setAsync(key: string | undefined, value: Addon): Promise { @@ -71,58 +57,31 @@ export class AddonStorageService { await this.removeAllAsync(...addons); } - public async getByExternalIdAsync( - externalId: string, - providerName: string, - installationId: string - ): Promise { - const addons: Addon[] = []; - const store = await this.getStore(); - - for (const addon of store) { - if ( - addon.installationId === installationId && - addon.externalId === externalId && - addon.providerName === providerName - ) { - addons.push(addon); - break; - } - } - - return addons[0]; + public getAll(): Promise { + return this._electronService.invoke(IPC_ADDONS_GET_ALL); } - public async getAll(): Promise { - return await this.getStore(); + public getAllForInstallationIdAsync(installationId: string): Promise { + return this._electronService.invoke(IPC_ADDONS_GET_ALL_FOR_INSTALLATION, installationId); } - public async getAllForInstallationIdAsync( - installationId: string, - validator?: (addon: Addon) => boolean - ): Promise { - const addons: Addon[] = []; - const store = await this.getStore(); - - for (const addon of store) { - if (addon.installationId === installationId && (!validator || validator(addon))) { - addons.push(addon); - } - } - - return addons; + public getAllForProviderAsync(providerName: string): Promise { + return this._electronService.invoke(IPC_ADDONS_GET_ALL_FOR_PROVIDER, providerName); } - public async getAllForProviderAsync(providerName: string, validator?: (addon: Addon) => boolean): Promise { - const addons: Addon[] = []; - const store = await this.getStore(); + public getByExternalIdAsync(externalId: string, providerName: string, installationId: string): Promise { + return this._electronService.invoke(IPC_ADDONS_GET_BY_EXTERNAL_ID, externalId, providerName, installationId); + } - for (const addon of store) { - if (addon.providerName === providerName && (!validator || validator(addon))) { - addons.push(addon); - } - } + public getByExternalIds(externalIds: string[]): Promise { + return this._electronService.invoke(IPC_ADDONS_GET_BY_EXTERNAL_IDS, externalIds); + } - return addons; + public getAvailableForUpdate(installationId?: string): Promise { + return this._electronService.invoke(IPC_ADDONS_GET_AVAILABLE_FOR_UPDATE, installationId); + } + + public getAutoUpdateEnabled(): Promise { + return this._electronService.invoke(IPC_ADDONS_GET_AUTO_UPDATE_ENABLED); } } diff --git a/wowup-electron/src/app/services/wowup/patch-notes.service.ts b/wowup-electron/src/app/services/wowup/patch-notes.service.ts index 7a2ebee6..0c271bff 100644 --- a/wowup-electron/src/app/services/wowup/patch-notes.service.ts +++ b/wowup-electron/src/app/services/wowup/patch-notes.service.ts @@ -15,6 +15,16 @@ export class PatchNotesService { } const CHANGELOGS: ChangeLog[] = [ + { + Version: "2.22.1", + html: ` +

Fixes

+
    +
  • Update electron versions
  • +
  • Various bug fixes
  • +
+ `, + }, { Version: "2.22.0", html: ` diff --git a/wowup-electron/src/common/constants.ts b/wowup-electron/src/common/constants.ts index 9f00a1f0..68a56c2a 100644 --- a/wowup-electron/src/common/constants.ts +++ b/wowup-electron/src/common/constants.ts @@ -86,6 +86,13 @@ export const IPC_REMOVE_AS_DEFAULT_PROTOCOL_CLIENT = "remove-as-default-protocol export const IPC_REQUEST_INSTALL_FROM_URL = "request-install-from-url"; export const IPC_CUSTOM_PROTOCOL_RECEIVED = "custom-protocol-received"; export const IPC_ADDONS_SAVE_ALL = "addons-save-all"; +export const IPC_ADDONS_GET_ALL_FOR_INSTALLATION = "addons-get-all-for-installation"; +export const IPC_ADDONS_GET_ALL_FOR_PROVIDER = "addons-get-all-for-provider"; +export const IPC_ADDONS_GET_ALL = "addons-get-all"; +export const IPC_ADDONS_GET_BY_EXTERNAL_ID = "addons-get-by-external-id"; +export const IPC_ADDONS_GET_BY_EXTERNAL_IDS = "addons-get-by-external-ids"; +export const IPC_ADDONS_GET_AVAILABLE_FOR_UPDATE = "addons-get-available-for-update"; +export const IPC_ADDONS_GET_AUTO_UPDATE_ENABLED = "addons-get-auto-update-enabled"; export const IPC_GET_PENDING_OPEN_URLS = "get-pending-open-urls"; export const IPC_GET_LATEST_DIR_UPDATE_TIME = "get-latest-dir-update-time"; export const IPC_LIST_DIR_RECURSIVE = "list-dir-recursive"; diff --git a/wowup-electron/src/common/wowup.d.ts b/wowup-electron/src/common/wowup.d.ts index b6f5c0a1..664cce0d 100644 --- a/wowup-electron/src/common/wowup.d.ts +++ b/wowup-electron/src/common/wowup.d.ts @@ -25,6 +25,13 @@ declare type MainChannels = // Events that can be sent from renderer to main declare type RendererChannels = + | "addons-get-all" + | "addons-get-all-for-installation" + | "addons-get-all-for-provider" + | "addons-get-auto-update-enabled" + | "addons-get-available-for-update" + | "addons-get-by-external-id" + | "addons-get-by-external-ids" | "addons-save-all" | "app-install-update" | "app-update-check-for-update"