Skip to content

Commit

Permalink
fix: clean restart after auto update
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfreska committed May 13, 2024
1 parent 0bda688 commit cb109d3
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 24 deletions.
6 changes: 6 additions & 0 deletions .changeset/rare-ladybugs-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'renterd': patch
'hostd': patch
---

Fix an issue with restarting after automatic updates.
46 changes: 39 additions & 7 deletions hostd/main/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { app, globalShortcut } from 'electron'
import { app, autoUpdater, globalShortcut } from 'electron'
import { stopDaemon } from './daemon'
import { initTray } from './tray'
import { state } from './state'
Expand Down Expand Up @@ -27,22 +27,54 @@ app.on('ready', async () => {
startup()
})

app.on('before-quit', async () => {
// Emitted after app.quit is called and before windows are closed.
app.on('before-quit', async (event?: { preventDefault: () => void }) => {
if (!state.isQuitting) {
// Events do not support waiting for asynchronous operations to complete.
// Instead we cancel the quit event with preventDefault, call quitDaemonAndApp,
// and then call app.quit() again to atually quit the app. After the second
// call to app.quit(), isQuitting will be set to true, and the app will quit.
event?.preventDefault()
await quitDaemonAndApp()
app.quit()
}
})

// https://www.electronjs.org/docs/latest/api/app#event-before-quit
// When restarting from an automatic update before-quit is
// not called **before** all windows are closed, so we must instead
// use this autoUpdater event to call quitDaemonAndApp.
autoUpdater.on(
'before-quit-for-update',
async (event?: { preventDefault: () => void }) => {
if (!state.isQuitting) {
event?.preventDefault()
await quitDaemonAndApp()
autoUpdater.quitAndInstall()
}
}
)

app.on('will-quit', async () => {
// Unregister the shortcut when the application is about to quit
// Unregister the shortcut when the application is about to quit.
globalShortcut.unregisterAll()

// https://www.electronjs.org/docs/latest/api/app#event-before-quit
// Note: On Windows, 'before-quit' event will not be emitted if the app is
// closed due to a shutdown/restart of the system or a user logout.
// Adding this extra attempt to quit the app for windows, but there is no
// guarantee that this will run before the app is killed.
if (!state.isQuitting) {
await quitDaemonAndApp()
}
})

// Quit the app once all windows are closed
// even though closing windows is not really possible
app.on('window-all-closed', app.quit)
// The default behavior of this event is to quit the app when all windows are closed.
// Because closeMainWindow does not actually close the window, this event is
// never used to quit the app, overriding it with a no-op to make this clear.
app.on('window-all-closed', () => {})

// https://github.com/mongodb-js/electron-squirrel-startup
// Windows: https://github.com/mongodb-js/electron-squirrel-startup
if (require('electron-squirrel-startup')) {
app.quit()
}
Expand Down
4 changes: 2 additions & 2 deletions hostd/main/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import {
getIsConfigured,
saveConfig,
} from './config'
import { closeWindow } from './window'
import { closeMainWindow } from './window'

export function initIpc() {
ipcMain.handle('open-browser', (_, url: string) => {
shell.openExternal(url)
})
ipcMain.handle('window-close', () => {
closeWindow()
closeMainWindow()
})
ipcMain.handle('daemon-start', async (_) => {
await startDaemon()
Expand Down
10 changes: 7 additions & 3 deletions hostd/main/window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ export function initWindow() {
},
})

// Hide the main window instead of closing it, to keep the app running in the tray
state.mainWindow.on('close', closeWindow)
state.mainWindow.on('close', closeMainWindow)

const url = env.isDev
? 'http://localhost:8000/'
Expand All @@ -37,12 +36,17 @@ export function initWindow() {
state.mainWindow.loadURL(url)
}

export function closeWindow(event?: { preventDefault: () => void }) {
// Hide the main window instead of closing it, to keep the app running in the tray.
export function closeMainWindow(event?: { preventDefault: () => void }) {
if (!state.isQuitting) {
event?.preventDefault()
if (system.isDarwin) {
// Hide the application icon in the dock. This is different from the
// mainWindow.hide() method, which hides the main window.
app.dock.hide()
}
// Hides the main window, the window will no longer show in the taskbar,
// but the window is not closed, it is still running in the background.
state.mainWindow?.hide()
}
}
46 changes: 39 additions & 7 deletions renterd/main/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { app, globalShortcut } from 'electron'
import { app, autoUpdater, globalShortcut } from 'electron'
import { stopDaemon } from './daemon'
import { initTray } from './tray'
import { state } from './state'
Expand Down Expand Up @@ -27,22 +27,54 @@ app.on('ready', async () => {
startup()
})

app.on('before-quit', async () => {
// Emitted after app.quit is called and before windows are closed.
app.on('before-quit', async (event?: { preventDefault: () => void }) => {
if (!state.isQuitting) {
// Events do not support waiting for asynchronous operations to complete.
// Instead we cancel the quit event with preventDefault, call quitDaemonAndApp,
// and then call app.quit() again to atually quit the app. After the second
// call to app.quit(), isQuitting will be set to true, and the app will quit.
event?.preventDefault()
await quitDaemonAndApp()
app.quit()
}
})

// https://www.electronjs.org/docs/latest/api/app#event-before-quit
// When restarting from an automatic update before-quit is
// not called **before** all windows are closed, so we must instead
// use this autoUpdater event to call quitDaemonAndApp.
autoUpdater.on(
'before-quit-for-update',
async (event?: { preventDefault: () => void }) => {
if (!state.isQuitting) {
event?.preventDefault()
await quitDaemonAndApp()
autoUpdater.quitAndInstall()
}
}
)

app.on('will-quit', async () => {
// Unregister the shortcut when the application is about to quit
// Unregister the shortcut when the application is about to quit.
globalShortcut.unregisterAll()

// https://www.electronjs.org/docs/latest/api/app#event-before-quit
// Note: On Windows, 'before-quit' event will not be emitted if the app is
// closed due to a shutdown/restart of the system or a user logout.
// Adding this extra attempt to quit the app for windows, but there is no
// guarantee that this will run before the app is killed.
if (!state.isQuitting) {
await quitDaemonAndApp()
}
})

// Quit the app once all windows are closed
// even though closing windows is not really possible
app.on('window-all-closed', app.quit)
// The default behavior of this event is to quit the app when all windows are closed.
// Because closeMainWindow does not actually close the window, this event is
// never used to quit the app, overriding it with a no-op to make this clear.
app.on('window-all-closed', () => {})

// https://github.com/mongodb-js/electron-squirrel-startup
// Windows: https://github.com/mongodb-js/electron-squirrel-startup
if (require('electron-squirrel-startup')) {
app.quit()
}
Expand Down
4 changes: 2 additions & 2 deletions renterd/main/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import {
getIsConfigured,
saveConfig,
} from './config'
import { closeWindow } from './window'
import { closeMainWindow } from './window'

export function initIpc() {
ipcMain.handle('open-browser', (_, url: string) => {
shell.openExternal(url)
})
ipcMain.handle('window-close', () => {
closeWindow()
closeMainWindow()
})
ipcMain.handle('daemon-start', async (_) => {
await startDaemon()
Expand Down
10 changes: 7 additions & 3 deletions renterd/main/window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ export function initWindow() {
},
})

// Hide the main window instead of closing it, to keep the app running in the tray
state.mainWindow.on('close', closeWindow)
state.mainWindow.on('close', closeMainWindow)

const url = env.isDev
? 'http://localhost:8000/'
Expand All @@ -37,12 +36,17 @@ export function initWindow() {
state.mainWindow.loadURL(url)
}

export function closeWindow(event?: { preventDefault: () => void }) {
// Hide the main window instead of closing it, to keep the app running in the tray.
export function closeMainWindow(event?: { preventDefault: () => void }) {
if (!state.isQuitting) {
event?.preventDefault()
if (system.isDarwin) {
// Hide the application icon in the dock. This is different from the
// mainWindow.hide() method, which hides the main window.
app.dock.hide()
}
// Hides the main window, the window will no longer show in the taskbar,
// but the window is not closed, it is still running in the background.
state.mainWindow?.hide()
}
}

0 comments on commit cb109d3

Please sign in to comment.