Move away from using hidden

This commit is contained in:
Lncvrt committed 2026-05-07 17:12:36 -07:00
1 parent 635cbfc14c
commit b2fefd2c6b
9 files changed
+502 -481

No files matched your search

+107 -106
View File
@@ -71,52 +71,55 @@ export default function Installs () {
{game.name} Installs {game.name} Installs
</p> </p>
<div className='flex gap-2'> <div className='flex gap-2'>
<button {game.id == 1 && (
className='button btntheme1' <button
onClick={() => className='button btntheme1'
new WebviewWindow('berrydashleaderboards', { onClick={() =>
title: 'Berry Dash Leaderboards', new WebviewWindow('berrydashleaderboards', {
url: title: 'Berry Dash Leaderboards',
'https://games.lncvrt.xyz/game/berry-dash/leaderboards?launcher=1&theme=' + url:
theme, 'https://games.lncvrt.xyz/game/berry-dash/leaderboards?launcher=1&theme=' +
width: 800, theme,
height: 600, width: 800,
resizable: false, height: 600,
maximizable: false resizable: false,
}) maximizable: false
} })
title='View the leaderboards for this game.' }
hidden={game.id != 1} title='View the leaderboards for this game.'
> >
Leaderboards Leaderboards
</button> </button>
<button )}
className='button btntheme1' {game.id == 9 && category == -1 && (
onClick={() => <button
new WebviewWindow('xpsdashboard', { className='button btntheme1'
title: 'XPS Dashboard', onClick={() =>
url: 'https://xps.lncvrt.xyz/dashboard/', new WebviewWindow('xpsdashboard', {
width: 1280, title: 'XPS Dashboard',
height: 720, url: 'https://xps.lncvrt.xyz/dashboard/',
minWidth: 1280, width: 1280,
minHeight: 720 height: 720,
}) minWidth: 1280,
} minHeight: 720
title='Open the GDPS Dashboard!' })
hidden={game.id != 9 || category != -1} }
> title='Open the GDPS Dashboard!'
Dashboard >
</button> Dashboard
<button </button>
className='button btntheme1' )}
onClick={() => { {category != -1 && (
setCategory(-1) <button
}} className='button btntheme1'
title='Click to go up a level.' onClick={() => {
hidden={category == -1} setCategory(-1)
> }}
Back title='Click to go up a level.'
</button> >
Back
</button>
)}
<button <button
className='button btntheme1' className='button btntheme1'
onClick={() => { onClick={() => {
@@ -267,72 +270,70 @@ export default function Installs () {
)} )}
</p> </p>
</div> </div>
<div {platform() == 'linux' &&
className='entry-info-item' versionInfo.wine &&
title='This version is using wine. It cannot be guarenteed to work fully and might not work at all.' needsRevisionUpdate(versionInfo.lastRevision, v) && (
hidden={ <div
!(platform() == 'linux' && versionInfo.wine) || className='entry-info-item'
needsRevisionUpdate(versionInfo.lastRevision, v) title='This version is using wine. It cannot be guarenteed to work fully and might not work at all.'
} >
> <FontAwesomeIcon icon={faWarning} color='#ffc800' />
<FontAwesomeIcon icon={faWarning} color='#ffc800' /> <p>Uses wine</p>
<p>Uses wine</p> </div>
</div> )}
<div {needsRevisionUpdate(versionInfo.lastRevision, v) && (
className='entry-info-item' <div className='entry-info-item'>
hidden={ <FontAwesomeIcon icon={faWarning} color='#ffc800' />
!needsRevisionUpdate(versionInfo.lastRevision, v) <p>Needs revision update!</p>
} </div>
> )}
<FontAwesomeIcon icon={faWarning} color='#ffc800' />
<p>Needs revision update!</p>
</div>
</div> </div>
<button {versionInfo.modSupportDownload && (
className='absolute right-0 bottom-0 button' <button
title='Click to manage mods for this game!' className='absolute right-0 bottom-0 button'
onClick={async e => { title='Click to manage mods for this game!'
e.stopPropagation() onClick={async e => {
e.stopPropagation()
if (
!(await exists(
customDataLocation
? customDataLocation + '/'
: null + 'game/' + v + '/BepInEx',
{
baseDir: customDataLocation
? undefined
: BaseDirectory.AppLocalData
}
))
) {
if ( if (
(await ask( !(await exists(
"You don't have BepInEx (the mod loader for Unity Games), would you like to install it now? It is about 1MB in size. If you choose yes, it will download the recommended BepInEx version for " + customDataLocation
versionInfo.displayName + ? customDataLocation + '/'
'.', : null + 'game/' + v + '/BepInEx',
{ title: 'BepInEx not found!', kind: 'error' }
)) &&
!downloadProgress.find(d => d.version == v)
) {
downloadVersions([
{ {
id: v, baseDir: customDataLocation
type: 1 ? undefined
: BaseDirectory.AppLocalData
} }
]) ))
) {
if (
(await ask(
"You don't have BepInEx (the mod loader for Unity Games), would you like to install it now? It is about 1MB in size. If you choose yes, it will download the recommended BepInEx version for " +
versionInfo.displayName +
'.',
{ title: 'BepInEx not found!', kind: 'error' }
)) &&
!downloadProgress.find(d => d.version == v)
) {
downloadVersions([
{
id: v,
type: 1
}
])
}
return
} }
return setManagingVersion(v)
} setPopupMode(3)
setManagingVersion(v) setShowPopup(true)
setPopupMode(3) setFadeOut(false)
setShowPopup(true) }}
setFadeOut(false) >
}} Mod Manager
hidden={!versionInfo.modSupportDownload} </button>
> )}
Mod Manager
</button>
</div> </div>
</div> </div>
) )
+6 -8
View File
@@ -822,10 +822,9 @@ export default function RootLayout ({
<body className={theme + '-theme'}> <body className={theme + '-theme'}>
{loading ? ( {loading ? (
<> <>
<div {platformName == 'windows' && (
className='relative z-2 w-screen border-b border-b-(--col3) h-8.25 bg-(--col1)' <div className='relative z-2 w-screen border-b border-b-(--col3) h-8.25 bg-(--col1)' />
hidden={platformName != 'windows'} )}
/>
<div <div
className={`w-screen ${ className={`w-screen ${
platformName == 'windows' platformName == 'windows'
@@ -892,10 +891,9 @@ export default function RootLayout ({
}} }}
> >
<Sidebar /> <Sidebar />
<div {platformName == 'windows' && (
className='relative z-2 ml-59.75 w-[calc(100vw-239px)] border-b border-b-(--col3) h-8.25 bg-(--col1)' <div className='relative z-2 ml-59.75 w-[calc(100vw-239px)] border-b border-b-(--col3) h-8.25 bg-(--col1)' />
hidden={platformName != 'windows'} )}
/>
<div className='relative z-0'> <div className='relative z-0'>
<main className='ml-60'>{children}</main> <main className='ml-60'>{children}</main>
</div> </div>
+24 -23
View File
@@ -114,29 +114,30 @@ export default function Installs () {
versions installed versions installed
</p> </p>
</div> </div>
<div {i.official ? (
className='entry-info-item' <div
hidden={!i.official} className='entry-info-item'
title='This game is official.' title='This game is official.'
> >
<FontAwesomeIcon icon={faCheck} color='#19c84b' /> <FontAwesomeIcon icon={faCheck} color='#19c84b' />
<p>Official</p> <p>Official</p>
</div> </div>
<div ) : (
className='entry-info-item' <div
hidden={i.official} className='entry-info-item'
title={ title={
i.verified i.verified
? 'This game is verified to be safe' ? 'This game is verified to be safe'
: 'This game is not verified to be save. Proceed with caution.' : 'This game is not verified to be save. Proceed with caution.'
} }
> >
<FontAwesomeIcon <FontAwesomeIcon
icon={i.verified ? faShieldHalved : faWarning} icon={i.verified ? faShieldHalved : faWarning}
color={i.verified ? '#19c84b' : '#ffc800'} color={i.verified ? '#19c84b' : '#ffc800'}
/> />
<p>{i.verified ? 'Verified' : 'Unverified'}</p> <p>{i.verified ? 'Verified' : 'Unverified'}</p>
</div> </div>
)}
</div> </div>
</div> </div>
</div> </div>
+13 -10
View File
@@ -54,16 +54,19 @@ export default function Settings () {
}} }}
className={platform() == 'linux' ? '' : 'hidden'} className={platform() == 'linux' ? '' : 'hidden'}
/> />
<p hidden={!(platform() == 'linux' && linuxUseWine)}>Wine Command:</p> {platform() == 'linux' && linuxUseWine && (
<input <>
type='text' <p>Wine Command:</p>
value={linuxWineCommand} <input
onChange={async e => type='text'
await settings?.set('linuxWineCommand', e.target.value) value={linuxWineCommand}
} onChange={async e =>
className='input-field my-1' await settings?.set('linuxWineCommand', e.target.value)
hidden={!(platform() == 'linux' && linuxUseWine)} }
></input> className='input-field my-1'
></input>
</>
)}
<Setting <Setting
label='Use custom data location' label='Use custom data location'
value={!!customDataLocation} value={!!customDataLocation}
+3 -4
View File
@@ -24,10 +24,9 @@ export default function RootLayout ({
<> <>
<html lang='en' className={roboto.className}> <html lang='en' className={roboto.className}>
<body className='dark-theme'> <body className='dark-theme'>
<div {platformName == 'windows' && (
className='relative z-2 w-screen border-b border-b-(--col3) h-8.25 bg-(--col1)' <div className='relative z-2 w-screen border-b border-b-(--col3) h-8.25 bg-(--col1)' />
hidden={platformName != 'windows'} )}
/>
<div <div
className={`w-screen ${ className={`w-screen ${
platformName == 'windows' ? 'h-[calc(100vh-64px)]' : 'h-screen' platformName == 'windows' ? 'h-[calc(100vh-64px)]' : 'h-screen'
+27 -25
View File
@@ -51,19 +51,20 @@ export default function Sidebar () {
return ( return (
<aside className='sidebar'> <aside className='sidebar'>
<div {platform() == 'macos' && (
className='macos-drag' <div
hidden={platform() != 'macos'} className='macos-drag'
onMouseDown={e => { onMouseDown={e => {
if (e.buttons === 1) { if (e.buttons === 1) {
if (e.detail === 2) { if (e.detail === 2) {
getCurrentWindow().toggleMaximize() getCurrentWindow().toggleMaximize()
} else { } else {
getCurrentWindow().startDragging() getCurrentWindow().startDragging()
}
} }
} }}
}} />
></div> )}
<div <div
className={ className={
'flex items-center h-10 w-60 ' + 'flex items-center h-10 w-60 ' +
@@ -228,19 +229,20 @@ export default function Sidebar () {
<FontAwesomeIcon icon={faDiscord} className='mr-1' /> Community <FontAwesomeIcon icon={faDiscord} className='mr-1' /> Community
</button> </button>
</nav> </nav>
<div {downloadProgress.length != 0 && (
className='sidebar-downloads' <div
hidden={downloadProgress.length == 0} className='sidebar-downloads'
onClick={() => { onClick={() => {
setPopupMode(1) setPopupMode(1)
setShowPopup(true) setShowPopup(true)
setFadeOut(false) setFadeOut(false)
}} }}
> >
<p> <p>
<FontAwesomeIcon icon={faDownload} /> Downloads <FontAwesomeIcon icon={faDownload} /> Downloads
</p> </p>
</div> </div>
)}
</aside> </aside>
) )
} }
+140 -129
View File
@@ -38,142 +38,153 @@ export default function DownloadsPopup () {
className='popup-entry flex flex-col justify-between relative' className='popup-entry flex flex-col justify-between relative'
> >
<div className='absolute right-2 top-2 flex flex-row gap-2'> <div className='absolute right-2 top-2 flex flex-row gap-2'>
<div {(v.downloading || v.paused) && (
className='cursor-pointer bg-(--col5) hover:bg-(--col7) border border-(--col7) hover:border-(--col9) transition-colors w-8 h-8 flex items-center justify-center rounded-full' <>
hidden={!v.downloading && !v.paused} <div
onClick={async () => { className='cursor-pointer bg-(--col5) hover:bg-(--col7) border border-(--col7) hover:border-(--col9) transition-colors w-8 h-8 flex items-center justify-center rounded-full'
if (v.downloading) { onClick={async () => {
await invoke('cancel_download', { name: v.version }) if (v.downloading) {
} else { await invoke('cancel_download', { name: v.version })
setDownloadProgress(prev => { } else {
const i = prev.findIndex(d => d.version === v.version) setDownloadProgress(prev => {
if (i === -1) return prev const i = prev.findIndex(
const copy = [...prev] d => d.version === v.version
copy[i] = { )
...copy[i], if (i === -1) return prev
paused: false, const copy = [...prev]
downloading: true copy[i] = {
} ...copy[i],
return copy paused: false,
}) downloading: true
const res = await invoke<string>('download', { }
url: v.url, return copy
name: v.version, })
hash: v.hash, const res = await invoke<string>('download', {
downloadType: v.type, url: v.url,
modId: String(v.modId ?? '') name: v.version,
}) hash: v.hash,
downloadType: v.type,
modId: String(v.modId ?? '')
})
if (res === '1') { if (res === '1') {
setDownloadProgress(prev => setDownloadProgress(prev =>
prev.filter(d => d.version !== v.version) prev.filter(d => d.version !== v.version)
) )
if (v.type != 1) { if (v.type != 1) {
if (v.type == 2) { if (v.type == 2) {
await versions?.set('mods', { await versions?.set('mods', {
...modsList, ...modsList,
[v.modGame! + '-' + v.modId!]: { [v.modGame! + '-' + v.modId!]: {
[v.modVersion!]: Date.now() [v.modVersion!]: Date.now()
}
})
} else {
await versions?.set('list', {
...versionsList,
[v.version]: Date.now()
})
} }
}
} else if (res == '0') {
setDownloadProgress(prev => {
const i = prev.findIndex(
d => d.version === v.version
)
if (i === -1) return prev
if (prev[i].canceled) {
return prev.filter((_, idx) => idx !== i)
}
const copy = [...prev]
copy[i] = {
...copy[i],
downloading: false,
paused: true,
failed: false
}
return copy
}) })
} else { } else if (res == '-1') {
await versions?.set('list', { setDownloadProgress(prev =>
...versionsList, prev.map(d =>
[v.version]: Date.now() d.version === v.version
}) ? {
...d,
queued: false,
failed: true,
progress: 0
}
: d
)
)
if (notificationsAllowed)
await notifyUser(
'Download Failed',
`The download for version ${
serverVersionList?.versions.find(
vf => vf.id == v.version
)?.displayName
} has failed.`
)
await getCurrentWindow().requestUserAttention(
UserAttentionType.Critical
)
} }
} }
} else if (res == '0') { }}
setDownloadProgress(prev => { >
const i = prev.findIndex(d => d.version === v.version) <FontAwesomeIcon
if (i === -1) return prev icon={v.downloading ? faPause : faPlay}
if (prev[i].canceled) { className='w-6 h-6'
/>
</div>
<div
className='cursor-pointer bg-(--col5) hover:bg-(--col7) border border-(--col7) hover:border-(--col9) transition-colors w-8 h-8 flex items-center justify-center rounded-full'
onClick={async () => {
if (!v.paused) {
await invoke('cancel_download', { name: v.version })
setDownloadProgress(prev => {
const i = prev.findIndex(
d => d.version === v.version
)
if (i === -1) return prev
const copy = [...prev]
copy[i] = {
...copy[i],
canceled: true
}
return copy
})
} else {
setDownloadProgress(prev => {
const i = prev.findIndex(
d => d.version === v.version
)
if (i === -1) return prev
return prev.filter((_, idx) => idx !== i) return prev.filter((_, idx) => idx !== i)
} })
const copy = [...prev]
copy[i] = {
...copy[i],
downloading: false,
paused: true,
failed: false
}
return copy
})
} else if (res == '-1') {
setDownloadProgress(prev =>
prev.map(d =>
d.version === v.version
? {
...d,
queued: false,
failed: true,
progress: 0
}
: d
)
)
if (notificationsAllowed)
await notifyUser(
'Download Failed',
`The download for version ${
serverVersionList?.versions.find(
vf => vf.id == v.version
)?.displayName
} has failed.`
)
await getCurrentWindow().requestUserAttention(
UserAttentionType.Critical
)
}
}
}}
>
<FontAwesomeIcon
icon={v.downloading ? faPause : faPlay}
className='w-6 h-6'
/>
</div>
<div
className='cursor-pointer bg-(--col5) hover:bg-(--col7) border border-(--col7) hover:border-(--col9) transition-colors w-8 h-8 flex items-center justify-center rounded-full'
hidden={!v.downloading && !v.paused}
onClick={async () => {
if (!v.paused) {
await invoke('cancel_download', { name: v.version })
setDownloadProgress(prev => {
const i = prev.findIndex(d => d.version === v.version)
if (i === -1) return prev
const copy = [...prev]
copy[i] = {
...copy[i],
canceled: true
} }
return copy }}
}) >
} else { <FontAwesomeIcon icon={faCancel} className='w-6 h-6' />
setDownloadProgress(prev => { </div>
const i = prev.findIndex(d => d.version === v.version) </>
if (i === -1) return prev )}
return prev.filter((_, idx) => idx !== i) {(v.failed || v.queued) && (
}) <div
} className='cursor-pointer bg-(--col5) hover:bg-(--col7) border border-(--col7) hover:border-(--col9) transition-colors w-8 h-8 flex items-center justify-center rounded-full'
}} onClick={() => {
> setDownloadQueue(prev =>
<FontAwesomeIcon icon={faCancel} className='w-6 h-6' /> prev.filter(id => id !== v.version)
</div> )
<div setDownloadProgress(prev =>
className='cursor-pointer bg-(--col5) hover:bg-(--col7) border border-(--col7) hover:border-(--col9) transition-colors w-8 h-8 flex items-center justify-center rounded-full' prev.filter(d => d.version !== v.version)
hidden={!v.failed && !v.queued} )
onClick={() => { }}
setDownloadQueue(prev => >
prev.filter(id => id !== v.version) <FontAwesomeIcon icon={faTrash} className='w-6 h-6' />
) </div>
setDownloadProgress(prev => )}
prev.filter(d => d.version !== v.version)
)
}}
>
<FontAwesomeIcon icon={faTrash} className='w-6 h-6' />
</div>
</div> </div>
<p className='text-2xl text-center'> <p className='text-2xl text-center'>
{v.type == 1 {v.type == 1
+75 -73
View File
@@ -65,25 +65,27 @@ export default function ManageGamePopup () {
<> <>
<p className='text-xl text-center'>Viewing {gameInfo?.name}</p> <p className='text-xl text-center'>Viewing {gameInfo?.name}</p>
<div className='popup-content flex flex-col items-center justify-center gap-2 h-full'> <div className='popup-content flex flex-col items-center justify-center gap-2 h-full'>
<div className='entry-info-item btntheme2' hidden={!gameInfo?.official}> {gameInfo?.official ? (
<FontAwesomeIcon icon={faCheck} color='#19c84b' /> <div className='entry-info-item btntheme2'>
<p>Official</p> <FontAwesomeIcon icon={faCheck} color='#19c84b' />
</div> <p>Official</p>
<div className='entry-info-item btntheme2' hidden={gameInfo?.official}> </div>
<FontAwesomeIcon ) : (
icon={gameInfo?.verified ? faShieldHalved : faWarning} <div className='entry-info-item btntheme2'>
color={gameInfo?.verified ? '#19c84b' : '#ffc800'} <FontAwesomeIcon
/> icon={gameInfo?.verified ? faShieldHalved : faWarning}
<p>{gameInfo?.verified ? 'Verified' : 'Unverified'}</p> color={gameInfo?.verified ? '#19c84b' : '#ffc800'}
</div> />
<div <p>{gameInfo?.verified ? 'Verified' : 'Unverified'}</p>
className='entry-info-item btntheme2' </div>
hidden={gameInfo?.developer == null} )}
> {gameInfo?.developer != null && (
<FontAwesomeIcon icon={faCode} color='lightgray' /> <div className='entry-info-item btntheme2'>
<p>Developer: {gameInfo?.developer}</p> <FontAwesomeIcon icon={faCode} color='lightgray' />
</div> <p>Developer: {gameInfo?.developer}</p>
<div className='entry-info-item btntheme2' hidden={!gameInfo?.official}> </div>
)}
<div className='entry-info-item btntheme2'>
<FontAwesomeIcon icon={faDownload} color='lightgray' /> <FontAwesomeIcon icon={faDownload} color='lightgray' />
<p> <p>
{(() => { {(() => {
@@ -102,65 +104,65 @@ export default function ManageGamePopup () {
versions installed versions installed
</p> </p>
</div> </div>
<div {versionsInstalled?.length != 0 && (
className='entry-info-item btntheme2' <>
hidden={versionsInstalled?.length == 0} <div className='entry-info-item btntheme2'>
> <FontAwesomeIcon icon={faHardDrive} color='lightgray' />
<FontAwesomeIcon icon={faHardDrive} color='lightgray' /> <p>
<p> Size on disk:{' '}
Size on disk:{' '} {prettyBytes(gameSize, {
{prettyBytes(gameSize, { minimumFractionDigits: 2,
minimumFractionDigits: 2, maximumFractionDigits: 2
maximumFractionDigits: 2 })}
})} </p>
</p> </div>
</div> <div
<div className='entry-info-item btntheme2'
className='entry-info-item btntheme2' onClick={async () => {
onClick={async () => { closePopup()
closePopup() if (!versionsInstalled) return
if (!versionsInstalled) return
const updatedList = { ...versionsList } const updatedList = { ...versionsList }
for (const version of versionsInstalled) for (const version of versionsInstalled)
delete updatedList[version.id] delete updatedList[version.id]
await versions?.set('list', updatedList) await versions?.set('list', updatedList)
for (const version of versionsInstalled) { for (const version of versionsInstalled) {
const managingVersion = version.id const managingVersion = version.id
if ( if (
await exists( await exists(
(customDataLocation ? customDataLocation + '/' : null) + (customDataLocation ? customDataLocation + '/' : null) +
'game/' + 'game/' +
managingVersion, managingVersion,
{ {
baseDir: customDataLocation baseDir: customDataLocation
? undefined ? undefined
: BaseDirectory.AppLocalData : BaseDirectory.AppLocalData
} }
) )
) )
await remove( await remove(
(customDataLocation ? customDataLocation + '/' : null) + (customDataLocation ? customDataLocation + '/' : null) +
'game/' + 'game/' +
managingVersion, managingVersion,
{ {
baseDir: customDataLocation baseDir: customDataLocation
? undefined ? undefined
: BaseDirectory.AppLocalData, : BaseDirectory.AppLocalData,
recursive: true recursive: true
} }
) )
} }
}} }}
title='Click to uninstall this game. This will NOT remove any progress or any save files.' title='Click to uninstall this game. This will NOT remove any progress or any save files.'
hidden={versionsInstalled?.length == 0} >
> Uninstall
Uninstall </div>
</div> </>
)}
</div> </div>
</> </>
) )
+107 -103
View File
@@ -68,33 +68,34 @@ export default function ModDownloadsPopup () {
return ( return (
<> <>
<button {typeof mods != 'number' && showModInfo == null && (
className='popup-top-button btntheme1 right-2' <button
onClick={async () => { className='popup-top-button btntheme1 right-2'
setMods(0) onClick={async () => {
const response = await fetch( setMods(0)
'https://games.lncvrt.xyz/api/launcher/mods?version=' + const response = await fetch(
managingVersion, 'https://games.lncvrt.xyz/api/launcher/mods?version=' +
{ managingVersion,
headers: { {
Requester: 'LncvrtGamesLauncherClient', headers: {
ClientVersion: await app.getVersion(), Requester: 'LncvrtGamesLauncherClient',
ClientPlatform: platform() + '-' + arch() ClientVersion: await app.getVersion(),
ClientPlatform: platform() + '-' + arch()
}
} }
)
const signature = response.headers.get('x-signature') ?? ''
const data = await response.json()
if (await verifySignature(JSON.stringify(data), signature)) {
setMods(data as Mod[])
} else {
setMods(1)
} }
) }}
const signature = response.headers.get('x-signature') ?? '' >
const data = await response.json() <FontAwesomeIcon icon={faRefresh} />
if (await verifySignature(JSON.stringify(data), signature)) { </button>
setMods(data as Mod[]) )}
} else {
setMods(1)
}
}}
hidden={typeof mods == 'number' || showModInfo != null}
>
<FontAwesomeIcon icon={faRefresh} />
</button>
<p className='text-xl text-center'> <p className='text-xl text-center'>
{!showModInfo {!showModInfo
? versionInfo?.displayName + ' Mod Manager' ? versionInfo?.displayName + ' Mod Manager'
@@ -180,13 +181,12 @@ export default function ModDownloadsPopup () {
> >
v{tab == 0 ? localVersion : v.latestVersion} v{tab == 0 ? localVersion : v.latestVersion}
</span> </span>
<span {tab == 0 && v.latestVersion != localVersion && (
className='text-green-300' <span className='text-green-300'>
hidden={tab != 0 || v.latestVersion == localVersion} {' '}
> (available: v{v.latestVersion})
{' '} </span>
(available: v{v.latestVersion}) )}
</span>
</p> </p>
<p className='text-yellow-200'> <p className='text-yellow-200'>
Made by {v.creators[0]} Made by {v.creators[0]}
@@ -196,66 +196,69 @@ export default function ModDownloadsPopup () {
</p> </p>
</div> </div>
<div className='flex flex-row items-center h-full gap-2 px-3 ml-auto'> <div className='flex flex-row items-center h-full gap-2 px-3 ml-auto'>
<p className='text-green-400' hidden={tab == 0}> {tab != 0 && (
<FontAwesomeIcon icon={faDownload} />{' '} <p className='text-green-400'>
{v.downloads.toLocaleString()} <FontAwesomeIcon icon={faDownload} />{' '}
</p> {v.downloads.toLocaleString()}
<button </p>
className='button btntheme3' )}
onClick={async () => { {tab == 0 && v.latestVersion != localVersion && (
const path = <button
'game/' + className='button btntheme3'
versionInfo?.id + onClick={async () => {
'/BepInEx/plugins/' + const path =
v.id 'game/' +
if ( versionInfo?.id +
await exists( '/BepInEx/plugins/' +
(customDataLocation v.id
? customDataLocation + '/' if (
: null) + path, await exists(
{ (customDataLocation
baseDir: customDataLocation ? customDataLocation + '/'
? undefined : null) + path,
: BaseDirectory.AppLocalData {
} baseDir: customDataLocation
) ? undefined
) : BaseDirectory.AppLocalData
await remove( }
(customDataLocation )
? customDataLocation + '/' )
: null) + path, await remove(
{ (customDataLocation
baseDir: customDataLocation ? customDataLocation + '/'
? undefined : null) + path,
: BaseDirectory.AppLocalData, {
recursive: true baseDir: customDataLocation
} ? undefined
) : BaseDirectory.AppLocalData,
await versions?.set( recursive: true
'mods', }
Object.fromEntries( )
Object.entries(modsList).filter( await versions?.set(
([k]) => k !== versionInfo?.game + '-' + v.id 'mods',
Object.fromEntries(
Object.entries(modsList).filter(
([k]) => k !== versionInfo?.game + '-' + v.id
)
) )
) )
)
downloadVersions([ downloadVersions([
{ {
id: managingVersion, id: managingVersion,
type: 2, type: 2,
modDownload: v.latestDownload, modDownload: v.latestDownload,
gameId: versionInfo?.game, gameId: versionInfo?.game,
modId: v.id, modId: v.id,
modVersion: v.latestVersion modVersion: v.latestVersion
} }
]) ])
}} }}
hidden={tab != 0 || v.latestVersion == localVersion} disabled={downloadProgress.length != 0}
disabled={downloadProgress.length != 0} >
> Update
Update </button>
</button> )}
<button <button
className='button btntheme3' className='button btntheme3'
onClick={() => setShowModInfo(v)} onClick={() => setShowModInfo(v)}
@@ -388,20 +391,21 @@ export default function ModDownloadsPopup () {
/>{' '} />{' '}
View changelog View changelog
</button> </button>
<button {showModInfo.creators.length > 2 && (
className='button btntheme2 w-fit' <button
hidden={showModInfo.creators.length < 2} className='button btntheme2 w-fit'
onClick={async () => { onClick={async () => {
if (!versionInfo) return if (!versionInfo) return
await message(showModInfo.creators.join(', '), { await message(showModInfo.creators.join(', '), {
title: 'Creators for ' + showModInfo.name, title: 'Creators for ' + showModInfo.name,
kind: 'info' kind: 'info'
}) })
}} }}
> >
<FontAwesomeIcon icon={faPeopleGroup} color='lightgray' /> View <FontAwesomeIcon icon={faPeopleGroup} color='lightgray' />{' '}
all creators View all creators
</button> </button>
)}
</div> </div>
</div> </div>
)} )}