mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-24 03:11:03 +00:00
fix: fixing css issues
This commit is contained in:
@@ -1,47 +1,8 @@
|
||||
import type { AppUpdaterEvent } from "@types";
|
||||
import { registerEvent } from "../register-event";
|
||||
import updater, { UpdateInfo } from "electron-updater";
|
||||
import { WindowManager } from "@main/services";
|
||||
import { app } from "electron";
|
||||
import { publishNotificationUpdateReadyToInstall } from "@main/services/notifications";
|
||||
|
||||
const { autoUpdater } = updater;
|
||||
|
||||
const sendEvent = (event: AppUpdaterEvent) => {
|
||||
WindowManager.mainWindow?.webContents.send("autoUpdaterEvent", event);
|
||||
};
|
||||
|
||||
const sendEventsForDebug = false;
|
||||
|
||||
const isAutoInstallAvailable =
|
||||
process.platform !== "darwin" && process.env.PORTABLE_EXECUTABLE_FILE == null;
|
||||
|
||||
const mockValuesForDebug = () => {
|
||||
sendEvent({ type: "update-available", info: { version: "1.3.0" } });
|
||||
sendEvent({ type: "update-downloaded" });
|
||||
};
|
||||
|
||||
const newVersionInfo = { version: "" };
|
||||
import { UpdateManager } from "@main/services/update-manager";
|
||||
|
||||
const checkForUpdates = async (_event: Electron.IpcMainInvokeEvent) => {
|
||||
autoUpdater
|
||||
.once("update-available", (info: UpdateInfo) => {
|
||||
sendEvent({ type: "update-available", info });
|
||||
newVersionInfo.version = info.version;
|
||||
})
|
||||
.once("update-downloaded", () => {
|
||||
sendEvent({ type: "update-downloaded" });
|
||||
publishNotificationUpdateReadyToInstall(newVersionInfo.version);
|
||||
});
|
||||
|
||||
if (app.isPackaged) {
|
||||
autoUpdater.autoDownload = isAutoInstallAvailable;
|
||||
autoUpdater.checkForUpdates();
|
||||
} else if (sendEventsForDebug) {
|
||||
mockValuesForDebug();
|
||||
}
|
||||
|
||||
return isAutoInstallAvailable;
|
||||
return UpdateManager.checkForUpdates();
|
||||
};
|
||||
|
||||
registerEvent("checkForUpdates", checkForUpdates);
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
import { registerEvent } from "../register-event";
|
||||
|
||||
const checkFolderWritePermission = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
path: string
|
||||
) =>
|
||||
new Promise((resolve) => {
|
||||
fs.access(path, fs.constants.W_OK, (err) => {
|
||||
resolve(!err);
|
||||
});
|
||||
});
|
||||
testPath: string
|
||||
) => {
|
||||
const testFilePath = path.join(testPath, ".hydra-write-test");
|
||||
|
||||
try {
|
||||
fs.writeFileSync(testFilePath, "");
|
||||
fs.rmSync(testFilePath);
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
registerEvent("checkFolderWritePermission", checkFolderWritePermission);
|
||||
|
||||
@@ -3,15 +3,14 @@ import { db, levelKeys } from "@main/level";
|
||||
import type { UserPreferences } from "@types";
|
||||
|
||||
export const getDownloadsPath = async () => {
|
||||
const userPreferences = await db.get<string, UserPreferences>(
|
||||
const userPreferences = await db.get<string, UserPreferences | null>(
|
||||
levelKeys.userPreferences,
|
||||
{
|
||||
valueEncoding: "json",
|
||||
}
|
||||
);
|
||||
|
||||
if (userPreferences && userPreferences.downloadsPath)
|
||||
return userPreferences.downloadsPath;
|
||||
if (userPreferences?.downloadsPath) return userPreferences.downloadsPath;
|
||||
|
||||
return defaultDownloadsPath;
|
||||
};
|
||||
|
||||
7
src/main/events/helpers/parse-launch-options.ts
Normal file
7
src/main/events/helpers/parse-launch-options.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export const parseLaunchOptions = (params?: string | null): string[] => {
|
||||
if (!params) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return params.split(" ");
|
||||
};
|
||||
@@ -1,8 +1,10 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import { shell } from "electron";
|
||||
import { spawn } from "child_process";
|
||||
import { parseExecutablePath } from "../helpers/parse-executable-path";
|
||||
import { gamesSublevel, levelKeys } from "@main/level";
|
||||
import { GameShop } from "@types";
|
||||
import { parseLaunchOptions } from "../helpers/parse-launch-options";
|
||||
|
||||
const openGame = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
@@ -11,8 +13,8 @@ const openGame = async (
|
||||
executablePath: string,
|
||||
launchOptions?: string | null
|
||||
) => {
|
||||
// TODO: revisit this for launchOptions
|
||||
const parsedPath = parseExecutablePath(executablePath);
|
||||
const parsedParams = parseLaunchOptions(launchOptions);
|
||||
|
||||
const gameKey = levelKeys.game(shop, objectId);
|
||||
|
||||
@@ -26,7 +28,12 @@ const openGame = async (
|
||||
launchOptions,
|
||||
});
|
||||
|
||||
shell.openPath(parsedPath);
|
||||
if (parsedParams.length === 0) {
|
||||
shell.openPath(parsedPath);
|
||||
return;
|
||||
}
|
||||
|
||||
spawn(parsedPath, parsedParams, { shell: false, detached: true });
|
||||
};
|
||||
|
||||
registerEvent("openGame", openGame);
|
||||
|
||||
@@ -10,7 +10,7 @@ const publishNewRepacksNotification = async (
|
||||
) => {
|
||||
if (newRepacksCount < 1) return;
|
||||
|
||||
const userPreferences = await db.get<string, UserPreferences>(
|
||||
const userPreferences = await db.get<string, UserPreferences | null>(
|
||||
levelKeys.userPreferences,
|
||||
{
|
||||
valueEncoding: "json",
|
||||
|
||||
@@ -7,7 +7,7 @@ import { omit } from "lodash-es";
|
||||
import axios from "axios";
|
||||
import { fileTypeFromFile } from "file-type";
|
||||
|
||||
const patchUserProfile = async (updateProfile: UpdateProfileRequest) => {
|
||||
export const patchUserProfile = async (updateProfile: UpdateProfileRequest) => {
|
||||
return HydraApi.patch<UserProfile>("/profile", updateProfile);
|
||||
};
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@ import type { UserPreferences } from "@types";
|
||||
|
||||
const getUserPreferences = async () =>
|
||||
db
|
||||
.get<string, UserPreferences>(levelKeys.userPreferences, {
|
||||
.get<string, UserPreferences | null>(levelKeys.userPreferences, {
|
||||
valueEncoding: "json",
|
||||
})
|
||||
.then((userPreferences) => {
|
||||
if (userPreferences.realDebridApiToken) {
|
||||
if (userPreferences?.realDebridApiToken) {
|
||||
userPreferences.realDebridApiToken = Crypto.decrypt(
|
||||
userPreferences.realDebridApiToken
|
||||
);
|
||||
|
||||
@@ -4,12 +4,13 @@ import type { UserPreferences } from "@types";
|
||||
import i18next from "i18next";
|
||||
import { db, levelKeys } from "@main/level";
|
||||
import { Crypto } from "@main/services";
|
||||
import { patchUserProfile } from "../profile/update-profile";
|
||||
|
||||
const updateUserPreferences = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
preferences: Partial<UserPreferences>
|
||||
) => {
|
||||
const userPreferences = await db.get<string, UserPreferences>(
|
||||
const userPreferences = await db.get<string, UserPreferences | null>(
|
||||
levelKeys.userPreferences,
|
||||
{ valueEncoding: "json" }
|
||||
);
|
||||
@@ -20,6 +21,7 @@ const updateUserPreferences = async (
|
||||
});
|
||||
|
||||
i18next.changeLanguage(preferences.language);
|
||||
patchUserProfile({ language: preferences.language }).catch(() => {});
|
||||
}
|
||||
|
||||
if (preferences.realDebridApiToken) {
|
||||
@@ -28,6 +30,10 @@ const updateUserPreferences = async (
|
||||
);
|
||||
}
|
||||
|
||||
if (!preferences.downloadsPath) {
|
||||
preferences.downloadsPath = null;
|
||||
}
|
||||
|
||||
await db.put<string, UserPreferences>(
|
||||
levelKeys.userPreferences,
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ const getComparedUnlockedAchievements = async (
|
||||
shop: GameShop,
|
||||
userId: string
|
||||
) => {
|
||||
const userPreferences = await db.get<string, UserPreferences>(
|
||||
const userPreferences = await db.get<string, UserPreferences | null>(
|
||||
levelKeys.userPreferences,
|
||||
{
|
||||
valueEncoding: "json",
|
||||
@@ -25,7 +25,7 @@ const getComparedUnlockedAchievements = async (
|
||||
{
|
||||
shop,
|
||||
objectId,
|
||||
language: userPreferences?.language || "en",
|
||||
language: userPreferences?.language ?? "en",
|
||||
}
|
||||
).then((achievements) => {
|
||||
const sortedAchievements = achievements.achievements
|
||||
|
||||
@@ -12,7 +12,7 @@ export const getUnlockedAchievements = async (
|
||||
levelKeys.game(shop, objectId)
|
||||
);
|
||||
|
||||
const userPreferences = await db.get<string, UserPreferences>(
|
||||
const userPreferences = await db.get<string, UserPreferences | null>(
|
||||
levelKeys.userPreferences,
|
||||
{
|
||||
valueEncoding: "json",
|
||||
|
||||
@@ -9,6 +9,7 @@ import resources from "@locales";
|
||||
import { PythonRPC } from "./services/python-rpc";
|
||||
import { Aria2 } from "./services/aria2";
|
||||
import { db, levelKeys } from "./level";
|
||||
import { loadState } from "./main";
|
||||
|
||||
const { autoUpdater } = updater;
|
||||
|
||||
@@ -57,7 +58,7 @@ app.whenReady().then(async () => {
|
||||
return net.fetch(url.pathToFileURL(decodeURI(filePath)).toString());
|
||||
});
|
||||
|
||||
await import("./main");
|
||||
await loadState();
|
||||
|
||||
const language = await db.get<string, string>(levelKeys.language, {
|
||||
valueEncoding: "utf-8",
|
||||
|
||||
@@ -21,8 +21,18 @@ import {
|
||||
import { Auth, User, type UserPreferences } from "@types";
|
||||
import { knexClient } from "./knex-client";
|
||||
|
||||
const loadState = async (userPreferences: UserPreferences | null) => {
|
||||
import("./events");
|
||||
export const loadState = async () => {
|
||||
const userPreferences = await migrateFromSqlite().then(async () => {
|
||||
await db.put<string, boolean>(levelKeys.sqliteMigrationDone, true, {
|
||||
valueEncoding: "json",
|
||||
});
|
||||
|
||||
return db.get<string, UserPreferences | null>(levelKeys.userPreferences, {
|
||||
valueEncoding: "json",
|
||||
});
|
||||
});
|
||||
|
||||
await import("./events");
|
||||
|
||||
Aria2.spawn();
|
||||
|
||||
@@ -104,24 +114,29 @@ const migrateFromSqlite = async () => {
|
||||
if (userPreferences.length > 0) {
|
||||
const { realDebridApiToken, ...rest } = userPreferences[0];
|
||||
|
||||
await db.put(levelKeys.userPreferences, {
|
||||
...rest,
|
||||
realDebridApiToken: realDebridApiToken
|
||||
? Crypto.encrypt(realDebridApiToken)
|
||||
: null,
|
||||
preferQuitInsteadOfHiding: rest.preferQuitInsteadOfHiding === 1,
|
||||
runAtStartup: rest.runAtStartup === 1,
|
||||
startMinimized: rest.startMinimized === 1,
|
||||
disableNsfwAlert: rest.disableNsfwAlert === 1,
|
||||
seedAfterDownloadComplete: rest.seedAfterDownloadComplete === 1,
|
||||
showHiddenAchievementsDescription:
|
||||
rest.showHiddenAchievementsDescription === 1,
|
||||
downloadNotificationsEnabled: rest.downloadNotificationsEnabled === 1,
|
||||
repackUpdatesNotificationsEnabled:
|
||||
rest.repackUpdatesNotificationsEnabled === 1,
|
||||
achievementNotificationsEnabled:
|
||||
rest.achievementNotificationsEnabled === 1,
|
||||
});
|
||||
await db.put<string, UserPreferences>(
|
||||
levelKeys.userPreferences,
|
||||
{
|
||||
...rest,
|
||||
realDebridApiToken: realDebridApiToken
|
||||
? Crypto.encrypt(realDebridApiToken)
|
||||
: null,
|
||||
preferQuitInsteadOfHiding: rest.preferQuitInsteadOfHiding === 1,
|
||||
runAtStartup: rest.runAtStartup === 1,
|
||||
startMinimized: rest.startMinimized === 1,
|
||||
disableNsfwAlert: rest.disableNsfwAlert === 1,
|
||||
seedAfterDownloadComplete: rest.seedAfterDownloadComplete === 1,
|
||||
showHiddenAchievementsDescription:
|
||||
rest.showHiddenAchievementsDescription === 1,
|
||||
downloadNotificationsEnabled:
|
||||
rest.downloadNotificationsEnabled === 1,
|
||||
repackUpdatesNotificationsEnabled:
|
||||
rest.repackUpdatesNotificationsEnabled === 1,
|
||||
achievementNotificationsEnabled:
|
||||
rest.achievementNotificationsEnabled === 1,
|
||||
},
|
||||
{ valueEncoding: "json" }
|
||||
);
|
||||
|
||||
if (rest.language) {
|
||||
await db.put(levelKeys.language, rest.language);
|
||||
@@ -192,15 +207,3 @@ const migrateFromSqlite = async () => {
|
||||
migrateUser,
|
||||
]);
|
||||
};
|
||||
|
||||
migrateFromSqlite().then(async () => {
|
||||
await db.put<string, boolean>(levelKeys.sqliteMigrationDone, true, {
|
||||
valueEncoding: "json",
|
||||
});
|
||||
|
||||
db.get<string, UserPreferences>(levelKeys.userPreferences, {
|
||||
valueEncoding: "json",
|
||||
}).then((userPreferences) => {
|
||||
loadState(userPreferences);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -141,7 +141,7 @@ const processAchievementFileDiff = async (
|
||||
export class AchievementWatcherManager {
|
||||
private static hasFinishedMergingWithRemote = false;
|
||||
|
||||
public static watchAchievements = () => {
|
||||
public static watchAchievements() {
|
||||
if (!this.hasFinishedMergingWithRemote) return;
|
||||
|
||||
if (process.platform === "win32") {
|
||||
@@ -149,12 +149,12 @@ export class AchievementWatcherManager {
|
||||
}
|
||||
|
||||
return watchAchievementsWithWine();
|
||||
};
|
||||
}
|
||||
|
||||
private static preProcessGameAchievementFiles = (
|
||||
private static preProcessGameAchievementFiles(
|
||||
game: Game,
|
||||
gameAchievementFiles: AchievementFile[]
|
||||
) => {
|
||||
) {
|
||||
const unlockedAchievements: UnlockedAchievement[] = [];
|
||||
for (const achievementFile of gameAchievementFiles) {
|
||||
const parsedAchievements = parseAchievementFile(
|
||||
@@ -182,7 +182,7 @@ export class AchievementWatcherManager {
|
||||
}
|
||||
|
||||
return mergeAchievements(game, unlockedAchievements, false);
|
||||
};
|
||||
}
|
||||
|
||||
private static preSearchAchievementsWindows = async () => {
|
||||
const games = await gamesSublevel
|
||||
@@ -230,7 +230,7 @@ export class AchievementWatcherManager {
|
||||
);
|
||||
};
|
||||
|
||||
public static preSearchAchievements = async () => {
|
||||
public static async preSearchAchievements() {
|
||||
try {
|
||||
const newAchievementsCount =
|
||||
process.platform === "win32"
|
||||
@@ -256,5 +256,5 @@ export class AchievementWatcherManager {
|
||||
}
|
||||
|
||||
this.hasFinishedMergingWithRemote = true;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ export const getGameAchievementData = async (
|
||||
throw err;
|
||||
}
|
||||
|
||||
logger.error("Failed to get game achievements", err);
|
||||
logger.error("Failed to get game achievements for", objectId, err);
|
||||
|
||||
return [];
|
||||
});
|
||||
|
||||
@@ -59,7 +59,7 @@ export const mergeAchievements = async (
|
||||
const unlockedAchievements = localGameAchievement?.unlockedAchievements ?? [];
|
||||
|
||||
const newAchievementsMap = new Map(
|
||||
achievements.reverse().map((achievement) => {
|
||||
achievements.toReversed().map((achievement) => {
|
||||
return [achievement.name.toUpperCase(), achievement];
|
||||
})
|
||||
);
|
||||
@@ -87,7 +87,7 @@ export const mergeAchievements = async (
|
||||
userPreferences?.achievementNotificationsEnabled
|
||||
) {
|
||||
const achievementsInfo = newAchievements
|
||||
.sort((a, b) => {
|
||||
.toSorted((a, b) => {
|
||||
return a.unlockTime - b.unlockTime;
|
||||
})
|
||||
.map((achievement) => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { WindowManager } from "./window-manager";
|
||||
import url from "url";
|
||||
import { uploadGamesBatch } from "./library-sync";
|
||||
import { clearGamesRemoteIds } from "./library-sync/clear-games-remote-id";
|
||||
import { logger } from "./logger";
|
||||
import { networkLogger as logger } from "./logger";
|
||||
import { UserNotLoggedInError, SubscriptionRequiredError } from "@shared";
|
||||
import { omit } from "lodash-es";
|
||||
import { appVersion } from "@main/constants";
|
||||
@@ -32,7 +32,8 @@ export class HydraApi {
|
||||
private static readonly EXPIRATION_OFFSET_IN_MS = 1000 * 60 * 5; // 5 minutes
|
||||
private static readonly ADD_LOG_INTERCEPTOR = true;
|
||||
|
||||
private static secondsToMilliseconds = (seconds: number) => seconds * 1000;
|
||||
private static readonly secondsToMilliseconds = (seconds: number) =>
|
||||
seconds * 1000;
|
||||
|
||||
private static userAuth: HydraApiUserAuth = {
|
||||
authToken: "",
|
||||
@@ -153,7 +154,8 @@ export class HydraApi {
|
||||
(error) => {
|
||||
logger.error(" ---- RESPONSE ERROR -----");
|
||||
const { config } = error;
|
||||
const data = JSON.parse(config.data);
|
||||
|
||||
const data = JSON.parse(config.data ?? null);
|
||||
|
||||
logger.error(
|
||||
config.method,
|
||||
@@ -174,14 +176,22 @@ export class HydraApi {
|
||||
error.response.status,
|
||||
error.response.data
|
||||
);
|
||||
} else if (error.request) {
|
||||
const errorData = error.toJSON();
|
||||
logger.error("Request error:", errorData.message);
|
||||
} else {
|
||||
logger.error("Error", error.message);
|
||||
|
||||
return Promise.reject(error as Error);
|
||||
}
|
||||
logger.error(" ----- END RESPONSE ERROR -------");
|
||||
return Promise.reject(error);
|
||||
|
||||
if (error.request) {
|
||||
const errorData = error.toJSON();
|
||||
logger.error("Request error:", errorData.code, errorData.message);
|
||||
return Promise.reject(
|
||||
new Error(
|
||||
`Request failed with ${errorData.code} ${errorData.message}`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
logger.error("Error", error.message);
|
||||
return Promise.reject(error as Error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,8 +6,12 @@ log.transports.file.resolvePathFn = (
|
||||
_: log.PathVariables,
|
||||
message?: log.LogMessage | undefined
|
||||
) => {
|
||||
if (message?.scope === "python-instance") {
|
||||
return path.join(logsPath, "pythoninstance.txt");
|
||||
if (message?.scope === "python-rpc") {
|
||||
return path.join(logsPath, "pythonrpc.txt");
|
||||
}
|
||||
|
||||
if (message?.scope === "network") {
|
||||
return path.join(logsPath, "network.txt");
|
||||
}
|
||||
|
||||
if (message?.scope == "achievements") {
|
||||
@@ -34,3 +38,4 @@ log.initialize();
|
||||
export const pythonRpcLogger = log.scope("python-rpc");
|
||||
export const logger = log.scope("main");
|
||||
export const achievementsLogger = log.scope("achievements");
|
||||
export const networkLogger = log.scope("network");
|
||||
|
||||
@@ -2,6 +2,7 @@ import { sleep } from "@main/helpers";
|
||||
import { DownloadManager } from "./download";
|
||||
import { watchProcesses } from "./process-watcher";
|
||||
import { AchievementWatcherManager } from "./achievements/achievement-watcher-manager";
|
||||
import { UpdateManager } from "./update-manager";
|
||||
|
||||
export const startMainLoop = async () => {
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
@@ -11,6 +12,7 @@ export const startMainLoop = async () => {
|
||||
DownloadManager.watchDownloads(),
|
||||
AchievementWatcherManager.watchAchievements(),
|
||||
DownloadManager.getSeedStatus(),
|
||||
UpdateManager.checkForUpdatePeriodically(),
|
||||
]);
|
||||
|
||||
await sleep(1500);
|
||||
|
||||
@@ -9,6 +9,7 @@ import { achievementSoundPath } from "@main/constants";
|
||||
import icon from "@resources/icon.png?asset";
|
||||
import { NotificationOptions, toXmlString } from "./xml";
|
||||
import { logger } from "../logger";
|
||||
import { WindowManager } from "../window-manager";
|
||||
import type { Game, UserPreferences } from "@types";
|
||||
import { db, levelKeys } from "@main/level";
|
||||
|
||||
@@ -96,7 +97,9 @@ export const publishCombinedNewAchievementNotification = async (
|
||||
toastXml: toXmlString(options),
|
||||
}).show();
|
||||
|
||||
if (process.platform !== "linux") {
|
||||
if (WindowManager.mainWindow) {
|
||||
WindowManager.mainWindow.webContents.send("on-achievement-unlocked");
|
||||
} else if (process.platform !== "linux") {
|
||||
sound.play(achievementSoundPath);
|
||||
}
|
||||
};
|
||||
@@ -143,7 +146,9 @@ export const publishNewAchievementNotification = async (info: {
|
||||
toastXml: toXmlString(options),
|
||||
}).show();
|
||||
|
||||
if (process.platform !== "linux") {
|
||||
if (WindowManager.mainWindow) {
|
||||
WindowManager.mainWindow.webContents.send("on-achievement-unlocked");
|
||||
} else if (process.platform !== "linux") {
|
||||
sound.play(achievementSoundPath);
|
||||
}
|
||||
};
|
||||
|
||||
60
src/main/services/update-manager.ts
Normal file
60
src/main/services/update-manager.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import updater, { UpdateInfo } from "electron-updater";
|
||||
import { logger, WindowManager } from "@main/services";
|
||||
import { AppUpdaterEvent } from "@types";
|
||||
import { app } from "electron";
|
||||
import { publishNotificationUpdateReadyToInstall } from "@main/services/notifications";
|
||||
|
||||
const isAutoInstallAvailable =
|
||||
process.platform !== "darwin" && process.env.PORTABLE_EXECUTABLE_FILE == null;
|
||||
|
||||
const { autoUpdater } = updater;
|
||||
const sendEventsForDebug = false;
|
||||
|
||||
export class UpdateManager {
|
||||
private static hasNotified = false;
|
||||
private static newVersion = "";
|
||||
private static checkTick = 0;
|
||||
|
||||
private static mockValuesForDebug() {
|
||||
this.sendEvent({ type: "update-available", info: { version: "1.3.0" } });
|
||||
this.sendEvent({ type: "update-downloaded" });
|
||||
}
|
||||
|
||||
private static sendEvent(event: AppUpdaterEvent) {
|
||||
WindowManager.mainWindow?.webContents.send("autoUpdaterEvent", event);
|
||||
}
|
||||
|
||||
public static checkForUpdates() {
|
||||
autoUpdater
|
||||
.once("update-available", (info: UpdateInfo) => {
|
||||
this.sendEvent({ type: "update-available", info });
|
||||
this.newVersion = info.version;
|
||||
})
|
||||
.once("update-downloaded", () => {
|
||||
this.sendEvent({ type: "update-downloaded" });
|
||||
|
||||
if (!this.hasNotified) {
|
||||
this.hasNotified = true;
|
||||
publishNotificationUpdateReadyToInstall(this.newVersion);
|
||||
}
|
||||
});
|
||||
|
||||
if (app.isPackaged) {
|
||||
autoUpdater.autoDownload = isAutoInstallAvailable;
|
||||
autoUpdater.checkForUpdates().then((result) => {
|
||||
logger.log(`Check for updates result: ${result}`);
|
||||
});
|
||||
} else if (sendEventsForDebug) {
|
||||
this.mockValuesForDebug();
|
||||
}
|
||||
|
||||
return isAutoInstallAvailable;
|
||||
}
|
||||
|
||||
public static checkForUpdatePeriodically() {
|
||||
if (this.checkTick % 2000 == 0) {
|
||||
this.checkForUpdates();
|
||||
}
|
||||
this.checkTick++;
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,6 @@ export const getUserData = async () => {
|
||||
})
|
||||
.catch(async (err) => {
|
||||
if (err instanceof UserNotLoggedInError) {
|
||||
logger.info("User is not logged in", err);
|
||||
return null;
|
||||
}
|
||||
logger.error("Failed to get logged user");
|
||||
@@ -59,6 +58,7 @@ export const getUserData = async () => {
|
||||
expiresAt: loggedUser.subscription.expiresAt,
|
||||
}
|
||||
: null,
|
||||
featurebaseJwt: "",
|
||||
} as UserDetails;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ export class WindowManager {
|
||||
minHeight: 540,
|
||||
backgroundColor: "#1c1c1c",
|
||||
titleBarStyle: process.platform === "linux" ? "default" : "hidden",
|
||||
...(process.platform === "linux" ? { icon } : {}),
|
||||
icon,
|
||||
trafficLightPosition: { x: 16, y: 16 },
|
||||
titleBarOverlay: {
|
||||
symbolColor: "#DADBE1",
|
||||
@@ -145,6 +145,11 @@ export class WindowManager {
|
||||
WindowManager.mainWindow?.setProgressBar(-1);
|
||||
WindowManager.mainWindow = null;
|
||||
});
|
||||
|
||||
this.mainWindow.webContents.setWindowOpenHandler((handler) => {
|
||||
shell.openExternal(handler.url);
|
||||
return { action: "deny" };
|
||||
});
|
||||
}
|
||||
|
||||
public static openAuthWindow(page: AuthPage, searchParams: URLSearchParams) {
|
||||
|
||||
Reference in New Issue
Block a user