mirror of
https://github.com/WowUp/WowUp.git
synced 2026-04-18 04:48:01 -04:00
Start controller pattern
Various fixes
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,14 +414,8 @@ export class AddonService {
|
||||
: [];
|
||||
}
|
||||
|
||||
public async getAllAddonsAvailableForUpdate(wowInstallation?: WowInstallation): Promise<Addon[]> {
|
||||
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<Addon[]> {
|
||||
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<Addon[]> {
|
||||
return await this._addonStorage.queryAllAsync((addon) => {
|
||||
return addon.isIgnored !== true && addon.autoUpdateEnabled && !!addon.installationId;
|
||||
});
|
||||
public getAutoUpdateEnabledAddons(): Promise<Addon[]> {
|
||||
return this._addonStorage.getAutoUpdateEnabled();
|
||||
}
|
||||
|
||||
public async getAllByExternalAddonId(externalAddonIds: string[]): Promise<Addon[]> {
|
||||
return await this._addonStorage.queryAllAsync((addon) => {
|
||||
return externalAddonIds.includes(addon.externalId);
|
||||
});
|
||||
public getAllByExternalAddonId(externalAddonIds: string[]): Promise<Addon[]> {
|
||||
return this._addonStorage.getByExternalIds(externalAddonIds);
|
||||
}
|
||||
|
||||
public async hasAnyWithExternalAddonIds(externalAddonIds: string[]): Promise<boolean> {
|
||||
|
||||
@@ -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<Addon[]> {
|
||||
return await this._electronService.invoke(IPC_STORE_GET_ALL, ADDON_STORE_NAME);
|
||||
}
|
||||
|
||||
public async queryAsync<T>(action: (store: Addon[]) => T): Promise<T> {
|
||||
const store = await this.getStore();
|
||||
return action(store);
|
||||
}
|
||||
|
||||
public async queryAllAsync(action: (item: Addon) => boolean): Promise<Addon[]> {
|
||||
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<void> {
|
||||
public saveAll(addons: Addon[]): Promise<void> {
|
||||
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<void> {
|
||||
@@ -71,58 +57,31 @@ export class AddonStorageService {
|
||||
await this.removeAllAsync(...addons);
|
||||
}
|
||||
|
||||
public async getByExternalIdAsync(
|
||||
externalId: string,
|
||||
providerName: string,
|
||||
installationId: string
|
||||
): Promise<Addon | undefined> {
|
||||
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<Addon[]> {
|
||||
return this._electronService.invoke(IPC_ADDONS_GET_ALL);
|
||||
}
|
||||
|
||||
public async getAll(): Promise<Addon[]> {
|
||||
return await this.getStore();
|
||||
public getAllForInstallationIdAsync(installationId: string): Promise<Addon[]> {
|
||||
return this._electronService.invoke(IPC_ADDONS_GET_ALL_FOR_INSTALLATION, installationId);
|
||||
}
|
||||
|
||||
public async getAllForInstallationIdAsync(
|
||||
installationId: string,
|
||||
validator?: (addon: Addon) => boolean
|
||||
): Promise<Addon[]> {
|
||||
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<Addon[]> {
|
||||
return this._electronService.invoke(IPC_ADDONS_GET_ALL_FOR_PROVIDER, providerName);
|
||||
}
|
||||
|
||||
public async getAllForProviderAsync(providerName: string, validator?: (addon: Addon) => boolean): Promise<Addon[]> {
|
||||
const addons: Addon[] = [];
|
||||
const store = await this.getStore();
|
||||
public getByExternalIdAsync(externalId: string, providerName: string, installationId: string): Promise<Addon | undefined> {
|
||||
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<Addon[]> {
|
||||
return this._electronService.invoke(IPC_ADDONS_GET_BY_EXTERNAL_IDS, externalIds);
|
||||
}
|
||||
|
||||
return addons;
|
||||
public getAvailableForUpdate(installationId?: string): Promise<Addon[]> {
|
||||
return this._electronService.invoke(IPC_ADDONS_GET_AVAILABLE_FOR_UPDATE, installationId);
|
||||
}
|
||||
|
||||
public getAutoUpdateEnabled(): Promise<Addon[]> {
|
||||
return this._electronService.invoke(IPC_ADDONS_GET_AUTO_UPDATE_ENABLED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,16 @@ export class PatchNotesService {
|
||||
}
|
||||
|
||||
const CHANGELOGS: ChangeLog[] = [
|
||||
{
|
||||
Version: "2.22.1",
|
||||
html: `
|
||||
<h4>Fixes</h4>
|
||||
<ul>
|
||||
<li>Update electron versions</li>
|
||||
<li>Various bug fixes</li>
|
||||
</ul>
|
||||
`,
|
||||
},
|
||||
{
|
||||
Version: "2.22.0",
|
||||
html: `
|
||||
|
||||
@@ -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";
|
||||
|
||||
7
wowup-electron/src/common/wowup.d.ts
vendored
7
wowup-electron/src/common/wowup.d.ts
vendored
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user