import { ipcRenderer } from 'electron' import type { ProgressInfo } from 'electron-updater' import { useCallback, useEffect, useState } from 'react' import Modal from '@/components/update/Modal' import Progress from '@/components/update/Progress' import './update.css' const Update = () => { const [checking, setChecking] = useState(false) const [updateAvailable, setUpdateAvailable] = useState(false) const [versionInfo, setVersionInfo] = useState() const [updateError, setUpdateError] = useState() const [progressInfo, setProgressInfo] = useState>() const [modalOpen, setModalOpen] = useState(false) const [modalBtn, setModalBtn] = useState<{ cancelText?: string okText?: string onCancel?: () => void onOk?: () => void }>({ onCancel: () => setModalOpen(false), onOk: () => ipcRenderer.invoke('start-download'), }) const checkUpdate = async () => { setChecking(true) /** * @type {import('electron-updater').UpdateCheckResult | null | { message: string, error: Error }} */ const result = await ipcRenderer.invoke('check-update') setProgressInfo({ percent: 0 }) setChecking(false) setModalOpen(true) if (result?.error) { setUpdateAvailable(false) setUpdateError(result?.error) } } const onUpdateCanAvailable = useCallback((_event: Electron.IpcRendererEvent, arg1: VersionInfo) => { setVersionInfo(arg1) setUpdateError(undefined) // Can be update if (arg1.update) { setModalBtn(state => ({ ...state, cancelText: 'Cancel', okText: 'Update', onOk: () => ipcRenderer.invoke('start-download'), })) setUpdateAvailable(true) } else { setUpdateAvailable(false) } }, []) const onUpdateError = useCallback((_event: Electron.IpcRendererEvent, arg1: ErrorType) => { setUpdateAvailable(false) setUpdateError(arg1) }, []) const onDownloadProgress = useCallback((_event: Electron.IpcRendererEvent, arg1: ProgressInfo) => { setProgressInfo(arg1) }, []) const onUpdateDownloaded = useCallback((_event: Electron.IpcRendererEvent, ...args: any[]) => { setProgressInfo({ percent: 100 }) setModalBtn(state => ({ ...state, cancelText: 'Later', okText: 'Install now', onOk: () => ipcRenderer.invoke('quit-and-install'), })) }, []) useEffect(() => { // Get version information and whether to update ipcRenderer.on('update-can-available', onUpdateCanAvailable) ipcRenderer.on('update-error', onUpdateError) ipcRenderer.on('download-progress', onDownloadProgress) ipcRenderer.on('update-downloaded', onUpdateDownloaded) return () => { ipcRenderer.off('update-can-available', onUpdateCanAvailable) ipcRenderer.off('update-error', onUpdateError) ipcRenderer.off('download-progress', onDownloadProgress) ipcRenderer.off('update-downloaded', onUpdateDownloaded) } }, []) return ( <>
{updateError ? (

Error downloading the latest version.

{updateError.message}

) : updateAvailable ? (
The last version is: v{versionInfo?.newVersion}
v{versionInfo?.version} -> v{versionInfo?.newVersion}
Update progress:
) : (
{JSON.stringify(versionInfo ?? {}, null, 2)}
)}
) } export default Update