Move away from using hidden
This commit is contained in:
9 files changed
+502
-481
No files matched your search
+107
-106
@@ -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>
|
||||
)
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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>
|
||||
)}
|
||||
|
||||
Reference in new issue
Block a user