backsplash-app
Version:
An AI powered wallpaper app.
176 lines (153 loc) • 5.46 kB
text/typescript
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,
};
}