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