diff --git a/backend/src/server.py b/backend/src/server.py index 4485ee300..bbe550d39 100644 --- a/backend/src/server.py +++ b/backend/src/server.py @@ -432,7 +432,17 @@ async def get_dependencies(_request: Request): await nodes_available() all_dependencies = [] for package in api.registry.packages.values(): - pkg_dependencies = [x.toDict() for x in package.dependencies] + pkg_dependencies = [] + for pkg_dep in package.dependencies: + installed_version = installed_packages.get(pkg_dep.pypi_name, None) + pkg_dep_item = { + **pkg_dep.toDict(), + } + if installed_version is None: + pkg_dep_item["installed"] = None + else: + pkg_dep_item["installed"] = installed_version + pkg_dependencies.append(pkg_dep_item) if package.name == "chaiNNer_standard": continue else: diff --git a/src/common/dependencies.ts b/src/common/dependencies.ts index 311630bf7..39818312c 100644 --- a/src/common/dependencies.ts +++ b/src/common/dependencies.ts @@ -10,6 +10,7 @@ export interface PyPiPackage { */ sizeEstimate: number; autoUpdate: boolean; + installed: Version | null; } export interface Package { name: string; diff --git a/src/renderer/contexts/DependencyContext.tsx b/src/renderer/contexts/DependencyContext.tsx index 675ba7562..a8e0b3448 100644 --- a/src/renderer/contexts/DependencyContext.tsx +++ b/src/renderer/contexts/DependencyContext.tsx @@ -32,12 +32,13 @@ import { } from '@chakra-ui/react'; import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { BsQuestionCircle, BsTerminalFill } from 'react-icons/bs'; +import { useQuery } from 'react-query'; import { createContext, useContext } from 'use-context-selector'; import { Version } from '../../common/common-types'; import { Package, PyPiPackage } from '../../common/dependencies'; import { Integration, externalIntegrations } from '../../common/externalIntegrations'; import { log } from '../../common/log'; -import { OnStdio, PipList, runPipInstall, runPipList, runPipUninstall } from '../../common/pip'; +import { OnStdio, runPipInstall, runPipUninstall } from '../../common/pip'; import { noop } from '../../common/util'; import { versionGt } from '../../common/version'; import { useAsyncEffect } from '../hooks/useAsyncEffect'; @@ -76,7 +77,7 @@ const formatSizeEstimate = (packages: readonly PyPiPackage[]): string => formatBytes(packages.reduce((a, p) => a + p.sizeEstimate, 0)); const FeaturePackage = memo( - ({ pkg, installedVersion }: { pkg: PyPiPackage; installedVersion?: Version }) => { + ({ pkg, installedVersion }: { pkg: PyPiPackage; installedVersion: Version | null }) => { let color = 'red.500'; let tagText = 'Missing'; let versionString: string = pkg.version; @@ -115,7 +116,6 @@ const FeaturePackage = memo( const Feature = memo( ({ dep, - pipList, isRunningShell, progress, onInstall, @@ -123,17 +123,15 @@ const Feature = memo( onUpdate, }: { dep: Package; - pipList: PipList; isRunningShell: boolean; progress?: number; onInstall: () => void; onUninstall: () => void; onUpdate: () => void; }) => { - const missingPackages = dep.dependencies.filter((p) => !pipList[p.pypiName]); - const outdatedPackages = dep.dependencies.filter((p) => { - const installedVersion = pipList[p.pypiName]; - return installedVersion && versionGt(p.version, installedVersion); + const missingPackages = dep.dependencies.filter((d) => !d.installed); + const outdatedPackages = dep.dependencies.filter((d) => { + return d.installed && versionGt(d.version, d.installed); }); return ( @@ -255,11 +253,11 @@ const Feature = memo( key={dep.name} w="full" > - {dep.dependencies.map((p) => ( + {dep.dependencies.map((d) => ( ))} @@ -279,20 +277,9 @@ export const DependencyProvider = memo(({ children }: React.PropsWithChildren(); - const refreshInstalledPackages = useCallback(() => setPipList(undefined), [setPipList]); - const [isConsoleOpen, setIsConsoleOpen] = useState(false); const [usePipDirectly, setUsePipDirectly] = useState(false); - useAsyncEffect(() => { - if (pipList) return; - return { - supplier: () => runPipList(pythonInfo), - successEffect: setPipList, - }; - }, [pythonInfo, pipList, setPipList]); - const [hasNvidia, setHasNvidia] = useState(false); useAsyncEffect( () => ({ @@ -302,17 +289,22 @@ export const DependencyProvider = memo(({ children }: React.PropsWithChildren([]); - useAsyncEffect( - () => ({ - supplier: async () => { - const res = await backend.dependencies(); - return res.filter((d) => d.dependencies.length > 0); - }, - successEffect: setAvailableDeps, - }), - [backend] - ); + const { data: depList, refetch } = useQuery({ + queryKey: 'dependencies', + queryFn: async () => { + try { + const response = await backend.dependencies(); + return response.filter((d) => d.dependencies.length > 0); + } catch (error) { + log.error(error); + throw error; + } + }, + cacheTime: 0, + retry: 25, + refetchOnWindowFocus: false, + refetchInterval: false, + }); const [installingPackage, setInstallingPackage] = useState(null); const [uninstallingPackage, setUninstallingPackage] = useState(null); @@ -341,12 +333,20 @@ export const DependencyProvider = memo(({ children }: React.PropsWithChildren { - setIsRunningShell(false); - refreshInstalledPackages(); - setInstallingPackage(null); - setUninstallingPackage(null); - setProgress(0); - restart().catch(log.error); + restart() + .catch(log.error) + .then(() => { + refetch() + .catch(log.error) + .then(() => { + setIsRunningShell(false); + setInstallingPackage(null); + setUninstallingPackage(null); + setProgress(0); + }) + .catch(log.error); + }) + .catch(log.error); }); }; @@ -372,22 +372,20 @@ export const DependencyProvider = memo(({ children }: React.PropsWithChildren { - return availableDeps.filter(({ dependencies }) => - dependencies.some(({ pypiName, version }) => { - if (!pipList) { - return false; - } - const installedVersion = pipList[pypiName]; - if (!installedVersion) { - return true; - } - return versionGt(version, installedVersion); - }) - ).length; - }, [pipList, availableDeps]); + return ( + depList?.filter(({ dependencies }) => + dependencies.some(({ version, installed }) => { + if (!installed) { + return true; + } + return versionGt(version, installed); + }) + ).length ?? 0 + ); + }, [depList]); const value = useMemoObject({ openDependencyManager: onOpen, @@ -496,7 +494,7 @@ export const DependencyProvider = memo(({ children }: React.PropsWithChildren - {!pipList ? ( + {!depList ? ( ) : ( - {availableDeps.map((dep) => { + {depList.map((dep) => { const install = () => installPackage(dep); const uninstall = () => { showAlert({ @@ -540,7 +538,6 @@ export const DependencyProvider = memo(({ children }: React.PropsWithChildren