From 5226ce4a6257fd66b78823d889fdfc00cd2b8dfd Mon Sep 17 00:00:00 2001 From: Lncvrt Date: Thu, 30 Apr 2026 20:39:16 -0700 Subject: [PATCH] Add manage game popup --- src/app/main/layout.tsx | 8 +- src/app/main/page.tsx | 10 ++- src/popups/ManageGame.tsx | 150 +++++++++++++++++++++++++++++++ src/providers/GlobalProvider.tsx | 2 + 4 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 src/popups/ManageGame.tsx diff --git a/src/app/main/layout.tsx b/src/app/main/layout.tsx index fadb024..b35d7d6 100644 --- a/src/app/main/layout.tsx +++ b/src/app/main/layout.tsx @@ -41,6 +41,7 @@ import DownloadsPopup from '@/popups/Downloads' import ManageVersionPopup from '@/popups/ManageVersion' import ModDownloadsPopup from '@/popups/ModDownloads' import VersionChangelogPopup from '@/popups/VersionChangelog' +import ManageGamePopup from '@/popups/ManageGame' const roboto = Roboto({ subsets: ['latin'] @@ -70,6 +71,7 @@ export default function RootLayout ({ const [downloadQueue, setDownloadQueue] = useState([]) const [isProcessingQueue, setIsProcessingQueue] = useState(false) const [managingVersion, setManagingVersion] = useState(null) + const [managingGame, setManagingGame] = useState(null) const [viewingInfoFromDownloads, setViewingInfoFromDownloads] = useState(false) const [selectedGame, setSelectedGame] = useState(null) @@ -791,7 +793,9 @@ export default function RootLayout ({ versionsList, modsList, movingData, - setMovingData + setMovingData, + managingGame, + setManagingGame }} >
) : popupMode === 4 ? ( + ) : popupMode === 5 ? ( + ) : null}
diff --git a/src/app/main/page.tsx b/src/app/main/page.tsx index 548d1bb..56dcd61 100644 --- a/src/app/main/page.tsx +++ b/src/app/main/page.tsx @@ -22,7 +22,8 @@ export default function Installs () { setFadeOut, setSelectedVersionList, setSelectedGame, - setCategory + setCategory, + setManagingGame } = useGlobal() const router = useRouter() @@ -78,6 +79,13 @@ export default function Installs () { setCategory(-1) router.push('/main/game?id=' + i.id) }} + onContextMenu={e => { + e.preventDefault() + setManagingGame(i.id) + setPopupMode(5) + setShowPopup(true) + setFadeOut(false) + }} >

{i.name}

diff --git a/src/popups/ManageGame.tsx b/src/popups/ManageGame.tsx new file mode 100644 index 0000000..98d4251 --- /dev/null +++ b/src/popups/ManageGame.tsx @@ -0,0 +1,150 @@ +'use client' + +import { + faCheck, + faCode, + faHardDrive, + faShieldHalved, + faWarning +} from '@fortawesome/free-solid-svg-icons' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { useGlobal } from '@/providers/GlobalProvider' +import { invoke } from '@tauri-apps/api/core' +import { useEffect, useMemo, useState } from 'react' +import prettyBytes from 'pretty-bytes' +import { BaseDirectory, exists, remove } from '@tauri-apps/plugin-fs' + +export default function ManageGamePopup () { + const { + versionsList, + serverVersionList, + viewingInfoFromDownloads, + closePopup, + versions, + customDataLocation, + managingGame + } = useGlobal() + const [gameSize, setGameSize] = useState(0) + + const versionsInstalled = useMemo(() => { + return serverVersionList?.versions.filter( + vf => vf.game == managingGame && Object.keys(versionsList).includes(vf.id) + ) + }, [serverVersionList, managingGame, versionsList]) + const gameInfo = serverVersionList?.games.find(vf => vf.id == managingGame) + + useEffect(() => { + if (viewingInfoFromDownloads || !versionsInstalled) return + + let cancelled = false + + const run = async () => { + let total = 0 + setGameSize(0) + + for (const version of versionsInstalled) { + if (cancelled) return + + const size = await invoke('folder_size', { + version: version.id + }).catch(() => '0') + + total += Number(size) + setGameSize(total) + } + } + + run() + + return () => { + cancelled = true + } + }, [versionsInstalled, viewingInfoFromDownloads]) + + return ( + <> +

Viewing {gameInfo?.name}

+
+ + + + +
{ + closePopup() + if (!versionsInstalled) return + + const updatedList = { ...versionsList } + + for (const version of versionsInstalled) + delete updatedList[version.id] + + await versions?.set('list', updatedList) + + for (const version of versionsInstalled) { + const managingVersion = version.id + + if ( + await exists( + (customDataLocation ? customDataLocation + '/' : null) + + 'game/' + + managingVersion, + { + baseDir: customDataLocation + ? undefined + : BaseDirectory.AppLocalData + } + ) + ) + await remove( + (customDataLocation ? customDataLocation + '/' : null) + + 'game/' + + managingVersion, + { + baseDir: customDataLocation + ? undefined + : BaseDirectory.AppLocalData, + recursive: true + } + ) + } + }} + title='Click to uninstall this game. This will NOT remove any progress or any save files.' + hidden={viewingInfoFromDownloads} + > + Uninstall +
+
+ + ) +} diff --git a/src/providers/GlobalProvider.tsx b/src/providers/GlobalProvider.tsx index 5818e1b..e845002 100644 --- a/src/providers/GlobalProvider.tsx +++ b/src/providers/GlobalProvider.tsx @@ -62,6 +62,8 @@ type GlobalCtxType = { modsList: Record> movingData: boolean setMovingData: Dispatch> + managingGame: number | null + setManagingGame: Dispatch> } const GlobalCtx = createContext(null)