-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
electron: Offer automatic app update
With this new implementation, the user is informed that a new version of the application is available and can choose between downloading it or not.
- Loading branch information
1 parent
8372c77
commit 6c4c088
Showing
6 changed files
with
296 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { BrowserWindow, ipcMain } from 'electron' | ||
import electronUpdater, { type AppUpdater } from 'electron-updater' | ||
|
||
/** | ||
* Setup auto updater | ||
* @param {BrowserWindow} mainWindow - The main Electron window | ||
*/ | ||
export const setupAutoUpdater = (mainWindow: BrowserWindow): void => { | ||
const autoUpdater: AppUpdater = electronUpdater.autoUpdater | ||
autoUpdater.logger = console | ||
autoUpdater.autoDownload = false // Prevent automatic downloads | ||
|
||
autoUpdater | ||
.checkForUpdates() | ||
.then((e) => console.info(e)) | ||
.catch((e) => console.error(e)) | ||
|
||
autoUpdater.on('checking-for-update', () => { | ||
mainWindow.webContents.send('checking-for-update') | ||
}) | ||
|
||
autoUpdater.on('update-available', (info) => { | ||
mainWindow.webContents.send('update-available', info) | ||
}) | ||
|
||
autoUpdater.on('update-not-available', (info) => { | ||
mainWindow.webContents.send('update-not-available', info) | ||
}) | ||
|
||
autoUpdater.on('download-progress', (progressInfo) => { | ||
mainWindow.webContents.send('download-progress', progressInfo) | ||
}) | ||
|
||
autoUpdater.on('update-downloaded', (info) => { | ||
mainWindow.webContents.send('update-downloaded', info) | ||
}) | ||
|
||
// Add handlers for update control | ||
ipcMain.on('download-update', () => { | ||
autoUpdater.downloadUpdate() | ||
}) | ||
|
||
ipcMain.on('install-update', () => { | ||
autoUpdater.quitAndInstall() | ||
}) | ||
|
||
ipcMain.on('cancel-update', () => { | ||
autoUpdater.removeAllListeners('update-downloaded') | ||
autoUpdater.removeAllListeners('download-progress') | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
<template> | ||
<InteractionDialog | ||
v-model="showUpdateDialog" | ||
:title="dialogTitle" | ||
:message="dialogMessage" | ||
:variant="dialogVariant" | ||
:actions="dialogActions" | ||
max-width="560" | ||
> | ||
<template #content> | ||
<div v-if="updateInfo" class="mt-2"> | ||
<strong>Update Details:</strong> | ||
<p>Current Version: {{ app_version.version }}</p> | ||
<p>New Version: {{ updateInfo.version }}</p> | ||
<p>Release Date: {{ formatDate(updateInfo.releaseDate) }}</p> | ||
</div> | ||
<v-progress-linear | ||
v-if="showProgress" | ||
:model-value="downloadProgress" | ||
color="primary" | ||
height="25" | ||
rounded | ||
class="my-4" | ||
> | ||
<template #default> | ||
<strong>{{ Math.round(downloadProgress) }}%</strong> | ||
</template> | ||
</v-progress-linear> | ||
</template> | ||
</InteractionDialog> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { useStorage } from '@vueuse/core' | ||
import { onBeforeMount, ref } from 'vue' | ||
import InteractionDialog, { type Action } from '@/components/InteractionDialog.vue' | ||
import { app_version } from '@/libs/cosmos' | ||
import { isElectron } from '@/libs/utils' | ||
const showUpdateDialog = ref(false) | ||
const dialogTitle = ref('') | ||
const dialogMessage = ref('') | ||
const dialogVariant = ref<'error' | 'info' | 'success' | 'warning' | 'text-only'>('info') | ||
const showProgress = ref(false) | ||
const downloadProgress = ref(0) | ||
const dialogActions = ref<Action[]>([]) | ||
const updateInfo = ref({ | ||
version: '', | ||
releaseDate: '', | ||
releaseNotes: '', | ||
}) | ||
const ignoredUpdateVersions = useStorage<string[]>('cockpit-ignored-update-versions', []) | ||
const formatDate = (date: string): string => { | ||
return new Date(date).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }) | ||
} | ||
onBeforeMount(() => { | ||
if (!isElectron()) { | ||
console.info('Not in Electron environment. UpdateNotification will not be initialized.') | ||
return | ||
} | ||
if (!window.electronAPI) { | ||
console.error('window.electronAPI is not defined. UpdateNotification will not be initialized.') | ||
return | ||
} | ||
// Listen for update events | ||
window.electronAPI.onCheckingForUpdate(() => { | ||
console.log('Checking if there are updates for the Electron app...') | ||
dialogTitle.value = 'Checking for Updates' | ||
dialogMessage.value = 'Looking for new versions of the application...' | ||
dialogVariant.value = 'info' | ||
dialogActions.value = [] | ||
showProgress.value = false | ||
showUpdateDialog.value = true | ||
}) | ||
window.electronAPI.onUpdateNotAvailable(() => { | ||
console.log('No updates available for the Electron app.') | ||
dialogTitle.value = 'No Updates Available' | ||
dialogMessage.value = 'You are running the latest version of the application.' | ||
dialogVariant.value = 'success' | ||
dialogActions.value = [ | ||
{ | ||
text: 'OK', | ||
action: () => { | ||
showUpdateDialog.value = false | ||
}, | ||
}, | ||
] | ||
showProgress.value = false | ||
}) | ||
window.electronAPI.onUpdateAvailable((info) => { | ||
console.log('Update available for the Electron app.', info) | ||
dialogTitle.value = 'Update Available' | ||
dialogMessage.value = 'A new version of the application is available. Would you like to download it now?' | ||
dialogVariant.value = 'info' | ||
updateInfo.value = { ...info } | ||
dialogActions.value = [ | ||
{ | ||
text: 'Ignore This Version', | ||
action: () => { | ||
console.log(`User chose to ignore version ${updateInfo.value.version}`) | ||
ignoredUpdateVersions.value.push(updateInfo.value.version) | ||
window.electronAPI!.cancelUpdate() | ||
showUpdateDialog.value = false | ||
}, | ||
}, | ||
{ | ||
text: 'Download', | ||
action: () => { | ||
window.electronAPI!.downloadUpdate() | ||
showProgress.value = true | ||
dialogActions.value = [ | ||
{ | ||
text: 'Cancel', | ||
action: () => { | ||
console.log('User chose to cancel the update for the Electron app.') | ||
window.electronAPI!.cancelUpdate() | ||
showUpdateDialog.value = false | ||
dialogMessage.value = 'Downloading update...' | ||
}, | ||
}, | ||
] | ||
}, | ||
}, | ||
{ | ||
text: 'Not Now', | ||
action: () => { | ||
window.electronAPI!.cancelUpdate() | ||
showUpdateDialog.value = false | ||
}, | ||
}, | ||
] | ||
// Check if this version is in the ignored list | ||
if (ignoredUpdateVersions.value.includes(info.version)) { | ||
console.log(`Skipping ignored version ${info.version}.`) | ||
showUpdateDialog.value = false | ||
return | ||
} | ||
showUpdateDialog.value = true | ||
}) | ||
window.electronAPI.onDownloadProgress((progressInfo) => { | ||
downloadProgress.value = progressInfo.percent | ||
}) | ||
window.electronAPI.onUpdateDownloaded(() => { | ||
console.log('Finished downloading the update for the Electron app.') | ||
dialogTitle.value = 'Update Ready to Install' | ||
dialogMessage.value = | ||
'The update has been downloaded. Would you like to install it now? The application will restart during installation.' | ||
dialogVariant.value = 'info' | ||
showProgress.value = false | ||
dialogActions.value = [ | ||
{ | ||
text: 'Install Now', | ||
action: () => { | ||
console.log('User chose to install the update for the Electron app now.') | ||
window.electronAPI!.installUpdate() | ||
showUpdateDialog.value = false | ||
}, | ||
}, | ||
{ | ||
text: 'Later', | ||
action: () => { | ||
console.log('User chose to install the update for the Electron app later.') | ||
showUpdateDialog.value = false | ||
}, | ||
}, | ||
] | ||
showUpdateDialog.value = true | ||
}) | ||
}) | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters