UNPKG

backsplash-app

Version:
176 lines (153 loc) 5.46 kB
import { useRecoilState } from "recoil"; import { updateStateAtom } from "../state/atoms/updateAtoms"; import { useEffect } from "react"; import { UPDATE_MESSAGES } from "@/ipc/channels/messages"; import { UpdateState, UpdateInfo } from "@/ipc/services/updateService"; import { IpcRendererEvent } from "electron"; // No need to define our own interface, we'll use the window.electron type // Get the IPC renderer from the window object const getIpcRenderer = () => { if (window.electron && window.electron.ipcRenderer) { return window.electron.ipcRenderer; } return null; }; export function useUpdateService() { const [updateState, setUpdateState] = useRecoilState(updateStateAtom); const ipcRenderer = getIpcRenderer(); useEffect(() => { if (!ipcRenderer) { console.error("IPC renderer not available"); return; } // Listen for update events const checkingHandler = () => { setUpdateState((prev) => ({ ...prev, checking: true })); }; const availableHandler = (_event: IpcRendererEvent, data: UpdateInfo) => { setUpdateState((prev) => ({ ...prev, checking: false, available: true, info: data, })); }; const notAvailableHandler = () => { setUpdateState((prev) => ({ ...prev, checking: false, available: false, })); }; const progressHandler = (_event: IpcRendererEvent, data: { percent: number }) => { setUpdateState((prev) => ({ ...prev, downloading: true, downloadProgress: data.percent, })); }; const downloadedHandler = (_event: IpcRendererEvent, data: UpdateInfo) => { setUpdateState((prev) => ({ ...prev, downloading: false, downloaded: true, info: data, })); }; const errorHandler = (_event: IpcRendererEvent, error: string) => { setUpdateState((prev) => ({ ...prev, checking: false, downloading: false, error, })); }; // Register all handlers ipcRenderer.on(`${UPDATE_MESSAGES.EVENTS.PREFIX}:checking-for-update`, checkingHandler); ipcRenderer.on(`${UPDATE_MESSAGES.EVENTS.PREFIX}:update-available`, availableHandler); ipcRenderer.on(`${UPDATE_MESSAGES.EVENTS.PREFIX}:update-not-available`, notAvailableHandler); ipcRenderer.on(`${UPDATE_MESSAGES.EVENTS.PREFIX}:download-progress`, progressHandler); ipcRenderer.on(`${UPDATE_MESSAGES.EVENTS.PREFIX}:update-downloaded`, downloadedHandler); ipcRenderer.on(`${UPDATE_MESSAGES.EVENTS.PREFIX}:error`, errorHandler); // Get initial state from electron-store const fetchInitialState = async () => { try { const storeState = await ipcRenderer.invoke("store:get", "update-state"); if (storeState) { setUpdateState((prev) => ({ ...prev, ...(storeState as UpdateState), })); } } catch (error) { console.error("Failed to get initial update state:", error); } }; fetchInitialState(); // Return cleanup function return () => { // Clean up listeners ipcRenderer.removeListener(`${UPDATE_MESSAGES.EVENTS.PREFIX}:checking-for-update`, checkingHandler); ipcRenderer.removeListener(`${UPDATE_MESSAGES.EVENTS.PREFIX}:update-available`, availableHandler); ipcRenderer.removeListener(`${UPDATE_MESSAGES.EVENTS.PREFIX}:update-not-available`, notAvailableHandler); ipcRenderer.removeListener(`${UPDATE_MESSAGES.EVENTS.PREFIX}:download-progress`, progressHandler); ipcRenderer.removeListener(`${UPDATE_MESSAGES.EVENTS.PREFIX}:update-downloaded`, downloadedHandler); ipcRenderer.removeListener(`${UPDATE_MESSAGES.EVENTS.PREFIX}:error`, errorHandler); }; }, [ipcRenderer, setUpdateState]); const checkForUpdate = async (): Promise<boolean> => { if (!ipcRenderer) { console.error("IPC renderer not available"); return false; } try { return (await ipcRenderer.invoke(UPDATE_MESSAGES.CHECK_FOR_UPDATE)) as boolean; } catch (error) { console.error("Failed to check for update:", error); setUpdateState((prev) => ({ ...prev, checking: false, error: String(error), })); return false; } }; const downloadUpdate = async (): Promise<boolean> => { if (!ipcRenderer) { console.error("IPC renderer not available"); return false; } setUpdateState((prev) => ({ ...prev, downloading: true })); try { return (await ipcRenderer.invoke(UPDATE_MESSAGES.DOWNLOAD_UPDATE)) as boolean; } catch (error) { console.error("Failed to download update:", error); setUpdateState((prev) => ({ ...prev, downloading: false, error: String(error), })); return false; } }; const installUpdate = (): void => { if (!ipcRenderer) { console.error("IPC renderer not available"); return; } ipcRenderer.invoke(UPDATE_MESSAGES.INSTALL_UPDATE); }; return { updateState, checkForUpdate, downloadUpdate, installUpdate, hasUpdate: updateState.available, isCheckingForUpdate: updateState.checking, isDownloadingUpdate: updateState.downloading, isUpdateDownloaded: updateState.downloaded, updateInfo: updateState.info, updateError: updateState.error, downloadProgress: updateState.downloadProgress || 0, }; }