-
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 applicaiton is available and can choose between downloading it or not.
- Loading branch information
1 parent
2c125a3
commit e4e006c
Showing
4 changed files
with
296 additions
and
10 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { contextBridge, ipcRenderer } from 'electron' | ||
|
||
contextBridge.exposeInMainWorld('electronAPI', { | ||
onUpdateAvailable: (callback: (info: any) => void) => | ||
ipcRenderer.on('update-available', (_event, info) => callback(info)), | ||
onUpdateDownloaded: (callback: (info: any) => void) => | ||
ipcRenderer.on('update-downloaded', (_event, info) => callback(info)), | ||
onCheckingForUpdate: (callback: () => void) => | ||
ipcRenderer.on('checking-for-update', (_event) => callback()), | ||
onUpdateNotAvailable: (callback: (info: any) => void) => | ||
ipcRenderer.on('update-not-available', (_event, info) => callback(info)), | ||
onDownloadProgress: (callback: (info: any) => void) => | ||
ipcRenderer.on('download-progress', (_event, info) => callback(info)), | ||
downloadUpdate: () => ipcRenderer.send('download-update'), | ||
installUpdate: () => ipcRenderer.send('install-update'), | ||
cancelUpdate: () => ipcRenderer.send('cancel-update'), | ||
}) |
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,193 @@ | ||
<template> | ||
<InteractionDialog | ||
v-model="showUpdateDialog" | ||
:title="dialogTitle" | ||
:message="dialogMessage" | ||
:variant="dialogVariant" | ||
:actions="dialogActions" | ||
> | ||
<template v-if="showProgress" #content> | ||
<v-progress-linear :model-value="downloadProgress" color="primary" height="25" rounded class="mb-2"> | ||
<template #default> | ||
<strong>{{ Math.round(downloadProgress) }}%</strong> | ||
</template> | ||
</v-progress-linear> | ||
</template> | ||
</InteractionDialog> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { ref } from 'vue' | ||
import InteractionDialog from '@/components/InteractionDialog.vue' | ||
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< | ||
Array<{ | ||
/** | ||
* Text of the button | ||
*/ | ||
text: string | ||
/** | ||
* Action to be executed when the button is clicked | ||
*/ | ||
action: () => void | ||
/** | ||
* Color of the button | ||
*/ | ||
color: string | ||
}> | ||
>([]) | ||
/** | ||
* Interface for the electron API exposed through preload | ||
*/ | ||
declare global { | ||
/** | ||
* Extended Window interface with Electron API | ||
*/ | ||
interface Window { | ||
/** | ||
* Electron API for update management | ||
*/ | ||
electronAPI: { | ||
/** | ||
* Register callback for update available event | ||
*/ | ||
onUpdateAvailable: (callback: (info: any) => void) => void | ||
/** | ||
* Register callback for update downloaded event | ||
*/ | ||
onUpdateDownloaded: (callback: (info: any) => void) => void | ||
/** | ||
* Trigger update download | ||
*/ | ||
downloadUpdate: () => void | ||
/** | ||
* Trigger update installation | ||
*/ | ||
installUpdate: () => void | ||
/** | ||
* Cancel ongoing update | ||
*/ | ||
cancelUpdate: () => void | ||
/** | ||
* Register callback for checking for update event | ||
*/ | ||
onCheckingForUpdate: (callback: () => void) => void | ||
/** | ||
* Register callback for update not available event | ||
*/ | ||
onUpdateNotAvailable: (callback: (info: any) => void) => void | ||
/** | ||
* Register callback for download progress event | ||
*/ | ||
onDownloadProgress: (callback: (info: any) => void) => void | ||
} | ||
} | ||
} | ||
// 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 | ||
}, | ||
color: 'primary', | ||
}, | ||
] | ||
showProgress.value = false | ||
}) | ||
window.electronAPI.onUpdateAvailable(() => { | ||
console.log('Update available for the Electron app.') | ||
dialogTitle.value = 'Update Available' | ||
dialogMessage.value = 'A new version of the application is available. Would you like to download it now?' | ||
dialogVariant.value = 'info' | ||
dialogActions.value = [ | ||
{ | ||
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 | ||
}, | ||
color: 'error', | ||
}, | ||
] | ||
}, | ||
color: 'primary', | ||
}, | ||
{ | ||
text: 'Not Now', | ||
action: () => { | ||
window.electronAPI.cancelUpdate() | ||
showUpdateDialog.value = false | ||
}, | ||
color: 'error', | ||
}, | ||
] | ||
showUpdateDialog.value = true | ||
}) | ||
window.electronAPI.onDownloadProgress((progressInfo) => { | ||
downloadProgress.value = progressInfo.percent | ||
dialogMessage.value = `Downloading update... ${Math.round(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 | ||
}, | ||
color: 'primary', | ||
}, | ||
{ | ||
text: 'Later', | ||
action: () => { | ||
console.log('User chose to install the update for the Electron app later.') | ||
showUpdateDialog.value = false | ||
}, | ||
color: 'error', | ||
}, | ||
] | ||
showUpdateDialog.value = true | ||
}) | ||
</script> |