Skip to content

Commit

Permalink
Migrate libraryStatus and make it a Record
Browse files Browse the repository at this point in the history
This was definitely the biggest change yet. Most of it was just taking a
`runner` everywhere (to build a key to index into the record)

This still has one issue (the library isn't refreshed after a game
install/update finishes), it'll be resolved by future commits. Still, this
should be a noticeable speed boost
  • Loading branch information
CommandMC committed Jun 18, 2024
1 parent 5895401 commit 407c18a
Show file tree
Hide file tree
Showing 21 changed files with 166 additions and 200 deletions.
18 changes: 12 additions & 6 deletions src/backend/__tests__/progress_bar.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ describe('progress_bar', () => {
it('does nothing', () => {
sendGameStatusUpdate({
appName: 'Test',
status: 'queued'
status: 'queued',
runner: 'legendary'
})

expect(window.setProgressBar).not.toBeCalled()
Expand All @@ -43,7 +44,8 @@ describe('progress_bar', () => {
it('sets progress bar to indeterminate', () => {
sendGameStatusUpdate({
appName: 'Test',
status: 'installing'
status: 'installing',
runner: 'legendary'
})

expect(window.setProgressBar).toBeCalledWith(2)
Expand All @@ -54,7 +56,8 @@ describe('progress_bar', () => {

sendGameStatusUpdate({
appName: 'Test',
status: 'installing'
status: 'installing',
runner: 'legendary'
})

expect(backendEvents.on).toBeCalledWith(
Expand All @@ -69,7 +72,8 @@ describe('progress_bar', () => {
sendProgressUpdate({
appName: 'Test',
status: 'installing',
progress: { percent: 42, bytes: '', eta: '' }
progress: { percent: 42, bytes: '', eta: '' },
runner: 'legendary'
})

expect(window.setProgressBar).toBeCalledWith(0.42)
Expand All @@ -80,7 +84,8 @@ describe('progress_bar', () => {
it('removes the progress bar', () => {
sendGameStatusUpdate({
appName: 'Test',
status: 'done'
status: 'done',
runner: 'legendary'
})

expect(window.setProgressBar).toBeCalledWith(-1)
Expand All @@ -91,7 +96,8 @@ describe('progress_bar', () => {

sendGameStatusUpdate({
appName: 'Test',
status: 'done'
status: 'done',
runner: 'legendary'
})

expect(backendEvents.off).toBeCalledWith(
Expand Down
13 changes: 9 additions & 4 deletions src/backend/api/downloadmanager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { DownloadManagerState } from './../../common/types'
import {
DownloadManagerState,
Runner,
DMQueueElement,
InstallParams,
UpdateParams
} from 'common/types'
import { ipcRenderer } from 'electron'
import { DMQueueElement, InstallParams, UpdateParams } from 'common/types'

export const install = async (args: InstallParams) => {
const dmQueueElement: DMQueueElement = {
Expand Down Expand Up @@ -57,8 +62,8 @@ export const updateGame = (args: UpdateParams) => {
export const getDMQueueInformation = async () =>
ipcRenderer.invoke('getDMQueueInformation')

export const removeFromDMQueue = (appName: string) =>
ipcRenderer.send('removeFromDMQueue', appName)
export const removeFromDMQueue = (appName: string, runner: Runner) =>
ipcRenderer.send('removeFromDMQueue', appName, runner)

export const handleDMQueueInformation = (
onChange: (
Expand Down
16 changes: 11 additions & 5 deletions src/backend/downloadmanager/downloadqueue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import { gameManagerMap, libraryManagerMap } from 'backend/storeManagers'
import { TypeCheckedStoreBackend } from './../electron_store'
import { logError, logInfo, LogPrefix, logWarning } from '../logger/logger'
import { getFileSize, removeFolder, sendGameStatusUpdate } from '../utils'
import { DMQueueElement, DMStatus, DownloadManagerState } from 'common/types'
import {
DMQueueElement,
DMStatus,
DownloadManagerState,
Runner
} from 'common/types'
import { installQueueElement, updateQueueElement } from './utils'
import { sendFrontendMessage } from '../main_window'
import { callAbortController } from 'backend/utils/aborthandler/aborthandler'
Expand Down Expand Up @@ -89,7 +94,7 @@ async function initQueue() {

if (!isPaused()) {
addToFinished(element, status)
removeFromQueue(element.params.appName)
removeFromQueue(element.params.appName, element.params.runner)
element = getFirstQueueElement()
} else {
element = null
Expand Down Expand Up @@ -178,7 +183,7 @@ async function addToQueue(element: DMQueueElement) {
}
}

function removeFromQueue(appName: string) {
function removeFromQueue(appName: string, runner: Runner) {
if (appName && downloadManager.has('queue')) {
const elements = downloadManager.get('queue', [])
const index = elements.findIndex(
Expand All @@ -192,6 +197,7 @@ function removeFromQueue(appName: string) {

sendGameStatusUpdate({
appName,
runner,
status: 'done'
})

Expand All @@ -216,13 +222,13 @@ function cancelCurrentDownload({ removeDownloaded = false }) {
if (Array.isArray(currentElement.params.installDlcs)) {
const dlcsToRemove = currentElement.params.installDlcs
for (const dlc of dlcsToRemove) {
removeFromQueue(dlc)
removeFromQueue(dlc, currentElement.params.runner)
}
}
if (isRunning()) {
stopCurrentDownload()
}
removeFromQueue(currentElement.params.appName)
removeFromQueue(currentElement.params.appName, currentElement.params.runner)

if (removeDownloaded) {
const { appName, runner } = currentElement!.params
Expand Down
4 changes: 2 additions & 2 deletions src/backend/downloadmanager/ipc_handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ ipcMain.handle('addToDMQueue', async (e, element) => {
await addToQueue(element)
})

ipcMain.on('removeFromDMQueue', (e, appName) => {
removeFromQueue(appName)
ipcMain.on('removeFromDMQueue', (e, appName, runner) => {
removeFromQueue(appName, runner)
})

ipcMain.on('resumeCurrentDownload', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/common/typedefs/ipcBridge.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ interface SyncIPCFunctions {
showLogFileInFolder: (appNameOrRunner: string) => void
addShortcut: (appName: string, runner: Runner, fromMenu: boolean) => void
removeShortcut: (appName: string, runner: Runner) => void
removeFromDMQueue: (appName: string) => void
removeFromDMQueue: (appName: string, runner: Runner) => void
clearDMFinished: () => void
abort: (id: string) => void
'connectivity-changed': (newStatus: ConnectivityStatus) => void
Expand Down
4 changes: 2 additions & 2 deletions src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,11 @@ export type Status =

export interface GameStatus {
appName: string
runner: Runner
status: Status
progress?: InstallProgress
folder?: string
context?: string // Additional context e.g current step
runner?: Runner
status: Status
}

export type GlobalConfigVersion = 'auto' | 'v0'
Expand Down
8 changes: 6 additions & 2 deletions src/frontend/components/UI/DLCList/DLC/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import DownIcon from 'frontend/assets/down-icon.svg?react'
import StopIcon from 'frontend/assets/stop-icon.svg?react'
import StopIconAlt from 'frontend/assets/stop-icon-alt.svg?react'
import SvgButton from '../../SvgButton'
import { useGlobalState } from 'frontend/state/GlobalStateV2'
import { useShallow } from 'zustand/react/shallow'

type Props = {
dlc: DLCInfo
Expand All @@ -23,7 +25,10 @@ type Props = {

const DLC = ({ dlc, runner, mainAppInfo, onClose }: Props) => {
const { title, app_name } = dlc
const { libraryStatus, showDialogModal } = useContext(ContextProvider)
const { showDialogModal } = useContext(ContextProvider)
const currentApp = useGlobalState(
useShallow((state) => state.libraryStatus[`${app_name}_${runner}`])
)
const { t } = useTranslation('gamepage')
const [showUninstallModal, setShowUninstallModal] = useState(false)
const [dlcInfo, setDlcInfo] = useState<GameInfo | null>(null)
Expand Down Expand Up @@ -64,7 +69,6 @@ const DLC = ({ dlc, runner, mainAppInfo, onClose }: Props) => {
getDlcSize()
}, [dlc, runner])

const currentApp = libraryStatus.find((app) => app.appName === app_name)
const isInstalling = currentApp?.status === 'installing'
const showInstallButton = !isInstalling && !refreshing

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext, useEffect, useState } from 'react'
import React, { useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
import LinearProgress from '@mui/material/LinearProgress'
import Typography from '@mui/material/Typography'
Expand All @@ -10,7 +10,6 @@ import { hasProgress } from 'frontend/hooks/hasProgress'
import { Runner } from 'common/types'
import './index.scss'
import { useTranslation } from 'react-i18next'
import ContextProvider from 'frontend/state/ContextProvider'
import Badge from '@mui/material/Badge'

type Props = {
Expand All @@ -21,7 +20,6 @@ type Props = {
export default React.memo(function CurrentDownload({ appName, runner }: Props) {
const [progress] = hasProgress(appName)
const [gameTitle, setGameTitle] = useState('')
const { libraryStatus } = useContext(ContextProvider)
const { t } = useTranslation()

useEffect(() => {
Expand All @@ -47,10 +45,6 @@ export default React.memo(function CurrentDownload({ appName, runner }: Props) {
: t('status.installing', 'Installing')
}

if (!libraryStatus.length) {
return null
}

return (
<>
<Link to={`/download-manager`} className="currentDownload">
Expand Down
14 changes: 11 additions & 3 deletions src/frontend/components/UI/UninstallModal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import './index.scss'
import React, { useContext, useEffect, useState } from 'react'
import React, { useEffect, useState } from 'react'
import {
Dialog,
DialogContent,
Expand All @@ -10,7 +10,8 @@ import { useTranslation } from 'react-i18next'
import { Runner } from 'common/types'
import ToggleSwitch from '../ToggleSwitch'
import { useNavigate, useLocation } from 'react-router-dom'
import ContextProvider from 'frontend/state/ContextProvider'
import { useGlobalState } from 'frontend/state/GlobalStateV2'
import { useShallow } from 'zustand/react/shallow'

interface UninstallModalProps {
appName: string
Expand All @@ -34,7 +35,14 @@ const UninstallModal: React.FC<UninstallModalProps> = function ({
const [showUninstallModal, setShowUninstallModal] = useState(false)
const navigate = useNavigate()
const location = useLocation()
const { installingEpicGame } = useContext(ContextProvider)
const installingEpicGame = useGlobalState(
useShallow((state) =>
Object.values(state.libraryStatus).some(
(status) =>
status.runner === 'legendary' && status.status === 'installing'
)
)
)
const [gameTitle, setGameTitle] = useState('')

const checkIfIsNative = async () => {
Expand Down
24 changes: 12 additions & 12 deletions src/frontend/hooks/hasStatus.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
import React from 'react'
import { useContext, useEffect, useState } from 'react'
import ContextProvider from 'frontend/state/ContextProvider'
import { GameInfo, GameStatus, Status } from 'common/types'
import { GameInfo, Status } from 'common/types'
import { hasProgress } from './hasProgress'
import { useTranslation } from 'react-i18next'
import { getStatusLabel, handleNonAvailableGames } from './constants'
import { useGlobalState } from '../state/GlobalStateV2'
import { useShallow } from 'zustand/react/shallow'

export function hasStatus(
appName: string,
gameInfo: GameInfo,
gameSize?: string
) {
const { libraryStatus, epic, gog } = React.useContext(ContextProvider)
const { epic, gog } = useContext(ContextProvider)
const thisStatus = useGlobalState(
useShallow((state) => state.libraryStatus[`${appName}_${gameInfo.runner}`])
)
const [progress] = hasProgress(appName)
const { t } = useTranslation('gamepage')

const [gameStatus, setGameStatus] = React.useState<{
const [gameStatus, setGameStatus] = useState<{
status?: Status
statusContext?: string
folder?: string
Expand All @@ -28,14 +33,9 @@ export function hasStatus(
isEAManaged
} = { ...gameInfo }

React.useEffect(() => {
useEffect(() => {
const checkGameStatus = async () => {
const {
status,
folder,
context: statusContext
} = libraryStatus.find((game: GameStatus) => game.appName === appName) ||
{}
const { status, folder, context: statusContext } = thisStatus ?? {}

if (status && status !== 'done') {
const label = getStatusLabel({
Expand Down Expand Up @@ -90,7 +90,7 @@ export function hasStatus(
}
checkGameStatus()
}, [
libraryStatus,
thisStatus,
appName,
epic.library,
gog.library,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ const DownloadManagerItem = ({
handleClearItem && handleClearItem(appName)
}

current ? stopInstallation() : window.api.removeFromDMQueue(appName)
current ? stopInstallation() : window.api.removeFromDMQueue(appName, runner)
}

// using one element for the different states so it doesn't
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/screens/Game/GamePage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ export default React.memo(function GamePage(): JSX.Element | null {
async function handleInstall(is_installed: boolean) {
if (isQueued) {
storage.removeItem(appName)
return window.api.removeFromDMQueue(appName)
return window.api.removeFromDMQueue(appName, runner)
}

if (!is_installed && !isInstalling) {
Expand Down
Loading

0 comments on commit 407c18a

Please sign in to comment.