Install downloaded updates while in tray
This commit is contained in:
parent
c4521a063c
commit
12a2ec8dd4
6 changed files with 87 additions and 24 deletions
|
@ -117,6 +117,10 @@ export class SystemTrayService {
|
|||
this.isQuitting = true;
|
||||
}
|
||||
|
||||
isVisible(): boolean {
|
||||
return this.tray !== undefined;
|
||||
}
|
||||
|
||||
private render(): void {
|
||||
if (this.isEnabled && this.browserWindow) {
|
||||
this.renderEnabled();
|
||||
|
|
12
app/main.ts
12
app/main.ts
|
@ -1161,7 +1161,17 @@ async function readyForUpdates() {
|
|||
settingsChannel !== undefined,
|
||||
'SettingsChannel must be initialized'
|
||||
);
|
||||
await updater.start(settingsChannel, getLogger(), getMainWindow);
|
||||
await updater.start({
|
||||
settingsChannel,
|
||||
logger: getLogger(),
|
||||
getMainWindow,
|
||||
canRunSilently: () => {
|
||||
return (
|
||||
systemTrayService?.isVisible() === true &&
|
||||
mainWindow?.isVisible() === false
|
||||
);
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
getLogger().error(
|
||||
'Error starting update checks:',
|
||||
|
|
|
@ -45,3 +45,17 @@ ManifestDPIAware true
|
|||
|
||||
end_semver_check:
|
||||
!macroend
|
||||
|
||||
!macro customInstall
|
||||
${If} ${Silent}
|
||||
${AndIf} ${isUpdated}
|
||||
# Copied from app-builder-lib templates/nsis/common.nsh:
|
||||
|
||||
# "otherwise app window will be in background"
|
||||
HideWindow
|
||||
|
||||
# Signal modification: '--start-in-tray' added
|
||||
${StdUtils.ExecShellAsUser} $0 "$launchLink" "open" \
|
||||
"--updated --start-in-tray"
|
||||
${EndIf}
|
||||
!macroend
|
||||
|
|
|
@ -84,6 +84,13 @@ type DownloadUpdateResultType = Readonly<{
|
|||
signature: Buffer;
|
||||
}>;
|
||||
|
||||
export type UpdaterOptionsType = Readonly<{
|
||||
settingsChannel: SettingsChannel;
|
||||
logger: LoggerType;
|
||||
getMainWindow: () => BrowserWindow | undefined;
|
||||
canRunSilently: () => boolean;
|
||||
}>;
|
||||
|
||||
export abstract class Updater {
|
||||
protected fileName: string | undefined;
|
||||
|
||||
|
@ -91,17 +98,31 @@ export abstract class Updater {
|
|||
|
||||
protected cachedDifferentialData: DifferentialDownloadDataType | undefined;
|
||||
|
||||
protected readonly logger: LoggerType;
|
||||
|
||||
private readonly settingsChannel: SettingsChannel;
|
||||
|
||||
protected readonly getMainWindow: () => BrowserWindow | undefined;
|
||||
|
||||
private throttledSendDownloadingUpdate: (downloadedSize: number) => void;
|
||||
|
||||
private activeDownload: Promise<boolean> | undefined;
|
||||
|
||||
private markedCannotUpdate = false;
|
||||
|
||||
constructor(
|
||||
protected readonly logger: LoggerType,
|
||||
private readonly settingsChannel: SettingsChannel,
|
||||
protected readonly getMainWindow: () => BrowserWindow | undefined
|
||||
) {
|
||||
private readonly canRunSilently: () => boolean;
|
||||
|
||||
constructor({
|
||||
settingsChannel,
|
||||
logger,
|
||||
getMainWindow,
|
||||
canRunSilently,
|
||||
}: UpdaterOptionsType) {
|
||||
this.settingsChannel = settingsChannel;
|
||||
this.logger = logger;
|
||||
this.getMainWindow = getMainWindow;
|
||||
this.canRunSilently = canRunSilently;
|
||||
|
||||
this.throttledSendDownloadingUpdate = throttle((downloadedSize: number) => {
|
||||
const mainWindow = this.getMainWindow();
|
||||
mainWindow?.webContents.send(
|
||||
|
@ -141,7 +162,10 @@ export abstract class Updater {
|
|||
|
||||
protected abstract deletePreviousInstallers(): Promise<void>;
|
||||
|
||||
protected abstract installUpdate(updateFilePath: string): Promise<void>;
|
||||
protected abstract installUpdate(
|
||||
updateFilePath: string,
|
||||
isSilent: boolean
|
||||
): Promise<void>;
|
||||
|
||||
//
|
||||
// Protected methods
|
||||
|
@ -255,7 +279,7 @@ export abstract class Updater {
|
|||
);
|
||||
}
|
||||
|
||||
await this.installUpdate(updateFilePath);
|
||||
await this.installUpdate(updateFilePath, this.canRunSilently());
|
||||
|
||||
const mainWindow = this.getMainWindow();
|
||||
if (mainWindow) {
|
||||
|
|
|
@ -2,26 +2,20 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import config from 'config';
|
||||
import type { BrowserWindow } from 'electron';
|
||||
|
||||
import type { Updater } from './common';
|
||||
import type { Updater, UpdaterOptionsType } from './common';
|
||||
import { MacOSUpdater } from './macos';
|
||||
import { WindowsUpdater } from './windows';
|
||||
import { isLinuxVersionSupported } from './linux';
|
||||
import type { LoggerType } from '../types/Logging';
|
||||
import { DialogType } from '../types/Dialogs';
|
||||
import type { SettingsChannel } from '../main/settingsChannel';
|
||||
|
||||
let initialized = false;
|
||||
|
||||
let updater: Updater | undefined;
|
||||
|
||||
export async function start(
|
||||
settingsChannel: SettingsChannel,
|
||||
logger: LoggerType,
|
||||
getMainWindow: () => BrowserWindow | undefined
|
||||
): Promise<void> {
|
||||
export async function start(options: UpdaterOptionsType): Promise<void> {
|
||||
const { platform } = process;
|
||||
const { logger, getMainWindow } = options;
|
||||
|
||||
if (initialized) {
|
||||
throw new Error('updater/start: Updates have already been initialized!');
|
||||
|
@ -50,9 +44,9 @@ export async function start(
|
|||
}
|
||||
|
||||
if (platform === 'win32') {
|
||||
updater = new WindowsUpdater(logger, settingsChannel, getMainWindow);
|
||||
updater = new WindowsUpdater(options);
|
||||
} else if (platform === 'darwin') {
|
||||
updater = new MacOSUpdater(logger, settingsChannel, getMainWindow);
|
||||
updater = new MacOSUpdater(options);
|
||||
} else {
|
||||
throw new Error('updater/start: Unsupported platform');
|
||||
}
|
||||
|
|
|
@ -44,13 +44,16 @@ export class WindowsUpdater extends Updater {
|
|||
})
|
||||
);
|
||||
}
|
||||
protected async installUpdate(updateFilePath: string): Promise<void> {
|
||||
protected async installUpdate(
|
||||
updateFilePath: string,
|
||||
isSilent: boolean
|
||||
): Promise<void> {
|
||||
const { logger } = this;
|
||||
|
||||
this.setUpdateListener(async () => {
|
||||
const doInstall = async () => {
|
||||
logger.info('downloadAndInstall: installing...');
|
||||
try {
|
||||
await this.install(updateFilePath);
|
||||
await this.install(updateFilePath, isSilent);
|
||||
this.installing = true;
|
||||
} catch (error) {
|
||||
this.markCannotUpdate(error);
|
||||
|
@ -61,10 +64,18 @@ export class WindowsUpdater extends Updater {
|
|||
logger.info('downloadAndInstall: restarting...');
|
||||
markShouldQuit();
|
||||
app.quit();
|
||||
});
|
||||
};
|
||||
|
||||
if (isSilent) {
|
||||
logger.info('downloadAndInstall: running immediately...');
|
||||
await doInstall();
|
||||
return;
|
||||
}
|
||||
|
||||
this.setUpdateListener(doInstall);
|
||||
}
|
||||
|
||||
private async install(filePath: string): Promise<void> {
|
||||
private async install(filePath: string, isSilent: boolean): Promise<void> {
|
||||
if (this.installing) {
|
||||
return;
|
||||
}
|
||||
|
@ -73,6 +84,12 @@ export class WindowsUpdater extends Updater {
|
|||
|
||||
logger.info('windows/install: installing package...');
|
||||
const args = ['--updated'];
|
||||
if (isSilent) {
|
||||
// App isn't automatically restarted with "/S" flag, but "--updated"
|
||||
// will trigger our code in `build/installer.nsh` that will start the app
|
||||
// with "--start-in-tray" flag (see `app/main.ts`)
|
||||
args.push('/S');
|
||||
}
|
||||
const options = {
|
||||
detached: true,
|
||||
stdio: 'ignore' as const, // TypeScript considers this a plain string without help
|
||||
|
|
Loading…
Add table
Reference in a new issue