diff --git a/src/backend/stores/mihoyo.ts b/src/backend/stores/mihoyo.ts index 54219b6..8c9b1ca 100644 --- a/src/backend/stores/mihoyo.ts +++ b/src/backend/stores/mihoyo.ts @@ -1,28 +1,103 @@ +import { useEffect, useState } from "preact/hooks"; + import { create } from "zustand"; import { persist, createJSONStorage } from "zustand/middleware"; import { invoke } from "@tauri-apps/api"; +import { exists } from "@tauri-apps/api/fs"; +import { convertFileSrc } from "@tauri-apps/api/tauri"; -export type GenshinStore = { +import { LauncherResponse, StoreWrite } from "@backend/types.ts"; +import { AppDataPath, LauncherUrls } from "@app/constants.ts"; + +export type GameDataStore = { backgroundHash: string; + + fetchLatestBackground: () => Promise; }; -export const useGenshinStore = create( +export const useGenshinStore = create()( persist( - (): GenshinStore => ({ - backgroundHash: "" + (set): GameDataStore => ({ + backgroundHash: "", + fetchLatestBackground: () => fetchLatestBackground( + set as StoreWrite, LauncherUrls.GENSHIN_IMPACT) }), { - name: "genshin", + name: "genshin_data", + storage: createJSONStorage(() => localStorage) + } + ) +); + +export const useStarRailStore = create()( + persist( + (set) => ({ + backgroundHash: "", + fetchLatestBackground: () => fetchLatestBackground( + set as StoreWrite, LauncherUrls.STAR_RAIL) + }), + { + name: "starrail_data", storage: createJSONStorage(() => localStorage) } ) ); +/** + * Fetches the latest background image. + * + * @param set The store write function. + * @param serviceUrl The URL used for fetching the background. + */ +export async function fetchLatestBackground(set: StoreWrite, serviceUrl: string): Promise { + // Fetch the launcher data. + const launcherData = await fetch(serviceUrl, { cache: "force-cache" }); + const responseData = await launcherData.json() as LauncherResponse; + + // Check if the background exists on the system. + const backgroundUrl = responseData.data.adv.background; + const backgroundHash = backgroundUrl.split("/").pop()?.substring(0, 32); + if (backgroundHash == undefined) throw new Error("Unable to find the hash of the background."); + + // Check if the file exists on the system. + const filePath = `${AppDataPath}/bg/${backgroundHash}.png`; + if (!await exists(filePath)) { + // Download the image. + await invoke("download_file", { + url: backgroundUrl, toFile: filePath + }); + + // Update the store. + set({ backgroundHash }); + } +} + +/** + * Attempts to get the file of the background. + * + * @param hash The hash of the background. + */ +export async function getBackgroundFile(hash: string): Promise { + return convertFileSrc(`${AppDataPath}/bg/${hash}.png`); +} + /** * React hook which returns the URL of the locally cached background image. */ export function useBackground() { - const { backgroundHash } = useGenshinStore(); + const { backgroundHash, fetchLatestBackground } = useGenshinStore(); const [background, setBackground] = useState(null); + + useEffect(() => { + (async () => { + if (backgroundHash != "") { + setBackground(await getBackgroundFile(backgroundHash)); + } else { + fetchLatestBackground(); + } + })(); + }, [backgroundHash, fetchLatestBackground]); + + return background; }