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
|
{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>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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
@@ -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>
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in new issue
Block a user