Audit app update functions
This commit is contained in:
parent
3c7277a0b1
commit
af79f4f0c9
13 changed files with 216 additions and 242 deletions
|
@ -27,7 +27,7 @@ import { attachFSWatchIPCHandlers, attachIPCHandlers } from "./main/ipc";
|
|||
import log, { initLogging } from "./main/log";
|
||||
import { createApplicationMenu } from "./main/menu";
|
||||
import { isDev } from "./main/util";
|
||||
import { setupAutoUpdater } from "./services/appUpdater";
|
||||
import { setupAutoUpdater } from "./services/app-update";
|
||||
import { initWatcher } from "./services/chokidar";
|
||||
|
||||
let appIsQuitting = false;
|
||||
|
@ -145,7 +145,7 @@ const attachEventHandlers = (mainWindow: BrowserWindow) => {
|
|||
// Let ipcRenderer know when mainWindow is in the foreground so that it can
|
||||
// in turn inform the renderer process.
|
||||
mainWindow.on("focus", () =>
|
||||
mainWindow.webContents.send("onMainWindowFocus"),
|
||||
mainWindow.webContents.send("mainWindowFocus"),
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -12,14 +12,11 @@ import type { FSWatcher } from "chokidar";
|
|||
import { ipcMain } from "electron/main";
|
||||
import {
|
||||
appVersion,
|
||||
muteUpdateNotification,
|
||||
skipAppUpdate,
|
||||
updateAndRestart,
|
||||
} from "../services/appUpdater";
|
||||
import {
|
||||
clipImageEmbedding,
|
||||
clipTextEmbedding,
|
||||
} from "../services/clip";
|
||||
updateOnNextRestart,
|
||||
} from "../services/app-update";
|
||||
import { clipImageEmbedding, clipTextEmbedding } from "../services/clip";
|
||||
import { runFFmpegCmd } from "../services/ffmpeg";
|
||||
import { getDirFiles } from "../services/fs";
|
||||
import {
|
||||
|
@ -108,14 +105,14 @@ export const attachIPCHandlers = () => {
|
|||
|
||||
// - App update
|
||||
|
||||
ipcMain.on("update-and-restart", () => updateAndRestart());
|
||||
ipcMain.on("updateAndRestart", () => updateAndRestart());
|
||||
|
||||
ipcMain.on("skip-app-update", (_, version) => skipAppUpdate(version));
|
||||
|
||||
ipcMain.on("mute-update-notification", (_, version) =>
|
||||
muteUpdateNotification(version),
|
||||
ipcMain.on("updateOnNextRestart", (_, version) =>
|
||||
updateOnNextRestart(version),
|
||||
);
|
||||
|
||||
ipcMain.on("skipAppUpdate", (_, version) => skipAppUpdate(version));
|
||||
|
||||
// - Conversion
|
||||
|
||||
ipcMain.handle("convertToJPEG", (_, fileData, filename) =>
|
||||
|
|
|
@ -6,7 +6,7 @@ import {
|
|||
shell,
|
||||
} from "electron";
|
||||
import { setIsAppQuitting } from "../main";
|
||||
import { forceCheckForUpdateAndNotify } from "../services/appUpdater";
|
||||
import { forceCheckForAppUpdates } from "../services/app-update";
|
||||
import autoLauncher from "../services/autoLauncher";
|
||||
import {
|
||||
getHideDockIconPreference,
|
||||
|
@ -26,8 +26,7 @@ export const createApplicationMenu = async (mainWindow: BrowserWindow) => {
|
|||
const macOSOnly = (options: MenuItemConstructorOptions[]) =>
|
||||
process.platform == "darwin" ? options : [];
|
||||
|
||||
const handleCheckForUpdates = () =>
|
||||
forceCheckForUpdateAndNotify(mainWindow);
|
||||
const handleCheckForUpdates = () => forceCheckForAppUpdates(mainWindow);
|
||||
|
||||
const handleViewChangelog = () =>
|
||||
shell.openExternal(
|
||||
|
|
|
@ -70,8 +70,30 @@ const saveEncryptionKey = (encryptionKey: string): Promise<void> =>
|
|||
ipcRenderer.invoke("saveEncryptionKey", encryptionKey);
|
||||
|
||||
const onMainWindowFocus = (cb?: () => void) => {
|
||||
ipcRenderer.removeAllListeners("onMainWindowFocus");
|
||||
if (cb) ipcRenderer.on("onMainWindowFocus", cb);
|
||||
ipcRenderer.removeAllListeners("mainWindowFocus");
|
||||
if (cb) ipcRenderer.on("mainWindowFocus", cb);
|
||||
};
|
||||
|
||||
// - App update
|
||||
|
||||
const onAppUpdateAvailable = (
|
||||
cb?: ((updateInfo: AppUpdateInfo) => void) | undefined,
|
||||
) => {
|
||||
ipcRenderer.removeAllListeners("appUpdateAvailable");
|
||||
if (cb) {
|
||||
ipcRenderer.on("appUpdateAvailable", (_, updateInfo: AppUpdateInfo) =>
|
||||
cb(updateInfo),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const updateAndRestart = () => ipcRenderer.send("updateAndRestart");
|
||||
|
||||
const updateOnNextRestart = (version: string) =>
|
||||
ipcRenderer.send("updateOnNextRestart", version);
|
||||
|
||||
const skipAppUpdate = (version: string) => {
|
||||
ipcRenderer.send("skipAppUpdate", version);
|
||||
};
|
||||
|
||||
const fsExists = (path: string): Promise<boolean> =>
|
||||
|
@ -79,29 +101,6 @@ const fsExists = (path: string): Promise<boolean> =>
|
|||
|
||||
// - AUDIT below this
|
||||
|
||||
// - App update
|
||||
|
||||
const registerUpdateEventListener = (
|
||||
showUpdateDialog: (updateInfo: AppUpdateInfo) => void,
|
||||
) => {
|
||||
ipcRenderer.removeAllListeners("show-update-dialog");
|
||||
ipcRenderer.on("show-update-dialog", (_, updateInfo: AppUpdateInfo) => {
|
||||
showUpdateDialog(updateInfo);
|
||||
});
|
||||
};
|
||||
|
||||
const updateAndRestart = () => {
|
||||
ipcRenderer.send("update-and-restart");
|
||||
};
|
||||
|
||||
const skipAppUpdate = (version: string) => {
|
||||
ipcRenderer.send("skip-app-update", version);
|
||||
};
|
||||
|
||||
const muteUpdateNotification = (version: string) => {
|
||||
ipcRenderer.send("mute-update-notification", version);
|
||||
};
|
||||
|
||||
// - Conversion
|
||||
|
||||
const convertToJPEG = (
|
||||
|
@ -310,10 +309,10 @@ contextBridge.exposeInMainWorld("electron", {
|
|||
onMainWindowFocus,
|
||||
|
||||
// - App update
|
||||
onAppUpdateAvailable,
|
||||
updateAndRestart,
|
||||
updateOnNextRestart,
|
||||
skipAppUpdate,
|
||||
muteUpdateNotification,
|
||||
registerUpdateEventListener,
|
||||
|
||||
// - Conversion
|
||||
convertToJPEG,
|
||||
|
|
98
desktop/src/services/app-update.ts
Normal file
98
desktop/src/services/app-update.ts
Normal file
|
@ -0,0 +1,98 @@
|
|||
import { compareVersions } from "compare-versions";
|
||||
import { app, BrowserWindow } from "electron";
|
||||
import { default as electronLog } from "electron-log";
|
||||
import { autoUpdater } from "electron-updater";
|
||||
import { setIsAppQuitting, setIsUpdateAvailable } from "../main";
|
||||
import log from "../main/log";
|
||||
import { userPreferencesStore } from "../stores/user-preferences";
|
||||
import { AppUpdateInfo } from "../types/ipc";
|
||||
|
||||
export const setupAutoUpdater = (mainWindow: BrowserWindow) => {
|
||||
autoUpdater.logger = electronLog;
|
||||
autoUpdater.autoDownload = false;
|
||||
|
||||
const oneDay = 1 * 24 * 60 * 60 * 1000;
|
||||
setInterval(() => checkForUpdatesAndNotify(mainWindow), oneDay);
|
||||
checkForUpdatesAndNotify(mainWindow);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check for app update check ignoring any previously saved skips / mutes.
|
||||
*/
|
||||
export const forceCheckForAppUpdates = (mainWindow: BrowserWindow) => {
|
||||
userPreferencesStore.delete("skipAppVersion");
|
||||
userPreferencesStore.delete("muteUpdateNotificationVersion");
|
||||
checkForUpdatesAndNotify(mainWindow);
|
||||
};
|
||||
|
||||
const checkForUpdatesAndNotify = async (mainWindow: BrowserWindow) => {
|
||||
try {
|
||||
const { updateInfo } = await autoUpdater.checkForUpdates();
|
||||
const { version } = updateInfo;
|
||||
|
||||
log.debug(() => `Checking for updates found version ${version}`);
|
||||
|
||||
if (compareVersions(version, app.getVersion()) <= 0) {
|
||||
log.debug(() => "Skipping update, already at latest version");
|
||||
return;
|
||||
}
|
||||
|
||||
if (version === userPreferencesStore.get("skipAppVersion")) {
|
||||
log.info(`User chose to skip version ${version}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const mutedVersion = userPreferencesStore.get(
|
||||
"muteUpdateNotificationVersion",
|
||||
);
|
||||
if (version === mutedVersion) {
|
||||
log.info(
|
||||
`User has muted update notifications for version ${version}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const showUpdateDialog = (updateInfo: AppUpdateInfo) =>
|
||||
mainWindow.webContents.send("appUpdateAvailable", updateInfo);
|
||||
|
||||
log.debug(() => "Attempting auto update");
|
||||
autoUpdater.downloadUpdate();
|
||||
|
||||
let timeout: NodeJS.Timeout;
|
||||
const fiveMinutes = 5 * 60 * 1000;
|
||||
autoUpdater.on("update-downloaded", () => {
|
||||
timeout = setTimeout(
|
||||
() => showUpdateDialog({ autoUpdatable: true, version }),
|
||||
fiveMinutes,
|
||||
);
|
||||
});
|
||||
autoUpdater.on("error", (error) => {
|
||||
clearTimeout(timeout);
|
||||
log.error("Auto update failed", error);
|
||||
showUpdateDialog({ autoUpdatable: false, version });
|
||||
});
|
||||
|
||||
setIsUpdateAvailable(true);
|
||||
} catch (e) {
|
||||
log.error("checkForUpdateAndNotify failed", e);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the version of the desktop app
|
||||
*
|
||||
* The return value is of the form `v1.2.3`.
|
||||
*/
|
||||
export const appVersion = () => `v${app.getVersion()}`;
|
||||
|
||||
export const updateAndRestart = () => {
|
||||
log.info("Restarting the app to apply update");
|
||||
setIsAppQuitting(true);
|
||||
autoUpdater.quitAndInstall();
|
||||
};
|
||||
|
||||
export const updateOnNextRestart = (version: string) =>
|
||||
userPreferencesStore.set("muteUpdateNotificationVersion", version);
|
||||
|
||||
export const skipAppUpdate = (version: string) =>
|
||||
userPreferencesStore.set("skipAppVersion", version);
|
|
@ -1,120 +0,0 @@
|
|||
import { compareVersions } from "compare-versions";
|
||||
import { app, BrowserWindow } from "electron";
|
||||
import { default as electronLog } from "electron-log";
|
||||
import { autoUpdater } from "electron-updater";
|
||||
import { setIsAppQuitting, setIsUpdateAvailable } from "../main";
|
||||
import log from "../main/log";
|
||||
import { AppUpdateInfo } from "../types/ipc";
|
||||
import {
|
||||
clearMuteUpdateNotificationVersion,
|
||||
clearSkipAppVersion,
|
||||
getMuteUpdateNotificationVersion,
|
||||
getSkipAppVersion,
|
||||
setMuteUpdateNotificationVersion,
|
||||
setSkipAppVersion,
|
||||
} from "./userPreference";
|
||||
|
||||
const FIVE_MIN_IN_MICROSECOND = 5 * 60 * 1000;
|
||||
const ONE_DAY_IN_MICROSECOND = 1 * 24 * 60 * 60 * 1000;
|
||||
|
||||
export function setupAutoUpdater(mainWindow: BrowserWindow) {
|
||||
autoUpdater.logger = electronLog;
|
||||
autoUpdater.autoDownload = false;
|
||||
checkForUpdateAndNotify(mainWindow);
|
||||
setInterval(
|
||||
() => checkForUpdateAndNotify(mainWindow),
|
||||
ONE_DAY_IN_MICROSECOND,
|
||||
);
|
||||
}
|
||||
|
||||
export function forceCheckForUpdateAndNotify(mainWindow: BrowserWindow) {
|
||||
try {
|
||||
clearSkipAppVersion();
|
||||
clearMuteUpdateNotificationVersion();
|
||||
checkForUpdateAndNotify(mainWindow);
|
||||
} catch (e) {
|
||||
log.error("forceCheckForUpdateAndNotify failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
async function checkForUpdateAndNotify(mainWindow: BrowserWindow) {
|
||||
try {
|
||||
log.debug(() => "checkForUpdateAndNotify");
|
||||
const { updateInfo } = await autoUpdater.checkForUpdates();
|
||||
log.debug(() => `Update version ${updateInfo.version}`);
|
||||
if (compareVersions(updateInfo.version, app.getVersion()) <= 0) {
|
||||
log.debug(() => "Skipping update, already at latest version");
|
||||
return;
|
||||
}
|
||||
const skipAppVersion = getSkipAppVersion();
|
||||
if (skipAppVersion && updateInfo.version === skipAppVersion) {
|
||||
log.info(`User chose to skip version ${updateInfo.version}`);
|
||||
return;
|
||||
}
|
||||
|
||||
let timeout: NodeJS.Timeout;
|
||||
log.debug(() => "Attempting auto update");
|
||||
autoUpdater.downloadUpdate();
|
||||
const muteUpdateNotificationVersion =
|
||||
getMuteUpdateNotificationVersion();
|
||||
if (
|
||||
muteUpdateNotificationVersion &&
|
||||
updateInfo.version === muteUpdateNotificationVersion
|
||||
) {
|
||||
log.info(
|
||||
`User has muted update notifications for version ${updateInfo.version}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
autoUpdater.on("update-downloaded", () => {
|
||||
timeout = setTimeout(
|
||||
() =>
|
||||
showUpdateDialog(mainWindow, {
|
||||
autoUpdatable: true,
|
||||
version: updateInfo.version,
|
||||
}),
|
||||
FIVE_MIN_IN_MICROSECOND,
|
||||
);
|
||||
});
|
||||
autoUpdater.on("error", (error) => {
|
||||
clearTimeout(timeout);
|
||||
log.error("Auto update failed", error);
|
||||
showUpdateDialog(mainWindow, {
|
||||
autoUpdatable: false,
|
||||
version: updateInfo.version,
|
||||
});
|
||||
});
|
||||
|
||||
setIsUpdateAvailable(true);
|
||||
} catch (e) {
|
||||
log.error("checkForUpdateAndNotify failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
export function updateAndRestart() {
|
||||
log.info("user quit the app");
|
||||
setIsAppQuitting(true);
|
||||
autoUpdater.quitAndInstall();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the version of the desktop app
|
||||
*
|
||||
* The return value is of the form `v1.2.3`.
|
||||
*/
|
||||
export const appVersion = () => `v${app.getVersion()}`;
|
||||
|
||||
export function skipAppUpdate(version: string) {
|
||||
setSkipAppVersion(version);
|
||||
}
|
||||
|
||||
export function muteUpdateNotification(version: string) {
|
||||
setMuteUpdateNotificationVersion(version);
|
||||
}
|
||||
|
||||
function showUpdateDialog(
|
||||
mainWindow: BrowserWindow,
|
||||
updateInfo: AppUpdateInfo,
|
||||
) {
|
||||
mainWindow.webContents.send("show-update-dialog", updateInfo);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { userPreferencesStore } from "../stores/userPreferences.store";
|
||||
import { userPreferencesStore } from "../stores/user-preferences";
|
||||
|
||||
export function getHideDockIconPreference() {
|
||||
return userPreferencesStore.get("hideDockIcon");
|
||||
|
@ -7,27 +7,3 @@ export function getHideDockIconPreference() {
|
|||
export function setHideDockIconPreference(shouldHideDockIcon: boolean) {
|
||||
userPreferencesStore.set("hideDockIcon", shouldHideDockIcon);
|
||||
}
|
||||
|
||||
export function getSkipAppVersion() {
|
||||
return userPreferencesStore.get("skipAppVersion");
|
||||
}
|
||||
|
||||
export function setSkipAppVersion(version: string) {
|
||||
userPreferencesStore.set("skipAppVersion", version);
|
||||
}
|
||||
|
||||
export function getMuteUpdateNotificationVersion() {
|
||||
return userPreferencesStore.get("muteUpdateNotificationVersion");
|
||||
}
|
||||
|
||||
export function setMuteUpdateNotificationVersion(version: string) {
|
||||
userPreferencesStore.set("muteUpdateNotificationVersion", version);
|
||||
}
|
||||
|
||||
export function clearSkipAppVersion() {
|
||||
userPreferencesStore.delete("skipAppVersion");
|
||||
}
|
||||
|
||||
export function clearMuteUpdateNotificationVersion() {
|
||||
userPreferencesStore.delete("muteUpdateNotificationVersion");
|
||||
}
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
import Store, { Schema } from "electron-store";
|
||||
import type { UserPreferencesType } from "../types/main";
|
||||
|
||||
const userPreferencesSchema: Schema<UserPreferencesType> = {
|
||||
interface UserPreferencesSchema {
|
||||
hideDockIcon: boolean;
|
||||
skipAppVersion?: string;
|
||||
muteUpdateNotificationVersion?: string;
|
||||
}
|
||||
|
||||
const userPreferencesSchema: Schema<UserPreferencesSchema> = {
|
||||
hideDockIcon: {
|
||||
type: "boolean",
|
||||
},
|
|
@ -29,9 +29,3 @@ export const FILE_PATH_KEYS: {
|
|||
export interface SafeStorageStoreType {
|
||||
encryptionKey: string;
|
||||
}
|
||||
|
||||
export interface UserPreferencesType {
|
||||
hideDockIcon: boolean;
|
||||
skipAppVersion: string;
|
||||
muteUpdateNotificationVersion: string;
|
||||
}
|
||||
|
|
|
@ -154,28 +154,26 @@ export default function App({ Component, pageProps }: AppProps) {
|
|||
|
||||
useEffect(() => {
|
||||
const electron = globalThis.electron;
|
||||
if (electron) {
|
||||
const showUpdateDialog = (updateInfo: AppUpdateInfo) => {
|
||||
if (updateInfo.autoUpdatable) {
|
||||
setDialogMessage(
|
||||
getUpdateReadyToInstallMessage(updateInfo),
|
||||
);
|
||||
} else {
|
||||
setNotificationAttributes({
|
||||
endIcon: <ArrowForward />,
|
||||
variant: "secondary",
|
||||
message: t("UPDATE_AVAILABLE"),
|
||||
onClick: () =>
|
||||
setDialogMessage(
|
||||
getUpdateAvailableForDownloadMessage(
|
||||
updateInfo,
|
||||
),
|
||||
),
|
||||
});
|
||||
}
|
||||
};
|
||||
electron.registerUpdateEventListener(showUpdateDialog);
|
||||
}
|
||||
if (!electron) return;
|
||||
|
||||
const showUpdateDialog = (updateInfo: AppUpdateInfo) => {
|
||||
if (updateInfo.autoUpdatable) {
|
||||
setDialogMessage(getUpdateReadyToInstallMessage(updateInfo));
|
||||
} else {
|
||||
setNotificationAttributes({
|
||||
endIcon: <ArrowForward />,
|
||||
variant: "secondary",
|
||||
message: t("UPDATE_AVAILABLE"),
|
||||
onClick: () =>
|
||||
setDialogMessage(
|
||||
getUpdateAvailableForDownloadMessage(updateInfo),
|
||||
),
|
||||
});
|
||||
}
|
||||
};
|
||||
electron.onAppUpdateAvailable(showUpdateDialog);
|
||||
|
||||
return () => electron.onAppUpdateAvailable(undefined);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { ensureElectron } from "@/next/electron";
|
||||
import { AppUpdateInfo } from "@/next/types/ipc";
|
||||
import { logoutUser } from "@ente/accounts/services/user";
|
||||
import { DialogBoxAttributes } from "@ente/shared/components/DialogBox/types";
|
||||
|
@ -52,35 +53,34 @@ export const getTrashFileMessage = (deleteFileHelper): DialogBoxAttributes => ({
|
|||
close: { text: t("CANCEL") },
|
||||
});
|
||||
|
||||
export const getUpdateReadyToInstallMessage = (
|
||||
updateInfo: AppUpdateInfo,
|
||||
): DialogBoxAttributes => ({
|
||||
export const getUpdateReadyToInstallMessage = ({
|
||||
version,
|
||||
}: AppUpdateInfo): DialogBoxAttributes => ({
|
||||
icon: <AutoAwesomeOutlinedIcon />,
|
||||
title: t("UPDATE_AVAILABLE"),
|
||||
content: t("UPDATE_INSTALLABLE_MESSAGE"),
|
||||
proceed: {
|
||||
action: () => globalThis.electron?.updateAndRestart(),
|
||||
action: () => ensureElectron().updateAndRestart(),
|
||||
text: t("INSTALL_NOW"),
|
||||
variant: "accent",
|
||||
},
|
||||
close: {
|
||||
text: t("INSTALL_ON_NEXT_LAUNCH"),
|
||||
variant: "secondary",
|
||||
action: () =>
|
||||
globalThis.electron?.muteUpdateNotification(updateInfo.version),
|
||||
action: () => ensureElectron().updateOnNextRestart(version),
|
||||
},
|
||||
});
|
||||
|
||||
export const getUpdateAvailableForDownloadMessage = (
|
||||
updateInfo: AppUpdateInfo,
|
||||
): DialogBoxAttributes => ({
|
||||
export const getUpdateAvailableForDownloadMessage = ({
|
||||
version,
|
||||
}: AppUpdateInfo): DialogBoxAttributes => ({
|
||||
icon: <AutoAwesomeOutlinedIcon />,
|
||||
title: t("UPDATE_AVAILABLE"),
|
||||
content: t("UPDATE_AVAILABLE_MESSAGE"),
|
||||
close: {
|
||||
text: t("IGNORE_THIS_VERSION"),
|
||||
variant: "secondary",
|
||||
action: () => globalThis.electron?.skipAppUpdate(updateInfo.version),
|
||||
action: () => ensureElectron().skipAppUpdate(version),
|
||||
},
|
||||
proceed: {
|
||||
action: downloadApp,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import log from "@/next/log";
|
||||
import {
|
||||
RecoveryKey,
|
||||
TwoFactorRecoveryResponse,
|
||||
|
|
|
@ -37,7 +37,11 @@ export enum PICKED_UPLOAD_TYPE {
|
|||
export interface Electron {
|
||||
// - General
|
||||
|
||||
/** Return the version of the desktop app. */
|
||||
/**
|
||||
* Return the version of the desktop app.
|
||||
*
|
||||
* The return value is of the form `v1.2.3`.
|
||||
*/
|
||||
appVersion: () => Promise<string>;
|
||||
|
||||
/**
|
||||
|
@ -97,6 +101,43 @@ export interface Electron {
|
|||
*/
|
||||
onMainWindowFocus: (cb?: () => void) => void;
|
||||
|
||||
// - App update
|
||||
|
||||
/**
|
||||
* Set or clear the callback {@link cb} to invoke whenever a new
|
||||
* (actionable) app update is available. This allows the Node.js layer to
|
||||
* ask the renderer to show an "Update available" dialog to the user.
|
||||
*
|
||||
* Note: Setting a callback clears any previous callbacks.
|
||||
*/
|
||||
onAppUpdateAvailable: (
|
||||
cb?: ((updateInfo: AppUpdateInfo) => void) | undefined,
|
||||
) => void;
|
||||
|
||||
/**
|
||||
* Restart the app to apply the latest available update.
|
||||
*
|
||||
* This is expected to be called in response to {@link onAppUpdateAvailable}
|
||||
* if the user so wishes.
|
||||
*/
|
||||
updateAndRestart: () => void;
|
||||
|
||||
/**
|
||||
* Mute update notifications for the given {@link version}. This allows us
|
||||
* to implement the "Install on next launch" functionality in response to
|
||||
* the {@link onAppUpdateAvailable} event.
|
||||
*/
|
||||
updateOnNextRestart: (version: string) => void;
|
||||
|
||||
/**
|
||||
* Skip the app update with the given {@link version}.
|
||||
*
|
||||
* This is expected to be called in response to {@link onAppUpdateAvailable}
|
||||
* if the user so wishes. It will remember this {@link version} as having
|
||||
* been marked as skipped so that we don't prompt the user again.
|
||||
*/
|
||||
skipAppUpdate: (version: string) => void;
|
||||
|
||||
/**
|
||||
* A subset of filesystem access APIs.
|
||||
*
|
||||
|
@ -132,18 +173,6 @@ export interface Electron {
|
|||
* the dataflow.
|
||||
*/
|
||||
|
||||
// - App update
|
||||
|
||||
updateAndRestart: () => void;
|
||||
|
||||
skipAppUpdate: (version: string) => void;
|
||||
|
||||
muteUpdateNotification: (version: string) => void;
|
||||
|
||||
registerUpdateEventListener: (
|
||||
showUpdateDialog: (updateInfo: AppUpdateInfo) => void,
|
||||
) => void;
|
||||
|
||||
// - Conversion
|
||||
|
||||
convertToJPEG: (
|
||||
|
|
Loading…
Add table
Reference in a new issue