Heavily improve codebase
This commit is contained in:
20 files changed
+289
-505
No files matched your search
@@ -2,13 +2,13 @@
|
||||
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { BirdColor } from '@/types/BerryDash/BirdColor'
|
||||
import { GetIconForUser } from '@/lib/BerryDash'
|
||||
import { GetIconForUser } from '@/lib/berrydashutil'
|
||||
import Image from 'next/image'
|
||||
import './styles.css'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
import { fetch } from '@tauri-apps/plugin-http'
|
||||
import { verifySignature } from '@/lib/Util'
|
||||
import { verifySignature } from '@/lib/util'
|
||||
|
||||
interface BaseEntry {
|
||||
id: number
|
||||
|
||||
+62
-96
@@ -3,36 +3,33 @@
|
||||
import { useEffect } from 'react'
|
||||
import '@/app/Installs.css'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { useGlobal } from '@/app/GlobalProvider'
|
||||
import { useGlobal } from '@/providers/GlobalProvider'
|
||||
import { useRouter, useSearchParams } from 'next/navigation'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
import { faWarning } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { ask } from '@tauri-apps/plugin-dialog'
|
||||
import { BaseDirectory, exists, remove } from '@tauri-apps/plugin-fs'
|
||||
import { writeVersionsConfig } from '@/lib/BazookaManager'
|
||||
import { openFolder } from '@/lib/Util'
|
||||
import { openFolder } from '@/lib/util'
|
||||
|
||||
export default function Installs () {
|
||||
const {
|
||||
versionsList,
|
||||
serverVersionList,
|
||||
showPopup,
|
||||
setShowPopup,
|
||||
setPopupMode,
|
||||
setFadeOut,
|
||||
setSelectedVersionList,
|
||||
downloadedVersionsConfig,
|
||||
setManagingVersion,
|
||||
getVersionInfo,
|
||||
getGameInfo,
|
||||
setSelectedGame,
|
||||
serverVersionList,
|
||||
category,
|
||||
setCategory,
|
||||
setDownloadedVersionsConfig,
|
||||
downloadVersions,
|
||||
downloadProgress,
|
||||
linuxUseWine,
|
||||
linuxWineCommand
|
||||
linuxWineCommand,
|
||||
versions
|
||||
} = useGlobal()
|
||||
|
||||
const params = useSearchParams()
|
||||
@@ -55,10 +52,7 @@ export default function Installs () {
|
||||
if (!lastRevision) return false
|
||||
return (
|
||||
lastRevision > 0 &&
|
||||
(downloadedVersionsConfig == undefined
|
||||
? 0
|
||||
: downloadedVersionsConfig?.list[version]) /
|
||||
1000 <=
|
||||
(versionsList == undefined ? 0 : versionsList[version]) / 1000 <=
|
||||
lastRevision
|
||||
)
|
||||
}
|
||||
@@ -122,12 +116,11 @@ export default function Installs () {
|
||||
>
|
||||
{category == -1 &&
|
||||
Object.entries(game.categoryNames)
|
||||
.sort(([a], [b]) => Number(b) - Number(a))
|
||||
.filter(([key]) => {
|
||||
const count = Object.keys(
|
||||
downloadedVersionsConfig?.list ?? {}
|
||||
).filter(v => {
|
||||
const info = getVersionInfo(v)
|
||||
const count = Object.keys(versionsList).filter(v => {
|
||||
const info = serverVersionList?.versions.find(
|
||||
vf => vf.id == v
|
||||
)
|
||||
if (!info) return false
|
||||
|
||||
if (platform() == 'linux' && info.wine && !linuxUseWine)
|
||||
@@ -138,6 +131,7 @@ export default function Installs () {
|
||||
|
||||
return count >= 1
|
||||
})
|
||||
.sort(([a], [b]) => Number(b) - Number(a))
|
||||
.map(([key, value]) => {
|
||||
return (
|
||||
<div
|
||||
@@ -157,10 +151,10 @@ export default function Installs () {
|
||||
<p>
|
||||
{(() => {
|
||||
const count =
|
||||
Object.keys(
|
||||
downloadedVersionsConfig?.list ?? []
|
||||
).filter(v => {
|
||||
const info = getVersionInfo(v)
|
||||
Object.keys(versionsList).filter(v => {
|
||||
const info = serverVersionList?.versions.find(
|
||||
vf => vf.id == v
|
||||
)
|
||||
if (!info) return false
|
||||
if (
|
||||
platform() == 'linux' &&
|
||||
@@ -181,20 +175,9 @@ export default function Installs () {
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
{Object.keys(downloadedVersionsConfig?.list ?? []).filter(v => {
|
||||
const info = getVersionInfo(v)
|
||||
if (!info) return false
|
||||
return info.game === id
|
||||
}).length != 0 ? (
|
||||
Object.keys(downloadedVersionsConfig?.list ?? [])
|
||||
.sort((a, b) => {
|
||||
const infoA = getVersionInfo(a)
|
||||
const infoB = getVersionInfo(b)
|
||||
if (!infoA || !infoB) return 0
|
||||
return infoB.place - infoA.place
|
||||
})
|
||||
{Object.keys(versionsList)
|
||||
.filter(v => {
|
||||
const info = getVersionInfo(v)
|
||||
const info = serverVersionList?.versions.find(vf => vf.id == v)
|
||||
if (!info) return false
|
||||
if (platform() == 'linux' && info.wine && !linuxUseWine)
|
||||
return false
|
||||
@@ -205,20 +188,27 @@ export default function Installs () {
|
||||
: info.category == category)
|
||||
)
|
||||
})
|
||||
.map(entry => (
|
||||
.sort((a, b) => {
|
||||
const infoA = serverVersionList?.versions.find(vf => vf.id == a)
|
||||
const infoB = serverVersionList?.versions.find(vf => vf.id == b)
|
||||
if (!infoA || !infoB) return 0
|
||||
return infoB.place - infoA.place
|
||||
})
|
||||
.map(v => {
|
||||
const versionInfo = serverVersionList?.versions.find(
|
||||
vf => vf.id == v
|
||||
)
|
||||
if (!versionInfo) return
|
||||
|
||||
return (
|
||||
<div
|
||||
key={entry}
|
||||
key={v}
|
||||
className={'downloads-entry'}
|
||||
title={
|
||||
'Click to launch game. Right-click to manage this version install'
|
||||
}
|
||||
onClick={async () => {
|
||||
if (
|
||||
needsRevisionUpdate(
|
||||
getVersionInfo(entry)?.lastRevision,
|
||||
entry
|
||||
)
|
||||
) {
|
||||
if (needsRevisionUpdate(versionInfo.lastRevision, v)) {
|
||||
const answer = await ask(
|
||||
'Before proceeding, if you do not want your installation directory wiped just yet, please backup the files to another directory. When you click "Yes", it will be wiped. Click "No" if you want to open the installation folder instead.',
|
||||
{
|
||||
@@ -242,55 +232,45 @@ export default function Installs () {
|
||||
setFadeOut(false)
|
||||
|
||||
//uninstall
|
||||
setDownloadedVersionsConfig(prev => {
|
||||
if (!prev) return prev
|
||||
const updatedList = Object.fromEntries(
|
||||
Object.entries(prev.list).filter(
|
||||
([k]) => k !== entry
|
||||
versions?.set(
|
||||
'list',
|
||||
Object.fromEntries(
|
||||
Object.entries(versionsList).filter(
|
||||
([k]) => k !== v
|
||||
)
|
||||
)
|
||||
)
|
||||
const updatedConfig = {
|
||||
...prev,
|
||||
list: updatedList
|
||||
}
|
||||
writeVersionsConfig(updatedConfig)
|
||||
return updatedConfig
|
||||
})
|
||||
|
||||
if (
|
||||
await exists('game/' + entry, {
|
||||
await exists('game/' + v, {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
})
|
||||
)
|
||||
await remove('game/' + entry, {
|
||||
await remove('game/' + v, {
|
||||
baseDir: BaseDirectory.AppLocalData,
|
||||
recursive: true
|
||||
})
|
||||
|
||||
//reinstall
|
||||
setSelectedVersionList([entry])
|
||||
setSelectedVersionList([v])
|
||||
downloadVersions([
|
||||
{
|
||||
id: entry,
|
||||
id: v,
|
||||
type: 0
|
||||
}
|
||||
])
|
||||
} else {
|
||||
openFolder(entry)
|
||||
openFolder(v)
|
||||
}
|
||||
return
|
||||
}
|
||||
const verInfo = getVersionInfo(entry)
|
||||
if (verInfo == undefined) return
|
||||
const gameInfo = getGameInfo(verInfo.game)
|
||||
if (gameInfo == undefined) return
|
||||
invoke('launch_game', {
|
||||
name: verInfo.id,
|
||||
executable: verInfo.executable,
|
||||
displayName: verInfo.displayName,
|
||||
name: versionInfo.id,
|
||||
executable: versionInfo.executable,
|
||||
displayName: versionInfo.displayName,
|
||||
useWine: !!(
|
||||
platform() == 'linux' &&
|
||||
verInfo.wine &&
|
||||
versionInfo.wine &&
|
||||
linuxUseWine
|
||||
),
|
||||
wineCommand: linuxWineCommand
|
||||
@@ -298,16 +278,14 @@ export default function Installs () {
|
||||
}}
|
||||
onContextMenu={e => {
|
||||
e.preventDefault()
|
||||
setManagingVersion(entry)
|
||||
setManagingVersion(v)
|
||||
setPopupMode(2)
|
||||
setShowPopup(true)
|
||||
setFadeOut(false)
|
||||
}}
|
||||
>
|
||||
<div className='h-18 w-screen relative'>
|
||||
<p className='text-2xl'>
|
||||
{getVersionInfo(entry)?.displayName}{' '}
|
||||
</p>
|
||||
<p className='text-2xl'>{versionInfo.displayName}</p>
|
||||
|
||||
<div className='flex gap-2 absolute left-0 bottom-0'>
|
||||
<div
|
||||
@@ -317,7 +295,7 @@ export default function Installs () {
|
||||
<p>
|
||||
Installed{' '}
|
||||
{new Intl.DateTimeFormat(undefined).format(
|
||||
downloadedVersionsConfig?.list[entry]
|
||||
versionsList[v]
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
@@ -325,13 +303,8 @@ export default function Installs () {
|
||||
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' && getVersionInfo(entry)?.wine
|
||||
) ||
|
||||
needsRevisionUpdate(
|
||||
getVersionInfo(entry)?.lastRevision,
|
||||
entry
|
||||
)
|
||||
!(platform() == 'linux' && versionInfo.wine) ||
|
||||
needsRevisionUpdate(versionInfo.lastRevision, v)
|
||||
}
|
||||
>
|
||||
<FontAwesomeIcon icon={faWarning} color='#ffc800' />
|
||||
@@ -340,10 +313,7 @@ export default function Installs () {
|
||||
<div
|
||||
className='entry-info-item'
|
||||
hidden={
|
||||
!needsRevisionUpdate(
|
||||
getVersionInfo(entry)?.lastRevision,
|
||||
entry
|
||||
)
|
||||
!needsRevisionUpdate(versionInfo.lastRevision, v)
|
||||
}
|
||||
>
|
||||
<FontAwesomeIcon icon={faWarning} color='#ffc800' />
|
||||
@@ -357,45 +327,41 @@ export default function Installs () {
|
||||
e.stopPropagation()
|
||||
|
||||
if (
|
||||
!(await exists('game/' + entry + '/BepInEx', {
|
||||
!(await exists('game/' + v + '/BepInEx', {
|
||||
baseDir: 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 " +
|
||||
getVersionInfo(entry)?.displayName +
|
||||
versionInfo.displayName +
|
||||
'.',
|
||||
{ title: 'BepInEx not found!', kind: 'error' }
|
||||
)) &&
|
||||
!downloadProgress.find(d => d.version == entry)
|
||||
!downloadProgress.find(d => d.version == v)
|
||||
) {
|
||||
downloadVersions([
|
||||
{
|
||||
id: entry,
|
||||
id: v,
|
||||
type: 1
|
||||
}
|
||||
])
|
||||
}
|
||||
return
|
||||
}
|
||||
setManagingVersion(entry)
|
||||
setManagingVersion(v)
|
||||
setPopupMode(3)
|
||||
setShowPopup(true)
|
||||
setFadeOut(false)
|
||||
}}
|
||||
hidden={!getVersionInfo(entry)?.modSupportDownload}
|
||||
hidden={!versionInfo.modSupportDownload}
|
||||
>
|
||||
Mod Manager
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className='flex justify-center items-center h-full'>
|
||||
<p className='text-3xl'>No versions installed</p>
|
||||
</div>
|
||||
)}
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+77
-132
@@ -1,21 +1,14 @@
|
||||
'use client'
|
||||
|
||||
import './Globals.css'
|
||||
import '@/styles/globals.css'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import Sidebar from '@/components/Sidebar'
|
||||
import { DownloadProgress } from '@/types/DownloadProgress'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faChevronLeft, faXmark } from '@fortawesome/free-solid-svg-icons'
|
||||
import { readVersionsConfig, writeVersionsConfig } from '@/lib/BazookaManager'
|
||||
import { VersionsConfig } from '@/types/VersionsConfig'
|
||||
import { app } from '@tauri-apps/api'
|
||||
import { openUrl } from '@tauri-apps/plugin-opener'
|
||||
import { GlobalProvider } from './GlobalProvider'
|
||||
import { GlobalProvider } from '../providers/GlobalProvider'
|
||||
import { Roboto } from 'next/font/google'
|
||||
import { ServerVersionsResponse } from '@/types/ServerVersionsResponse'
|
||||
import { GameVersion } from '@/types/GameVersion'
|
||||
import { Game } from '@/types/Game'
|
||||
import { listen } from '@tauri-apps/api/event'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import { arch, platform } from '@tauri-apps/plugin-os'
|
||||
@@ -30,17 +23,21 @@ import {
|
||||
remove
|
||||
} from '@tauri-apps/plugin-fs'
|
||||
import { fetch } from '@tauri-apps/plugin-http'
|
||||
import { verifySignature } from '@/lib/Util'
|
||||
import { verifySignature } from '@/lib/util'
|
||||
import { getCurrentWindow, UserAttentionType } from '@tauri-apps/api/window'
|
||||
|
||||
import VersionsDownloadPopup from '@/components/popups/VersionsDownload'
|
||||
import GamesDownloadPopup from '@/components/popups/GamesDownload'
|
||||
import DownloadsPopup from '@/components/popups/Downloads'
|
||||
import ManageVersionPopup from '@/components/popups/ManageVersion'
|
||||
import ModDownloadsPopup from '@/components/popups/ModDownloads'
|
||||
import { Mod } from '@/types/Mod'
|
||||
import { load, Store } from '@tauri-apps/plugin-store'
|
||||
import { notifyUser } from '@/lib/Notifications'
|
||||
import { notifyUser } from '@/lib/notifications'
|
||||
|
||||
import VersionsDownloadPopup from '@/popups/VersionsDownload'
|
||||
import GamesDownloadPopup from '@/popups/GamesDownload'
|
||||
import DownloadsPopup from '@/popups/Downloads'
|
||||
import ManageVersionPopup from '@/popups/ManageVersion'
|
||||
import ModDownloadsPopup from '@/popups/ModDownloads'
|
||||
import { GameVersion } from '@/types/GameVersion'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faChevronLeft, faXmark } from '@fortawesome/free-solid-svg-icons'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
|
||||
const roboto = Roboto({
|
||||
subsets: ['latin']
|
||||
@@ -61,9 +58,6 @@ export default function RootLayout ({
|
||||
useState<null | ServerVersionsResponse>(null)
|
||||
const [selectedVersionList, setSelectedVersionList] = useState<string[]>([])
|
||||
|
||||
const [downloadedVersionsConfig, setDownloadedVersionsConfig] =
|
||||
useState<VersionsConfig | null>(null)
|
||||
|
||||
const [showPopup, setShowPopup] = useState(false)
|
||||
const [popupMode, setPopupMode] = useState<null | number>(null)
|
||||
const [fadeOut, setFadeOut] = useState(false)
|
||||
@@ -85,6 +79,7 @@ export default function RootLayout ({
|
||||
const revisionCheck = useRef(false)
|
||||
|
||||
const [settings, setSettings] = useState<Store | null>(null)
|
||||
const [versions, setVersions] = useState<Store | null>(null)
|
||||
|
||||
const [notificationsAllowed, setNotificationsAllowed] =
|
||||
useState<boolean>(false)
|
||||
@@ -95,13 +90,16 @@ export default function RootLayout ({
|
||||
useState<string>('wine %path%')
|
||||
const [theme, setTheme] = useState<string>('dark')
|
||||
|
||||
const [versionsList, setVersionsList] = useState<Record<string, number>>({})
|
||||
const [modsList, setModsList] = useState<
|
||||
Record<string, Record<string, number>>
|
||||
>({})
|
||||
|
||||
function getSpecialVersionsList (game?: number): GameVersion[] {
|
||||
if (!serverVersionList) return []
|
||||
|
||||
return serverVersionList.versions
|
||||
.filter(
|
||||
v => !Object.keys(downloadedVersionsConfig?.list ?? []).includes(v.id)
|
||||
)
|
||||
.filter(v => !Object.keys(versionsList).includes(v.id))
|
||||
.filter(v => {
|
||||
if (platformName == 'linux' && v.wine && linuxUseWine) return false
|
||||
|
||||
@@ -118,62 +116,6 @@ export default function RootLayout ({
|
||||
})
|
||||
}
|
||||
|
||||
const getVersionInfo = useCallback(
|
||||
(id: string | undefined): GameVersion | undefined => {
|
||||
if (!id) return undefined
|
||||
return serverVersionList?.versions.find(v => v.id === id)
|
||||
},
|
||||
[serverVersionList]
|
||||
)
|
||||
|
||||
const getGameInfo = useCallback(
|
||||
(game: number | undefined): Game | undefined => {
|
||||
if (!game) return undefined
|
||||
return serverVersionList?.games.find(g => g.id === game)
|
||||
},
|
||||
[serverVersionList]
|
||||
)
|
||||
|
||||
function getListOfGames (): Game[] {
|
||||
if (!downloadedVersionsConfig?.list) return []
|
||||
|
||||
const gamesMap = new Map<number, Game>()
|
||||
|
||||
Object.keys(downloadedVersionsConfig.list).forEach(i => {
|
||||
const version = getVersionInfo(i)
|
||||
if (!version) return
|
||||
const game = getGameInfo(version.game)
|
||||
if (!game) return
|
||||
gamesMap.set(game.id, game)
|
||||
})
|
||||
|
||||
return Array.from(gamesMap.values())
|
||||
}
|
||||
|
||||
function getVersionsAmountData (gameId: number): {
|
||||
installed: number
|
||||
total: number
|
||||
} | null {
|
||||
if (!downloadedVersionsConfig || !serverVersionList) return null
|
||||
|
||||
const allowWine = platformName !== 'linux' || linuxUseWine
|
||||
|
||||
const installed = Object.keys(downloadedVersionsConfig.list).filter(v => {
|
||||
const info = getVersionInfo(v)
|
||||
if (!info) return false
|
||||
if (info.wine && !allowWine) return false
|
||||
return getGameInfo(info.game)?.id === gameId
|
||||
}).length
|
||||
|
||||
const total = serverVersionList.versions.filter(v => {
|
||||
if (!v) return false
|
||||
if (v.wine && !allowWine) return false
|
||||
return getGameInfo(v.game)?.id === gameId
|
||||
}).length
|
||||
|
||||
return { installed, total }
|
||||
}
|
||||
|
||||
const closePopup = useCallback(() => {
|
||||
if (popupMode == 0 && selectedGame && pathname === '/') {
|
||||
setSelectedGame(null)
|
||||
@@ -369,12 +311,21 @@ export default function RootLayout ({
|
||||
theme: 'dark'
|
||||
}
|
||||
})
|
||||
const versionsLocal = await load('versions.json', {
|
||||
autoSave: true,
|
||||
defaults: {
|
||||
version: client,
|
||||
list: {},
|
||||
mods: {}
|
||||
}
|
||||
})
|
||||
settingsLocal.set('version', client)
|
||||
const oldSettingsOptions = {
|
||||
versionsLocal.set('version', client)
|
||||
const legacyOptions = {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
}
|
||||
if (await exists('config.json', oldSettingsOptions)) {
|
||||
const config = await readTextFile('config.json', oldSettingsOptions)
|
||||
if (await exists('config.json', legacyOptions)) {
|
||||
const config = await readTextFile('config.json', legacyOptions)
|
||||
const raw = JSON.parse(config)
|
||||
if (
|
||||
raw.settings &&
|
||||
@@ -432,11 +383,10 @@ export default function RootLayout ({
|
||||
})()
|
||||
settingsLocal?.set('theme', tempTheme)
|
||||
}
|
||||
await remove('config.json', oldSettingsOptions)
|
||||
await remove('config.json', legacyOptions)
|
||||
}
|
||||
const versionsConfig = await readVersionsConfig()
|
||||
setDownloadedVersionsConfig(versionsConfig)
|
||||
setSettings(settingsLocal)
|
||||
setVersions(versionsLocal)
|
||||
setLoading(false)
|
||||
|
||||
if (!(await isPermissionGranted())) {
|
||||
@@ -511,7 +461,7 @@ export default function RootLayout ({
|
||||
const versionId = downloadQueue[0]
|
||||
const downloadInfo = downloadProgress.find(d => d.version == versionId)
|
||||
if (!downloadInfo) return
|
||||
const info = getVersionInfo(versionId)
|
||||
const info = serverVersionList?.versions.find(vf => vf.id == versionId)
|
||||
|
||||
if (!info) {
|
||||
setDownloadProgress(prev => prev.filter(d => d.version !== versionId))
|
||||
@@ -520,7 +470,7 @@ export default function RootLayout ({
|
||||
return
|
||||
}
|
||||
|
||||
const gameInfo = getGameInfo(info.game)
|
||||
const gameInfo = serverVersionList?.games.find(vf => vf.id == info.game)
|
||||
if (!gameInfo) {
|
||||
setDownloadProgress(prev => prev.filter(d => d.version !== versionId))
|
||||
setDownloadQueue(prev => prev.slice(1))
|
||||
@@ -590,31 +540,19 @@ export default function RootLayout ({
|
||||
if (res === '1') {
|
||||
setDownloadProgress(prev => prev.filter(d => d.version !== versionId))
|
||||
if (downloadInfo.type != 1) {
|
||||
setDownloadedVersionsConfig(prev => {
|
||||
if (!prev) return prev
|
||||
|
||||
const updated =
|
||||
downloadInfo.type == 2
|
||||
? {
|
||||
...prev,
|
||||
mods: {
|
||||
...prev.mods,
|
||||
if (downloadInfo.type == 2) {
|
||||
versions?.set('mods', {
|
||||
...modsList,
|
||||
[downloadInfo.modGame! + '-' + downloadInfo.modId!]: {
|
||||
[downloadInfo.modVersion!]: Date.now()
|
||||
}
|
||||
}
|
||||
}
|
||||
: {
|
||||
...prev,
|
||||
list: {
|
||||
...prev.list,
|
||||
[versionId]: Date.now()
|
||||
}
|
||||
}
|
||||
|
||||
writeVersionsConfig(updated)
|
||||
return updated
|
||||
})
|
||||
} else {
|
||||
versions?.set('list', {
|
||||
...versionsList,
|
||||
[versionId]: Date.now()
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if (res == '0') {
|
||||
setDownloadProgress(prev => {
|
||||
@@ -658,20 +596,20 @@ export default function RootLayout ({
|
||||
}, [
|
||||
downloadQueue,
|
||||
isProcessingQueue,
|
||||
getVersionInfo,
|
||||
getGameInfo,
|
||||
downloadProgress,
|
||||
settings
|
||||
serverVersionList,
|
||||
settings,
|
||||
versions,
|
||||
versionsList,
|
||||
modsList
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
if (revisionCheck.current) return
|
||||
if (!serverVersionList || !downloadedVersionsConfig) return
|
||||
if (!serverVersionList) return
|
||||
revisionCheck.current = true
|
||||
;(async () => {
|
||||
for (const [key, value] of Object.entries(
|
||||
downloadedVersionsConfig.list
|
||||
)) {
|
||||
for (const [key, value] of Object.entries(versionsList)) {
|
||||
const verInfo = serverVersionList.versions.find(item => item.id === key)
|
||||
|
||||
if (
|
||||
@@ -690,7 +628,7 @@ export default function RootLayout ({
|
||||
}
|
||||
}
|
||||
})()
|
||||
}, [serverVersionList, downloadedVersionsConfig, downloadVersions])
|
||||
}, [serverVersionList, downloadVersions, versionsList])
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
@@ -719,30 +657,40 @@ export default function RootLayout ({
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
if (!settings) return
|
||||
if (!settings || !versions) return
|
||||
const unlisteners: Promise<() => void>[] = []
|
||||
|
||||
function watch<T> (key: string, fn: (v: T | undefined) => void) {
|
||||
function watchSettings<T> (key: string, fn: (v: T | undefined) => void) {
|
||||
settings!.get<T>(key).then(fn)
|
||||
unlisteners.push(settings!.onKeyChange<T>(key, fn))
|
||||
}
|
||||
|
||||
watch<string>('theme', v => setTheme(v ?? 'dark'))
|
||||
watch<boolean>('notificationsAllowed', v =>
|
||||
function watchVersions<T> (key: string, fn: (v: T | undefined) => void) {
|
||||
versions!.get<T>(key).then(fn)
|
||||
unlisteners.push(versions!.onKeyChange<T>(key, fn))
|
||||
}
|
||||
|
||||
watchSettings<string>('theme', v => setTheme(v ?? 'dark'))
|
||||
watchSettings<boolean>('notificationsAllowed', v =>
|
||||
setNotificationsAllowed(v ?? true)
|
||||
)
|
||||
watch<boolean>('sidebarAlwaysShowGames', v =>
|
||||
watchSettings<boolean>('sidebarAlwaysShowGames', v =>
|
||||
setSidebarAlwaysShowGames(v ?? true)
|
||||
)
|
||||
watch<boolean>('linuxUseWine', v => setLinuxUseWine(v ?? false))
|
||||
watch<string>('linuxWineCommand', v =>
|
||||
watchSettings<boolean>('linuxUseWine', v => setLinuxUseWine(v ?? false))
|
||||
watchSettings<string>('linuxWineCommand', v =>
|
||||
setLinuxWineCommand(v ?? 'wine %path%')
|
||||
)
|
||||
|
||||
watchVersions<Record<string, number>>('list', v => setVersionsList(v ?? {}))
|
||||
watchVersions<Record<string, Record<string, number>>>('mods', v =>
|
||||
setModsList(v ?? {})
|
||||
)
|
||||
|
||||
return () => {
|
||||
unlisteners.forEach(u => u.then(fn => fn()))
|
||||
}
|
||||
}, [settings])
|
||||
}, [settings, versions])
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -795,15 +743,9 @@ export default function RootLayout ({
|
||||
setPopupMode,
|
||||
fadeOut,
|
||||
setFadeOut,
|
||||
downloadedVersionsConfig,
|
||||
setDownloadedVersionsConfig,
|
||||
managingVersion,
|
||||
setManagingVersion,
|
||||
getVersionInfo,
|
||||
getGameInfo,
|
||||
getListOfGames,
|
||||
setSelectedGame,
|
||||
getVersionsAmountData,
|
||||
viewingInfoFromDownloads,
|
||||
version,
|
||||
downloadVersions,
|
||||
@@ -812,17 +754,20 @@ export default function RootLayout ({
|
||||
downloadQueue,
|
||||
setDownloadQueue,
|
||||
closePopup,
|
||||
getSpecialVersionsList,
|
||||
selectedGame,
|
||||
setViewingInfoFromDownloads,
|
||||
showModInfo,
|
||||
setShowModInfo,
|
||||
getSpecialVersionsList,
|
||||
settings,
|
||||
versions,
|
||||
notificationsAllowed,
|
||||
sidebarAlwaysShowGames,
|
||||
linuxUseWine,
|
||||
linuxWineCommand,
|
||||
theme
|
||||
theme,
|
||||
versionsList,
|
||||
modsList
|
||||
}}
|
||||
>
|
||||
<div
|
||||
|
||||
+20
-19
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useEffect } from 'react'
|
||||
import './Installs.css'
|
||||
import { useGlobal } from './GlobalProvider'
|
||||
import { useGlobal } from '../providers/GlobalProvider'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import {
|
||||
faCheck,
|
||||
@@ -14,15 +14,14 @@ import { useRouter } from 'next/navigation'
|
||||
|
||||
export default function Installs () {
|
||||
const {
|
||||
versionsList,
|
||||
serverVersionList,
|
||||
showPopup,
|
||||
setShowPopup,
|
||||
setPopupMode,
|
||||
setFadeOut,
|
||||
setSelectedVersionList,
|
||||
downloadedVersionsConfig,
|
||||
setSelectedGame,
|
||||
getListOfGames,
|
||||
getVersionsAmountData,
|
||||
setCategory
|
||||
} = useGlobal()
|
||||
|
||||
@@ -58,12 +57,12 @@ export default function Installs () {
|
||||
: 'h-[calc(100vh-84px)]'
|
||||
}`}
|
||||
>
|
||||
{downloadedVersionsConfig &&
|
||||
Object.keys(downloadedVersionsConfig.list).length ? (
|
||||
getListOfGames()
|
||||
.sort((a, b) => {
|
||||
return a.id - b.id
|
||||
})
|
||||
{serverVersionList?.games
|
||||
.filter(g =>
|
||||
serverVersionList.versions
|
||||
.filter(v => v.game === g.id)
|
||||
.some(v => Object.keys(versionsList).includes(v.id))
|
||||
)
|
||||
.map(i => (
|
||||
<div
|
||||
key={i.id}
|
||||
@@ -85,9 +84,16 @@ export default function Installs () {
|
||||
>
|
||||
<p>
|
||||
{(() => {
|
||||
const data = getVersionsAmountData(i.id)
|
||||
if (!data) return 'N/A'
|
||||
return `${data.installed}/${data.total}`
|
||||
const gameVersions =
|
||||
serverVersionList.versions.filter(
|
||||
v => v.game === i.id
|
||||
)
|
||||
const installed = gameVersions.filter(v =>
|
||||
Object.keys(versionsList).includes(v.id)
|
||||
).length
|
||||
return gameVersions.length
|
||||
? `${installed}/${gameVersions.length}`
|
||||
: 'N/A'
|
||||
})()}{' '}
|
||||
versions installed
|
||||
</p>
|
||||
@@ -120,12 +126,7 @@ export default function Installs () {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className='flex justify-center items-center h-full'>
|
||||
<p className='text-3xl'>No games installed</p>
|
||||
</div>
|
||||
)}
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use client'
|
||||
|
||||
import { Setting } from '@/components/Setting'
|
||||
import { useGlobal } from '@/app/GlobalProvider'
|
||||
import { copyToClipboard } from '@/lib/Clipboard'
|
||||
import { useGlobal } from '@/providers/GlobalProvider'
|
||||
import { copyToClipboard } from '@/lib/clipboard'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
|
||||
export default function Settings () {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import './Setting.css'
|
||||
import '@/styles/setting.css'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faCheck } from '@fortawesome/free-solid-svg-icons'
|
||||
import { SettingProps } from '@/types/SettingProps'
|
||||
|
||||
+14
-13
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import './Sidebar.css'
|
||||
import '@/styles/sidebar.css'
|
||||
import Icon from '@/assets/Icon.png'
|
||||
import { openUrl } from '@tauri-apps/plugin-opener'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import { faDiscord } from '@fortawesome/free-brands-svg-icons'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
import { useGlobal } from '@/app/GlobalProvider'
|
||||
import { useGlobal } from '@/providers/GlobalProvider'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
|
||||
@@ -27,13 +27,12 @@ const lexend = Lexend({
|
||||
|
||||
export default function Sidebar () {
|
||||
const {
|
||||
getListOfGames,
|
||||
serverVersionList,
|
||||
versionsList,
|
||||
setShowPopup,
|
||||
setPopupMode,
|
||||
setFadeOut,
|
||||
downloadProgress,
|
||||
downloadedVersionsConfig,
|
||||
getVersionInfo,
|
||||
category,
|
||||
setCategory,
|
||||
sidebarAlwaysShowGames,
|
||||
@@ -90,10 +89,12 @@ export default function Sidebar () {
|
||||
>
|
||||
<FontAwesomeIcon icon={faHexagonNodes} className='mr-2' /> Games
|
||||
</Link>
|
||||
{getListOfGames()
|
||||
.sort((a, b) => {
|
||||
return a.id - b.id
|
||||
})
|
||||
{serverVersionList?.games
|
||||
.filter(g =>
|
||||
serverVersionList.versions
|
||||
.filter(v => v.game === g.id)
|
||||
.some(v => Object.keys(versionsList).includes(v.id))
|
||||
)
|
||||
.map(i => (
|
||||
<React.Fragment key={i.id}>
|
||||
<div
|
||||
@@ -131,10 +132,10 @@ export default function Sidebar () {
|
||||
{Object.entries(i.categoryNames)
|
||||
.sort(([a], [b]) => Number(b) - Number(a))
|
||||
.filter(([key]) => {
|
||||
const count = Object.keys(
|
||||
downloadedVersionsConfig?.list ?? {}
|
||||
).filter(v => {
|
||||
const info = getVersionInfo(v)
|
||||
const count = Object.keys(versionsList).filter(v => {
|
||||
const info = serverVersionList.versions.find(
|
||||
vf => vf.id == v
|
||||
)
|
||||
if (!info) return false
|
||||
|
||||
if (platform() == 'linux' && info.wine && !linuxUseWine)
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
import { app } from '@tauri-apps/api'
|
||||
import {
|
||||
BaseDirectory,
|
||||
create,
|
||||
exists,
|
||||
mkdir,
|
||||
readTextFile,
|
||||
writeFile
|
||||
} from '@tauri-apps/plugin-fs'
|
||||
import { VersionsConfig } from '@/types/VersionsConfig'
|
||||
|
||||
export async function readVersionsConfig (): Promise<VersionsConfig> {
|
||||
const version = await app.getVersion()
|
||||
try {
|
||||
const options = {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
}
|
||||
const doesFolderExist = await exists('', options)
|
||||
const doesConfigExist = await exists('versions.json', options)
|
||||
if (!doesFolderExist || !doesConfigExist) {
|
||||
if (!doesFolderExist) {
|
||||
await mkdir('', options)
|
||||
}
|
||||
const file = await create('versions.json', options)
|
||||
await file.write(
|
||||
new TextEncoder().encode(
|
||||
JSON.stringify(new VersionsConfig(version), null, 2)
|
||||
)
|
||||
)
|
||||
await file.close()
|
||||
return new VersionsConfig(version)
|
||||
}
|
||||
const config = await readTextFile('versions.json', options)
|
||||
const raw = JSON.parse(config)
|
||||
if (raw.list && raw.timestamps) {
|
||||
raw.list = raw.timestamps
|
||||
delete raw.timestamps
|
||||
|
||||
await writeFile(
|
||||
'versions.json',
|
||||
new TextEncoder().encode(JSON.stringify(raw, null, 2)),
|
||||
options
|
||||
)
|
||||
}
|
||||
raw.version = version
|
||||
writeVersionsConfig(raw)
|
||||
return VersionsConfig.import(raw)
|
||||
} catch {
|
||||
return new VersionsConfig(version)
|
||||
}
|
||||
}
|
||||
|
||||
export async function writeVersionsConfig (data: VersionsConfig) {
|
||||
const options = {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
}
|
||||
const doesFolderExist = await exists('', options)
|
||||
const doesConfigExist = await exists('versions.json', options)
|
||||
if (!doesFolderExist || !doesConfigExist) {
|
||||
if (!doesFolderExist) {
|
||||
await mkdir('', options)
|
||||
}
|
||||
const file = await create('versions.json', options)
|
||||
await file.write(new TextEncoder().encode(JSON.stringify(data, null, 2)))
|
||||
await file.close()
|
||||
} else {
|
||||
await writeFile(
|
||||
'versions.json',
|
||||
new TextEncoder().encode(JSON.stringify(data, null, 2)),
|
||||
options
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { writeText } from '@tauri-apps/plugin-clipboard-manager'
|
||||
import { notifyUser } from './Notifications'
|
||||
import { notifyUser } from './notifications'
|
||||
|
||||
export async function copyToClipboard (
|
||||
text: string,
|
||||
|
||||
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
import { useGlobal } from '@/app/GlobalProvider'
|
||||
import { useGlobal } from '@/providers/GlobalProvider'
|
||||
import prettyBytes from 'pretty-bytes'
|
||||
import ProgressBar from '../ProgressBar'
|
||||
import { formatEtaSmart } from '@/lib/Util'
|
||||
import ProgressBar from '@/components/ProgressBar'
|
||||
import { formatEtaSmart } from '@/lib/util'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import {
|
||||
faCancel,
|
||||
@@ -10,19 +10,20 @@ import {
|
||||
faTrash
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { writeVersionsConfig } from '@/lib/BazookaManager'
|
||||
import { notifyUser } from '@/lib/Notifications'
|
||||
import { notifyUser } from '@/lib/notifications'
|
||||
import { getCurrentWindow, UserAttentionType } from '@tauri-apps/api/window'
|
||||
|
||||
export default function DownloadsPopup () {
|
||||
const {
|
||||
downloadProgress,
|
||||
getVersionInfo,
|
||||
setDownloadProgress,
|
||||
downloadQueue,
|
||||
setDownloadQueue,
|
||||
setDownloadedVersionsConfig,
|
||||
notificationsAllowed
|
||||
notificationsAllowed,
|
||||
versionsList,
|
||||
modsList,
|
||||
versions,
|
||||
serverVersionList
|
||||
} = useGlobal()
|
||||
|
||||
return (
|
||||
@@ -68,31 +69,19 @@ export default function DownloadsPopup () {
|
||||
prev.filter(d => d.version !== v.version)
|
||||
)
|
||||
if (v.type != 1) {
|
||||
setDownloadedVersionsConfig(prev => {
|
||||
if (!prev) return prev
|
||||
|
||||
const updated =
|
||||
v.type == 2
|
||||
? {
|
||||
...prev,
|
||||
mods: {
|
||||
...prev.mods,
|
||||
if (v.type == 2) {
|
||||
versions?.set('mods', {
|
||||
...modsList,
|
||||
[v.modGame! + '-' + v.modId!]: {
|
||||
[v.modVersion!]: Date.now()
|
||||
}
|
||||
}
|
||||
}
|
||||
: {
|
||||
...prev,
|
||||
list: {
|
||||
...prev.list,
|
||||
[v.version]: Date.now()
|
||||
}
|
||||
}
|
||||
|
||||
writeVersionsConfig(updated)
|
||||
return updated
|
||||
})
|
||||
} else {
|
||||
versions?.set('list', {
|
||||
...versionsList,
|
||||
[v.version]: Date.now()
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if (res == '0') {
|
||||
setDownloadProgress(prev => {
|
||||
@@ -127,7 +116,9 @@ export default function DownloadsPopup () {
|
||||
await notifyUser(
|
||||
'Download Failed',
|
||||
`The download for version ${
|
||||
getVersionInfo(v.version)?.displayName
|
||||
serverVersionList?.versions.find(
|
||||
vf => vf.id == v.version
|
||||
)?.displayName
|
||||
} has failed.`
|
||||
)
|
||||
await getCurrentWindow().requestUserAttention(
|
||||
@@ -186,11 +177,14 @@ export default function DownloadsPopup () {
|
||||
</div>
|
||||
<p className='text-2xl text-center'>
|
||||
{v.type == 1
|
||||
? 'Mod Manager for '
|
||||
? 'Mod loader for '
|
||||
: v.type == 2
|
||||
? 'Mod for '
|
||||
: null}{' '}
|
||||
{getVersionInfo(v.version)?.displayName}
|
||||
{
|
||||
serverVersionList?.versions.find(vf => vf.id == v.version)
|
||||
?.displayName
|
||||
}
|
||||
</p>
|
||||
<div className='mt-6.25 flex items-center justify-between'>
|
||||
{v.failed || v.queued ? (
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useGlobal } from '@/app/GlobalProvider'
|
||||
import { useGlobal } from '@/providers/GlobalProvider'
|
||||
import {
|
||||
faCheck,
|
||||
faCode,
|
||||
@@ -9,18 +9,18 @@ import {
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
|
||||
export default function GamesDownloadPopup () {
|
||||
const { serverVersionList, getVersionsAmountData, setSelectedGame } =
|
||||
useGlobal()
|
||||
const { serverVersionList, setSelectedGame, versionsList } = useGlobal()
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className='text-xl text-center'>Select a game to download</p>
|
||||
<div className='popup-content'>
|
||||
{serverVersionList?.games
|
||||
.filter(v => {
|
||||
const data = getVersionsAmountData(v.id)
|
||||
if (!data) return false
|
||||
if (data.total > 0) return true
|
||||
.filter(i => {
|
||||
const gameVersions = serverVersionList.versions.filter(
|
||||
vf => vf.game === i.id
|
||||
)
|
||||
if (gameVersions.length > 0) return true
|
||||
})
|
||||
.map((v, i) => (
|
||||
<div key={i} className='popup-entry'>
|
||||
@@ -32,9 +32,15 @@ export default function GamesDownloadPopup () {
|
||||
>
|
||||
<p>
|
||||
{(() => {
|
||||
const data = getVersionsAmountData(v.id)
|
||||
if (!data) return 'N/A'
|
||||
return `${data.installed}/${data.total}`
|
||||
const gameVersions = serverVersionList.versions.filter(
|
||||
vf => vf.game === v.id
|
||||
)
|
||||
const installed = gameVersions.filter(v =>
|
||||
Object.keys(versionsList).includes(v.id)
|
||||
).length
|
||||
return gameVersions.length
|
||||
? `${installed}/${gameVersions.length}`
|
||||
: 'N/A'
|
||||
})()}{' '}
|
||||
versions installed
|
||||
</p>
|
||||
@@ -74,11 +80,7 @@ export default function GamesDownloadPopup () {
|
||||
<button
|
||||
className='button btntheme3 right-2 bottom-2'
|
||||
onClick={() => setSelectedGame(v.id)}
|
||||
title={`Click to download specific versions of the game. You have ${(() => {
|
||||
const data = getVersionsAmountData(v.id)
|
||||
if (!data) return 'N/A'
|
||||
return `${data.installed} of ${data.total}`
|
||||
})()} versions downloaded.`}
|
||||
title='Click to download more versions of the game.'
|
||||
>
|
||||
<>
|
||||
<FontAwesomeIcon icon={faDownload} /> Download
|
||||
@@ -9,28 +9,26 @@ import {
|
||||
faWarning
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { useGlobal } from '@/app/GlobalProvider'
|
||||
import { useGlobal } from '@/providers/GlobalProvider'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { useEffect, useState } from 'react'
|
||||
import prettyBytes from 'pretty-bytes'
|
||||
import { message } from '@tauri-apps/plugin-dialog'
|
||||
import { BaseDirectory, exists, remove } from '@tauri-apps/plugin-fs'
|
||||
import { writeVersionsConfig } from '@/lib/BazookaManager'
|
||||
import { openFolder } from '@/lib/Util'
|
||||
import { openFolder } from '@/lib/util'
|
||||
|
||||
export default function ManageVersionPopup () {
|
||||
const {
|
||||
getGameInfo,
|
||||
getVersionInfo,
|
||||
versionsList,
|
||||
serverVersionList,
|
||||
managingVersion,
|
||||
downloadedVersionsConfig,
|
||||
viewingInfoFromDownloads,
|
||||
setManagingVersion,
|
||||
closePopup,
|
||||
setDownloadedVersionsConfig,
|
||||
setPopupMode,
|
||||
setSelectedVersionList,
|
||||
downloadVersions
|
||||
downloadVersions,
|
||||
versions
|
||||
} = useGlobal()
|
||||
const [versionSize, setVersionSize] = useState<number>(0)
|
||||
|
||||
@@ -43,10 +41,14 @@ export default function ManageVersionPopup () {
|
||||
})
|
||||
}, [managingVersion, setVersionSize, viewingInfoFromDownloads])
|
||||
|
||||
if (!managingVersion || !downloadedVersionsConfig) return <></>
|
||||
if (!managingVersion) return <></>
|
||||
|
||||
const versionInfo = getVersionInfo(managingVersion)
|
||||
const gameInfo = getGameInfo(versionInfo?.game)
|
||||
const versionInfo = serverVersionList?.versions.find(
|
||||
vf => vf.id == managingVersion
|
||||
)
|
||||
const gameInfo = serverVersionList?.games.find(
|
||||
vf => vf.id == versionInfo?.game
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -59,7 +61,7 @@ export default function ManageVersionPopup () {
|
||||
<p>
|
||||
Installed{' '}
|
||||
{new Intl.DateTimeFormat(undefined).format(
|
||||
downloadedVersionsConfig.list[managingVersion] ?? 0
|
||||
versionsList[managingVersion] ?? 0
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
@@ -135,18 +137,14 @@ export default function ManageVersionPopup () {
|
||||
onClick={async () => {
|
||||
closePopup()
|
||||
|
||||
setDownloadedVersionsConfig(prev => {
|
||||
if (!prev) return prev
|
||||
const updatedList = Object.fromEntries(
|
||||
Object.entries(prev.list).filter(([k]) => k !== managingVersion)
|
||||
versions?.set(
|
||||
'list',
|
||||
Object.fromEntries(
|
||||
Object.entries(versionsList).filter(
|
||||
([k]) => k !== managingVersion
|
||||
)
|
||||
)
|
||||
)
|
||||
const updatedConfig = {
|
||||
...prev,
|
||||
list: updatedList
|
||||
}
|
||||
writeVersionsConfig(updatedConfig)
|
||||
return updatedConfig
|
||||
})
|
||||
|
||||
if (
|
||||
await exists('game/' + managingVersion, {
|
||||
@@ -171,18 +169,14 @@ export default function ManageVersionPopup () {
|
||||
setPopupMode(1)
|
||||
|
||||
//uninstall
|
||||
setDownloadedVersionsConfig(prev => {
|
||||
if (!prev) return prev
|
||||
const updatedList = Object.fromEntries(
|
||||
Object.entries(prev.list).filter(([k]) => k !== managingVersion)
|
||||
versions?.set(
|
||||
'list',
|
||||
Object.fromEntries(
|
||||
Object.entries(versionsList).filter(
|
||||
([k]) => k !== managingVersion
|
||||
)
|
||||
)
|
||||
)
|
||||
const updatedConfig = {
|
||||
...prev,
|
||||
list: updatedList
|
||||
}
|
||||
writeVersionsConfig(updatedConfig)
|
||||
return updatedConfig
|
||||
})
|
||||
|
||||
if (
|
||||
await exists('game/' + managingVersion, {
|
||||
@@ -1,8 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { useGlobal } from '@/app/GlobalProvider'
|
||||
import { writeVersionsConfig } from '@/lib/BazookaManager'
|
||||
import { verifySignature } from '@/lib/Util'
|
||||
import { useGlobal } from '@/providers/GlobalProvider'
|
||||
import { verifySignature } from '@/lib/util'
|
||||
import { Mod } from '@/types/Mod'
|
||||
import {
|
||||
faArrowUpRightFromSquare,
|
||||
@@ -23,14 +22,14 @@ import { useEffect, useState } from 'react'
|
||||
|
||||
export default function ModDownloadsPopup () {
|
||||
const {
|
||||
getVersionInfo,
|
||||
modsList,
|
||||
serverVersionList,
|
||||
managingVersion,
|
||||
downloadedVersionsConfig,
|
||||
showModInfo,
|
||||
setShowModInfo,
|
||||
downloadVersions,
|
||||
downloadProgress,
|
||||
setDownloadedVersionsConfig
|
||||
versions
|
||||
} = useGlobal()
|
||||
|
||||
const [mods, setMods] = useState<Mod[] | 0 | 1>(0)
|
||||
@@ -52,9 +51,11 @@ export default function ModDownloadsPopup () {
|
||||
})()
|
||||
}, [managingVersion])
|
||||
|
||||
if (!managingVersion) return <></>
|
||||
if (!managingVersion || !serverVersionList) return <></>
|
||||
|
||||
const versionInfo = getVersionInfo(managingVersion)
|
||||
const versionInfo = serverVersionList.versions.find(
|
||||
v => v.id == managingVersion
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -110,10 +111,10 @@ export default function ModDownloadsPopup () {
|
||||
(!showModInfo &&
|
||||
mods.filter(v =>
|
||||
tab == 0
|
||||
? Object.keys(downloadedVersionsConfig?.mods ?? []).includes(
|
||||
? Object.keys(modsList).includes(
|
||||
String(versionInfo?.game + '-' + v.id)
|
||||
)
|
||||
: !Object.keys(downloadedVersionsConfig?.mods ?? []).includes(
|
||||
: !Object.keys(modsList).includes(
|
||||
String(versionInfo?.game + '-' + v.id)
|
||||
)
|
||||
).length == 0) ? (
|
||||
@@ -131,10 +132,10 @@ export default function ModDownloadsPopup () {
|
||||
{mods
|
||||
.filter(v =>
|
||||
tab == 0
|
||||
? Object.keys(downloadedVersionsConfig?.mods ?? []).includes(
|
||||
? Object.keys(modsList).includes(
|
||||
String(versionInfo?.game + '-' + v.id)
|
||||
)
|
||||
: !Object.keys(downloadedVersionsConfig?.mods ?? []).includes(
|
||||
: !Object.keys(modsList).includes(
|
||||
String(versionInfo?.game + '-' + v.id)
|
||||
)
|
||||
)
|
||||
@@ -142,9 +143,7 @@ export default function ModDownloadsPopup () {
|
||||
const localVersion =
|
||||
tab == 0
|
||||
? Object.keys(
|
||||
downloadedVersionsConfig?.mods?.[
|
||||
versionInfo?.game + '-' + v.id
|
||||
] ?? {}
|
||||
modsList[versionInfo?.game + '-' + v.id] ?? {}
|
||||
)[0]
|
||||
: null
|
||||
return (
|
||||
@@ -201,20 +200,14 @@ export default function ModDownloadsPopup () {
|
||||
baseDir: BaseDirectory.AppLocalData,
|
||||
recursive: true
|
||||
})
|
||||
setDownloadedVersionsConfig(prev => {
|
||||
if (!prev) return prev
|
||||
const updatedMods = Object.fromEntries(
|
||||
Object.entries(prev.mods).filter(
|
||||
versions?.set(
|
||||
'mods',
|
||||
Object.fromEntries(
|
||||
Object.entries(modsList).filter(
|
||||
([k]) => k !== versionInfo?.game + '-' + v.id
|
||||
)
|
||||
)
|
||||
const updatedConfig = {
|
||||
...prev,
|
||||
mods: updatedMods
|
||||
}
|
||||
writeVersionsConfig(updatedConfig)
|
||||
return updatedConfig
|
||||
})
|
||||
)
|
||||
|
||||
downloadVersions([
|
||||
{
|
||||
@@ -273,7 +266,7 @@ export default function ModDownloadsPopup () {
|
||||
: '(No description added)'}
|
||||
</div>
|
||||
<div className='flex flex-row h-fit w-full gap-2 justify-center my-2'>
|
||||
{Object.keys(downloadedVersionsConfig?.mods ?? []).includes(
|
||||
{Object.keys(modsList).includes(
|
||||
String(versionInfo?.game + '-' + showModInfo.id)
|
||||
) ? (
|
||||
<button
|
||||
@@ -294,21 +287,15 @@ export default function ModDownloadsPopup () {
|
||||
baseDir: BaseDirectory.AppLocalData,
|
||||
recursive: true
|
||||
})
|
||||
setDownloadedVersionsConfig(prev => {
|
||||
if (!prev) return prev
|
||||
const updatedMods = Object.fromEntries(
|
||||
Object.entries(prev.mods).filter(
|
||||
versions?.set(
|
||||
'mods',
|
||||
Object.fromEntries(
|
||||
Object.entries(modsList).filter(
|
||||
([k]) =>
|
||||
k !== versionInfo?.game + '-' + showModInfo.id
|
||||
)
|
||||
)
|
||||
const updatedConfig = {
|
||||
...prev,
|
||||
mods: updatedMods
|
||||
}
|
||||
writeVersionsConfig(updatedConfig)
|
||||
return updatedConfig
|
||||
})
|
||||
)
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faTrash} className='text-red-400' />{' '}
|
||||
@@ -1,22 +1,23 @@
|
||||
import { useGlobal } from '@/app/GlobalProvider'
|
||||
import { useGlobal } from '@/providers/GlobalProvider'
|
||||
import { faAdd, faInfo, faRemove } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
|
||||
export default function VersionsDownloadPopup () {
|
||||
const {
|
||||
serverVersionList,
|
||||
getSpecialVersionsList,
|
||||
selectedVersionList,
|
||||
setSelectedVersionList,
|
||||
setManagingVersion,
|
||||
setPopupMode,
|
||||
getSpecialVersionsList,
|
||||
selectedGame,
|
||||
setViewingInfoFromDownloads,
|
||||
downloadedVersionsConfig,
|
||||
downloadVersions,
|
||||
getGameInfo
|
||||
downloadVersions
|
||||
} = useGlobal()
|
||||
|
||||
if (!selectedGame) return <></>
|
||||
const game = serverVersionList?.games.find(g => g.id === selectedGame)
|
||||
|
||||
if (!selectedGame || !game) return <></>
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -78,7 +79,6 @@ export default function VersionsDownloadPopup () {
|
||||
<button
|
||||
className='button btntheme1 w-fit mt-2 -mb-4'
|
||||
onClick={() => {
|
||||
if (downloadedVersionsConfig) {
|
||||
downloadVersions(
|
||||
selectedVersionList.map(versionId => ({
|
||||
id: versionId,
|
||||
@@ -86,16 +86,11 @@ export default function VersionsDownloadPopup () {
|
||||
}))
|
||||
)
|
||||
setPopupMode(1)
|
||||
}
|
||||
}}
|
||||
disabled={selectedVersionList.length == 0}
|
||||
title={
|
||||
selectedVersionList.length == 0
|
||||
? 'Select at least one version to download'
|
||||
: `Download ${selectedVersionList.length} version${
|
||||
title={`Download ${selectedVersionList.length} version${
|
||||
selectedVersionList.length == 1 ? '' : 's'
|
||||
} of ${getGameInfo(selectedGame)?.name}`
|
||||
}
|
||||
} of ${game.name}`}
|
||||
>
|
||||
Download {selectedVersionList.length} version
|
||||
{selectedVersionList.length == 1 ? '' : 's'}
|
||||
@@ -8,12 +8,10 @@ import {
|
||||
SetStateAction
|
||||
} from 'react'
|
||||
import { DownloadProgress } from '@/types/DownloadProgress'
|
||||
import { VersionsConfig } from '@/types/VersionsConfig'
|
||||
import { ServerVersionsResponse } from '@/types/ServerVersionsResponse'
|
||||
import { GameVersion } from '@/types/GameVersion'
|
||||
import { Game } from '@/types/Game'
|
||||
import { Mod } from '@/types/Mod'
|
||||
import { Store } from '@tauri-apps/plugin-store'
|
||||
import { GameVersion } from '@/types/GameVersion'
|
||||
|
||||
type GlobalCtxType = {
|
||||
serverVersionList: ServerVersionsResponse | null
|
||||
@@ -27,18 +25,9 @@ type GlobalCtxType = {
|
||||
setPopupMode: Dispatch<SetStateAction<number | null>>
|
||||
fadeOut: boolean
|
||||
setFadeOut: Dispatch<SetStateAction<boolean>>
|
||||
downloadedVersionsConfig: VersionsConfig | null
|
||||
setDownloadedVersionsConfig: Dispatch<SetStateAction<VersionsConfig | null>>
|
||||
managingVersion: string | null
|
||||
setManagingVersion: Dispatch<SetStateAction<string | null>>
|
||||
setSelectedGame: Dispatch<SetStateAction<number | null>>
|
||||
getVersionInfo: (id: string | undefined) => GameVersion | undefined
|
||||
getGameInfo: (game: number | undefined) => Game | undefined
|
||||
getListOfGames(): Game[]
|
||||
getVersionsAmountData: (gameId: number) => {
|
||||
installed: number
|
||||
total: number
|
||||
} | null
|
||||
viewingInfoFromDownloads: boolean
|
||||
version: string | null
|
||||
downloadVersions: (
|
||||
@@ -56,17 +45,20 @@ type GlobalCtxType = {
|
||||
downloadQueue: string[]
|
||||
setDownloadQueue: Dispatch<SetStateAction<string[]>>
|
||||
closePopup: () => void
|
||||
getSpecialVersionsList(game?: number | undefined): GameVersion[]
|
||||
selectedGame: number | null
|
||||
setViewingInfoFromDownloads: Dispatch<SetStateAction<boolean>>
|
||||
showModInfo: Mod | null
|
||||
setShowModInfo: Dispatch<SetStateAction<Mod | null>>
|
||||
getSpecialVersionsList: (game?: number) => GameVersion[]
|
||||
settings: Store | null
|
||||
versions: Store | null
|
||||
notificationsAllowed: boolean
|
||||
sidebarAlwaysShowGames: boolean
|
||||
linuxUseWine: boolean
|
||||
linuxWineCommand: string
|
||||
theme: string
|
||||
versionsList: Record<string, number>
|
||||
modsList: Record<string, Record<string, number>>
|
||||
}
|
||||
|
||||
const GlobalCtx = createContext<GlobalCtxType | null>(null)
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,20 +0,0 @@
|
||||
export type VersionsConfigData = {
|
||||
version: string
|
||||
list: Record<string, number>
|
||||
mods: Record<string, Record<string, number>>
|
||||
}
|
||||
|
||||
export class VersionsConfig {
|
||||
constructor (
|
||||
public version: string,
|
||||
public list: Record<string, number> = {},
|
||||
public mods: Record<string, Record<string, number>> = {}
|
||||
) {}
|
||||
|
||||
static import (data: VersionsConfigData) {
|
||||
const cfg = new VersionsConfig(data.version)
|
||||
cfg.list = { ...data.list }
|
||||
cfg.mods = { ...data.mods }
|
||||
return cfg
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user