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

+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>
)}