diff --git a/src/app/game/berrydash/leaderboards/page.tsx b/src/app/game/berrydash/leaderboards/page.tsx index 75f72a0..d8bf5dc 100644 --- a/src/app/game/berrydash/leaderboards/page.tsx +++ b/src/app/game/berrydash/leaderboards/page.tsx @@ -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 diff --git a/src/app/game/page.tsx b/src/app/game/page.tsx index 251f19f..0a43420 100644 --- a/src/app/game/page.tsx +++ b/src/app/game/page.tsx @@ -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 (
{(() => { 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,44 +175,40 @@ export default function Installs () {
) })} - {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 - }) - .filter(v => { - const info = getVersionInfo(v) - if (!info) return false - if (platform() == 'linux' && info.wine && !linuxUseWine) - return false - return ( - info.game === id && - (category == -1 - ? info.category == -1 - : info.category == category) - ) - }) - .map(entry => ( + {Object.keys(versionsList) + .filter(v => { + const info = serverVersionList?.versions.find(vf => vf.id == v) + if (!info) return false + if (platform() == 'linux' && info.wine && !linuxUseWine) + return false + return ( + info.game === id && + (category == -1 + ? info.category == -1 + : info.category == category) + ) + }) + .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 (
{ - 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) }} >
-

- {getVersionInfo(entry)?.displayName}{' '} -

+

{versionInfo.displayName}

Installed{' '} {new Intl.DateTimeFormat(undefined).format( - downloadedVersionsConfig?.list[entry] + versionsList[v] )}

@@ -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) } > @@ -340,10 +313,7 @@ export default function Installs () {
- )) - ) : ( -
-

No versions installed

-
- )} + ) + })}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx index bc45f6e..d5cb8e4 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -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) const [selectedVersionList, setSelectedVersionList] = useState([]) - const [downloadedVersionsConfig, setDownloadedVersionsConfig] = - useState(null) - const [showPopup, setShowPopup] = useState(false) const [popupMode, setPopupMode] = useState(null) const [fadeOut, setFadeOut] = useState(false) @@ -85,6 +79,7 @@ export default function RootLayout ({ const revisionCheck = useRef(false) const [settings, setSettings] = useState(null) + const [versions, setVersions] = useState(null) const [notificationsAllowed, setNotificationsAllowed] = useState(false) @@ -95,13 +90,16 @@ export default function RootLayout ({ useState('wine %path%') const [theme, setTheme] = useState('dark') + const [versionsList, setVersionsList] = useState>({}) + const [modsList, setModsList] = useState< + Record> + >({}) + 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() - - 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, - [downloadInfo.modGame! + '-' + downloadInfo.modId!]: { - [downloadInfo.modVersion!]: Date.now() - } - } - } - : { - ...prev, - list: { - ...prev.list, - [versionId]: Date.now() - } - } - - writeVersionsConfig(updated) - return updated - }) + if (downloadInfo.type == 2) { + versions?.set('mods', { + ...modsList, + [downloadInfo.modGame! + '-' + downloadInfo.modId!]: { + [downloadInfo.modVersion!]: Date.now() + } + }) + } 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 (key: string, fn: (v: T | undefined) => void) { + function watchSettings (key: string, fn: (v: T | undefined) => void) { settings!.get(key).then(fn) unlisteners.push(settings!.onKeyChange(key, fn)) } - watch('theme', v => setTheme(v ?? 'dark')) - watch('notificationsAllowed', v => + function watchVersions (key: string, fn: (v: T | undefined) => void) { + versions!.get(key).then(fn) + unlisteners.push(versions!.onKeyChange(key, fn)) + } + + watchSettings('theme', v => setTheme(v ?? 'dark')) + watchSettings('notificationsAllowed', v => setNotificationsAllowed(v ?? true) ) - watch('sidebarAlwaysShowGames', v => + watchSettings('sidebarAlwaysShowGames', v => setSidebarAlwaysShowGames(v ?? true) ) - watch('linuxUseWine', v => setLinuxUseWine(v ?? false)) - watch('linuxWineCommand', v => + watchSettings('linuxUseWine', v => setLinuxUseWine(v ?? false)) + watchSettings('linuxWineCommand', v => setLinuxWineCommand(v ?? 'wine %path%') ) + watchVersions>('list', v => setVersionsList(v ?? {})) + watchVersions>>('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 }} >
- {downloadedVersionsConfig && - Object.keys(downloadedVersionsConfig.list).length ? ( - getListOfGames() - .sort((a, b) => { - return a.id - b.id - }) - .map(i => ( -
{ - setCategory(-1) - router.push('/game?id=' + i.id) - }} - > -
-

{i.name}

+ {serverVersionList?.games + .filter(g => + serverVersionList.versions + .filter(v => v.game === g.id) + .some(v => Object.keys(versionsList).includes(v.id)) + ) + .map(i => ( +
{ + setCategory(-1) + router.push('/game?id=' + i.id) + }} + > +
+

{i.name}

-
-
e.stopPropagation()} - > -

- {(() => { - const data = getVersionsAmountData(i.id) - if (!data) return 'N/A' - return `${data.installed}/${data.total}` - })()}{' '} - versions installed -

-
- - +
+
e.stopPropagation()} + > +

+ {(() => { + 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 +

+
+ +
- )) - ) : ( -
-

No games installed

-
- )} +
+ ))}
diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx index a6545b0..b40a0f7 100644 --- a/src/app/settings/page.tsx +++ b/src/app/settings/page.tsx @@ -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 () { diff --git a/src/components/Setting.tsx b/src/components/Setting.tsx index b889348..864afc3 100644 --- a/src/components/Setting.tsx +++ b/src/components/Setting.tsx @@ -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' diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 817eaa5..9bc9fef 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -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 () { > Games - {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 => (
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) diff --git a/src/lib/BazookaManager.ts b/src/lib/BazookaManager.ts deleted file mode 100644 index 39e2934..0000000 --- a/src/lib/BazookaManager.ts +++ /dev/null @@ -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 { - 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 - ) - } -} diff --git a/src/lib/Clipboard.ts b/src/lib/Clipboard.ts index ee93c9a..3a8d4af 100644 --- a/src/lib/Clipboard.ts +++ b/src/lib/Clipboard.ts @@ -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, diff --git a/src/lib/BerryDash.ts b/src/lib/berrydashutil.ts similarity index 100% rename from src/lib/BerryDash.ts rename to src/lib/berrydashutil.ts diff --git a/src/components/popups/Downloads.tsx b/src/popups/Downloads.tsx similarity index 85% rename from src/components/popups/Downloads.tsx rename to src/popups/Downloads.tsx index 09423ff..c9020d0 100644 --- a/src/components/popups/Downloads.tsx +++ b/src/popups/Downloads.tsx @@ -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, - [v.modGame! + '-' + v.modId!]: { - [v.modVersion!]: Date.now() - } - } - } - : { - ...prev, - list: { - ...prev.list, - [v.version]: Date.now() - } - } - - writeVersionsConfig(updated) - return updated - }) + if (v.type == 2) { + versions?.set('mods', { + ...modsList, + [v.modGame! + '-' + v.modId!]: { + [v.modVersion!]: Date.now() + } + }) + } 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 () {

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

{v.failed || v.queued ? ( diff --git a/src/components/popups/GamesDownload.tsx b/src/popups/GamesDownload.tsx similarity index 75% rename from src/components/popups/GamesDownload.tsx rename to src/popups/GamesDownload.tsx index 64dcbca..095dc15 100644 --- a/src/components/popups/GamesDownload.tsx +++ b/src/popups/GamesDownload.tsx @@ -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 ( <>

Select a game to download

{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) => (
@@ -32,9 +32,15 @@ export default function GamesDownloadPopup () { >

{(() => { - 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

@@ -74,11 +80,7 @@ export default function GamesDownloadPopup () {
@@ -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, { diff --git a/src/components/popups/ModDownloads.tsx b/src/popups/ModDownloads.tsx similarity index 86% rename from src/components/popups/ModDownloads.tsx rename to src/popups/ModDownloads.tsx index 7862dbb..266e2fe 100644 --- a/src/components/popups/ModDownloads.tsx +++ b/src/popups/ModDownloads.tsx @@ -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(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)'}
- {Object.keys(downloadedVersionsConfig?.mods ?? []).includes( + {Object.keys(modsList).includes( String(versionInfo?.game + '-' + showModInfo.id) ) ? (