import useSettingStore from "@/stores/settingStore" import { Check, Folder, File, X, Settings } from "lucide-react" import { useEffect } from "react" import { toast } from "react-toastify" import { DiffService} from "@bindings/firefly-launcher/internal/diff-service" import { FSService } from "@bindings/firefly-launcher/internal/fs-service" import { motion } from "motion/react" import useDiffStore from "@/stores/diffStore" export default function DiffPage() { const { gameDir, setGameDir } = useSettingStore() const { isLoading, setIsLoading, folderCheckResult, setFolderCheckResult, diffDir, setDiffDir, diffCheckResult, setDiffCheckResult, isDiffLoading, setIsDiffLoading, progressUpdate, setProgressUpdate, maxProgressUpdate, setMaxProgressUpdate, stageType, setStageType, messageUpdate, setMessageUpdate } = useDiffStore() useEffect(() => { const getLanguage = async () => { if (gameDir) { const subPath = 'StarRail_Data/StreamingAssets/DesignData/Windows' const fullPath = `${gameDir}/${subPath}` const exists = await FSService.DirExists(fullPath) if (exists) { setFolderCheckResult('success') } else { setFolderCheckResult('error') setGameDir('') } } } getLanguage() }, [gameDir]) const handlePickGameFolder = async () => { try { setIsLoading({game: true, diff: false}) const basePath = await FSService.PickFolder() if (basePath) { setGameDir(basePath) const subPath = 'StarRail_Data/StreamingAssets/DesignData/Windows' const fullPath = `${basePath}/${subPath}` const exists = await FSService.DirExists(fullPath) setFolderCheckResult(exists ? 'success' : 'error') setGameDir(exists ? basePath : '') if (!exists) { toast.error('Game directory not found. Please select the correct folder.') } } else { toast.error('No folder path selected') setFolderCheckResult('error') setGameDir('') } } catch (err: any) { toast.error('PickFolder error:', err) setFolderCheckResult('error') } finally { setIsLoading({game: false, diff: false}) } } const handlePickDiffFile = async () => { try { setIsLoading({game: false, diff: true}) const basePath = await FSService.PickFile("") if (basePath) { if (!basePath.endsWith(".7z") && !basePath.endsWith(".zip") && !basePath.endsWith(".rar")) { toast.error('Not valid file type') setDiffCheckResult('error') setDiffDir('') return } setDiffDir(basePath) setDiffCheckResult('success') } else { toast.error('No file path selected') setDiffCheckResult('error') setDiffDir('') } } catch (err: any) { toast.error('PickFile error:', err) setDiffCheckResult('error') } finally { setIsLoading({game: false, diff: false}) } } const handleUpdateGame = async () => { const handleResult = (ok: boolean, error: string) => { if (!ok) { toast.error(error) return false } return true } try { setIsDiffLoading(true) if (!gameDir || !diffDir) { toast.error('Please select game directory and diff file') return } setStageType('Check Type HDiff') setProgressUpdate(0) setMaxProgressUpdate(1) const [isOk, validType, errorType] = await DiffService.CheckTypeHDiff(diffDir) if (!handleResult(isOk, errorType)) return setProgressUpdate(1) if (['hdiffmap.json', 'hdifffiles.txt', 'hdifffiles.json'].includes(validType)) { setStageType('Version Validate') setProgressUpdate(0) setMaxProgressUpdate(1) const [validVersion, errorVersion] = await DiffService.VersionValidate(gameDir, diffDir) if (!handleResult(validVersion, errorVersion)) return setProgressUpdate(1) } setStageType('Data Extract') const [validData, errorData] = await DiffService.DataExtract(gameDir, diffDir) if (!handleResult(validData, errorData)) return setStageType('Cut Data') setMessageUpdate('') const [validCut, errorCut] = await DiffService.CutData(gameDir) if (!handleResult(validCut, errorCut)) return switch (validType) { case 'hdifffiles.txt': case 'hdiffmap.json': case 'hdifffiles.json': { setStageType('Patch Data') const [validPatch, errorPatch] = await DiffService.HDiffPatchData(gameDir) if (!handleResult(validPatch, errorPatch)) return setStageType('Delete old files') const [validDelete, errorDelete] = await DiffService.DeleteFiles(gameDir) if (!handleResult(validDelete, errorDelete)) return break } case 'manifest': { setStageType('Patch Data') const [validPatch, errorPatch] = await DiffService.LDiffPatchData(gameDir) if (!handleResult(validPatch, errorPatch)) return break } } toast.success('Update game completed') } catch (err: any) { console.error(err) toast.error(`PickFile error: ${err}`) } finally { setIsDiffLoading(false) } } return (
{/* Header */}

🎮 Game Update by Hdiffz

Help you update game with hdiffz

{/* Main Content */}
{/* Folder Selection Section */}

Game Directory

{gameDir && (

{gameDir}

)}
{folderCheckResult && (
{folderCheckResult === 'success' ? ( <> Valid game directory found! ) : ( <> Game directory not found. Please select the correct folder. )}
)}
{/* Folder Selection Section */}

Diff file Directory

{diffDir && (

{diffDir}

)}
{diffCheckResult && (
{diffCheckResult === 'success' ? ( <> Valid diff file found! ) : ( <> Diff file not found. Please select the correct file. )}
)}
{/* Apply Button */}
{isDiffLoading && (

Update Game

{stageType}:
{stageType !== 'Cut Data' && {progressUpdate.toFixed(0)} / {maxProgressUpdate.toFixed(0)}} {stageType === 'Cut Data' && {messageUpdate}}
Please wait...
)} {/* Instructions */}

📋 Instructions:

  1. 1. Click "Select Game Folder" and choose your game's root directory
  2. 2. Wait for the system to validate the game directory
  3. 3. Click "Select Diff file Folder" and choose your diff file's root directory
  4. 4. Wait for the system to validate the diff file directory
  5. 5. Click "Update Game" to save your changes
) }