WIP home page & rework some stuff
This commit is contained in:
6 files changed
+154
-99
No files matched your search
@@ -22,12 +22,14 @@
|
||||
"@tauri-apps/plugin-store": "2.4.4",
|
||||
"@tauri-apps/plugin-updater": "2.10.1",
|
||||
"@tauri-apps/plugin-window-state": "2.4.1",
|
||||
"date-fns": "4.4.0",
|
||||
"dompurify": "3.4.12",
|
||||
"next": "16.2.12",
|
||||
"pretty-bytes": "7.1.1",
|
||||
"react": "19.2.8",
|
||||
"react-dom": "19.2.8",
|
||||
"semver": "7.8.5",
|
||||
"swiper": "14.0.6",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "3.3.6",
|
||||
@@ -425,7 +427,7 @@
|
||||
|
||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.11.6", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-69D/imtToCsIcAl8WBS2YaRwA4jO/j0HhU+hELqMEu9f54MoUtI6+XH5mrKU8rEFNEk/Ui1I2MK4/JkWacclGw=="],
|
||||
|
||||
"brace-expansion": ["brace-expansion@1.1.16", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw=="],
|
||||
"brace-expansion": ["brace-expansion@1.1.17", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-w+aeW/mkgM4PyRMOJCgi3fOrTm5Q8QY1OSfn2TO2iuDj3ezIHqejmuxbjfPrqUkgqRew1iqkyAn0tr0ZwHD9+w=="],
|
||||
|
||||
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
||||
|
||||
@@ -467,6 +469,8 @@
|
||||
|
||||
"data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="],
|
||||
|
||||
"date-fns": ["date-fns@4.4.0", "", {}, "sha512-+1UMbeh68lH1SegH83CGWwpb6OHHbpSgr3+s5Eww5M4CAgswBpoWS0AjTOfEJ33HiYKz1hdj/KTFprzXHmq/6w=="],
|
||||
|
||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||
|
||||
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
||||
@@ -483,7 +487,7 @@
|
||||
|
||||
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.397", "", {}, "sha512-khGTy9U9x02KEtsKM8vx5A62BsRmcOsIgDpWr1ImE32Ax8GxHGPHZf+Eu9H8zOOyHJnB0jTbseyTHbq2XCT8yw=="],
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.398", "", {}, "sha512-AsvhAxopJGh6museTDMIjn6JpDYOfgu4RLlygomt87MUwBUqTfd/1EiPtx10/LZE8xpTvkP2E9Gafq7lkLtodQ=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
||||
|
||||
@@ -803,7 +807,7 @@
|
||||
|
||||
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
|
||||
|
||||
"postcss": ["postcss@8.5.24", "", { "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-8RyVklq0owXUTa4xlpzu4l9AaVKIdQvAcOHZWaMh98HgySsUtxRVf/chRe3dsSLqb6i40BzGRzEUddRaI+9TSw=="],
|
||||
"postcss": ["postcss@8.5.25", "", { "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw=="],
|
||||
|
||||
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
||||
|
||||
@@ -893,6 +897,8 @@
|
||||
|
||||
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
|
||||
|
||||
"swiper": ["swiper@14.0.6", "", {}, "sha512-ArptjmcZMBvpLCbvzSKuqvQpjjITCbZdymiGOrbZQffQ3ZSjgpvMByXX0WZBUt+FV4PPIumdYfZ9ZdBbFsdH6g=="],
|
||||
|
||||
"tailwindcss": ["tailwindcss@4.3.3", "", {}, "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ=="],
|
||||
|
||||
"tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="],
|
||||
|
||||
+3
-1
@@ -28,12 +28,14 @@
|
||||
"@tauri-apps/plugin-store": "2.4.4",
|
||||
"@tauri-apps/plugin-updater": "2.10.1",
|
||||
"@tauri-apps/plugin-window-state": "2.4.1",
|
||||
"date-fns": "4.4.0",
|
||||
"dompurify": "3.4.12",
|
||||
"next": "16.2.12",
|
||||
"pretty-bytes": "7.1.1",
|
||||
"react": "19.2.8",
|
||||
"react-dom": "19.2.8",
|
||||
"semver": "7.8.5"
|
||||
"semver": "7.8.5",
|
||||
"swiper": "14.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "3.3.6",
|
||||
|
||||
+35
-30
@@ -384,6 +384,39 @@ export default function RootLayout ({
|
||||
)
|
||||
}
|
||||
|
||||
const uninstallVersion = async (
|
||||
version: string,
|
||||
updateList: boolean = true
|
||||
) => {
|
||||
if (updateList)
|
||||
await versions?.set(
|
||||
'list',
|
||||
Object.fromEntries(
|
||||
Object.entries(versionsList).filter(([k]) => k !== version)
|
||||
)
|
||||
)
|
||||
|
||||
if (
|
||||
await exists(
|
||||
(customDataLocation ? customDataLocation + '/' : null) +
|
||||
'game/' +
|
||||
version,
|
||||
{
|
||||
baseDir: customDataLocation ? undefined : BaseDirectory.AppLocalData
|
||||
}
|
||||
)
|
||||
)
|
||||
await remove(
|
||||
(customDataLocation ? customDataLocation + '/' : null) +
|
||||
'game/' +
|
||||
version,
|
||||
{
|
||||
baseDir: customDataLocation ? undefined : BaseDirectory.AppLocalData,
|
||||
recursive: true
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const launchGame = async (versionInfo: GameVersion) => {
|
||||
if (needsRevisionUpdate(versionInfo.lastRevision, versionInfo.id)) {
|
||||
const answer = await ask(
|
||||
@@ -409,36 +442,7 @@ export default function RootLayout ({
|
||||
setFadeOut(false)
|
||||
|
||||
//uninstall
|
||||
await versions?.set(
|
||||
'list',
|
||||
Object.fromEntries(
|
||||
Object.entries(versionsList).filter(([k]) => k !== versionInfo.id)
|
||||
)
|
||||
)
|
||||
|
||||
if (
|
||||
await exists(
|
||||
customDataLocation
|
||||
? customDataLocation + '/'
|
||||
: null + 'game/' + versionInfo.id,
|
||||
{
|
||||
baseDir: customDataLocation
|
||||
? undefined
|
||||
: BaseDirectory.AppLocalData
|
||||
}
|
||||
)
|
||||
)
|
||||
await remove(
|
||||
customDataLocation
|
||||
? customDataLocation + '/'
|
||||
: null + 'game/' + versionInfo.id,
|
||||
{
|
||||
baseDir: customDataLocation
|
||||
? undefined
|
||||
: BaseDirectory.AppLocalData,
|
||||
recursive: true
|
||||
}
|
||||
)
|
||||
await uninstallVersion(versionInfo.id)
|
||||
|
||||
//reinstall
|
||||
setSelectedVersionList([versionInfo.id])
|
||||
@@ -912,6 +916,7 @@ export default function RootLayout ({
|
||||
managingGame,
|
||||
setManagingGame,
|
||||
needsRevisionUpdate,
|
||||
uninstallVersion,
|
||||
launchGame
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
'use client'
|
||||
|
||||
import { useGlobal } from '@/providers/GlobalProvider'
|
||||
import 'swiper/css'
|
||||
import { Swiper, SwiperSlide } from 'swiper/react'
|
||||
import { formatDistanceToNow } from 'date-fns'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faEllipsis, faPlay } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
export default function HomePage () {
|
||||
const {
|
||||
launchesList,
|
||||
serverVersionList,
|
||||
accountName,
|
||||
launchGame,
|
||||
setManagingVersion,
|
||||
setPopupMode,
|
||||
setShowPopup,
|
||||
setFadeOut
|
||||
} = useGlobal()
|
||||
|
||||
const filteredLaunchesList = Object.fromEntries(
|
||||
Object.entries(launchesList)
|
||||
.flatMap(([gameId, launches]) => {
|
||||
const entries = Object.entries(launches)
|
||||
|
||||
if (entries.length === 0) return []
|
||||
|
||||
const [version, timestamp] = entries.reduce((latest, current) =>
|
||||
current[1] > latest[1] ? current : latest
|
||||
)
|
||||
|
||||
return [[`${gameId}-${version}`, timestamp] as const]
|
||||
})
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
)
|
||||
|
||||
return (
|
||||
<div className='mx-4 mt-4'>
|
||||
<div className='flex flex-col gap-1 mb-4'>
|
||||
<p className='text-3xl'>Home</p>
|
||||
<p className='text-gray-300'>Welcome back, {accountName ?? 'User'}!</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className='text-2xl'>Jump back in</p>
|
||||
{Object.entries(filteredLaunchesList).length == 0 ? (
|
||||
<p className='text-gray-300'>You have no recently launched games</p>
|
||||
) : (
|
||||
<Swiper spaceBetween={16} slidesPerView={2}>
|
||||
{Object.entries(filteredLaunchesList).map(([key, timestamp]) => {
|
||||
const versionInfo = serverVersionList?.versions.find(
|
||||
v => v.id == key.split('-').slice(1).join('-')
|
||||
)
|
||||
if (!versionInfo) return
|
||||
|
||||
return (
|
||||
<SwiperSlide
|
||||
key={key}
|
||||
className='flex flex-col gap-2 bg-(--col1) border border-(--col3) rounded-lg px-3 py-2'
|
||||
>
|
||||
<p className='truncate text-2xl'>
|
||||
{versionInfo?.displayName}
|
||||
</p>
|
||||
<p className='truncate text-gray-300'>
|
||||
Last played:{' '}
|
||||
{formatDistanceToNow(new Date(timestamp), {
|
||||
addSuffix: true
|
||||
})}
|
||||
</p>
|
||||
<div className='flex flex-row gap-2 my-1'>
|
||||
<FontAwesomeIcon
|
||||
icon={faPlay}
|
||||
className='button btntheme1'
|
||||
onClick={async () => await launchGame(versionInfo)}
|
||||
/>
|
||||
<FontAwesomeIcon
|
||||
icon={faEllipsis}
|
||||
className='button btntheme1'
|
||||
onClick={() => {
|
||||
setManagingVersion(versionInfo.id)
|
||||
setPopupMode(2)
|
||||
setShowPopup(true)
|
||||
setFadeOut(false)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</SwiperSlide>
|
||||
)
|
||||
})}
|
||||
</Swiper>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import { useGlobal } from '@/providers/GlobalProvider'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { useEffect, useState } from 'react'
|
||||
import prettyBytes from 'pretty-bytes'
|
||||
import { BaseDirectory, exists, remove } from '@tauri-apps/plugin-fs'
|
||||
import { openFolder } from '@/lib/util'
|
||||
|
||||
export default function ManageVersionPopup () {
|
||||
@@ -23,8 +22,9 @@ export default function ManageVersionPopup () {
|
||||
setPopupMode,
|
||||
setSelectedVersionList,
|
||||
downloadVersions,
|
||||
uninstallVersion,
|
||||
versions,
|
||||
customDataLocation
|
||||
launchesList
|
||||
} = useGlobal()
|
||||
const [versionSize, setVersionSize] = useState<number>(0)
|
||||
|
||||
@@ -114,39 +114,16 @@ export default function ManageVersionPopup () {
|
||||
className='entry-info-item btntheme2'
|
||||
onClick={async () => {
|
||||
closePopup()
|
||||
uninstallVersion(managingVersion)
|
||||
if (!versionInfo) return
|
||||
|
||||
await versions?.set(
|
||||
'list',
|
||||
Object.fromEntries(
|
||||
Object.entries(versionsList).filter(
|
||||
([k]) => k !== managingVersion
|
||||
)
|
||||
)
|
||||
)
|
||||
const gameLaunches = { ...launchesList[versionInfo.game] }
|
||||
delete gameLaunches[versionInfo.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
|
||||
}
|
||||
)
|
||||
await versions?.set('launches', {
|
||||
...launchesList,
|
||||
[versionInfo.game]: gameLaunches
|
||||
})
|
||||
}}
|
||||
title='Click to uninstall this game. This will NOT remove any progress or any save files.'
|
||||
>
|
||||
@@ -160,38 +137,7 @@ export default function ManageVersionPopup () {
|
||||
setPopupMode(1)
|
||||
|
||||
//uninstall
|
||||
await versions?.set(
|
||||
'list',
|
||||
Object.fromEntries(
|
||||
Object.entries(versionsList).filter(
|
||||
([k]) => k !== managingVersion
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
)
|
||||
uninstallVersion(managingVersion)
|
||||
|
||||
//reinstall
|
||||
setSelectedVersionList([managingVersion])
|
||||
|
||||
@@ -73,6 +73,7 @@ type GlobalCtxType = {
|
||||
lastRevision: number | undefined,
|
||||
version: string
|
||||
) => boolean
|
||||
uninstallVersion: (version: string, updateList?: boolean) => Promise<void>
|
||||
launchGame: (versionInfo: GameVersion) => Promise<void>
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user