Skip to content

Commit aedd478

Browse files
author
colinmcneil
committed
Decouple query states out of context provider
- Catalog/Registry - Config - MCP Clients - Image loading
1 parent 87917a2 commit aedd478

File tree

10 files changed

+1076
-126
lines changed

10 files changed

+1076
-126
lines changed

src/extension/ui/src/App.tsx

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ import { CatalogItemWithName } from './types/catalog';
55
import { Close } from '@mui/icons-material';
66
import { CatalogGrid } from './components/CatalogGrid';
77
import { POLL_INTERVAL } from './Constants';
8-
import { CatalogProvider, useCatalogContext } from './context/CatalogContext';
9-
import { ConfigProvider } from './context/ConfigContext';
10-
import { MCPClientProvider, useMCPClientContext } from './context/MCPClientContext';
11-
import { RequiredImagesProvider, useRequiredImagesContext } from './context/RequiredImageContext';
128
import ConfigurationModal from './components/tile/Modal';
139
import LoadingState from './components/LoadingState';
10+
import { useCatalogAll } from './hooks/useCatalog';
11+
import { useRequiredImages } from './hooks/useRequiredImages';
12+
import { useMCPClient } from './hooks/useMCPClient';
13+
import { useConfig } from './hooks/useConfig';
1414

1515
export const client = createDockerDesktopClient();
1616

@@ -22,44 +22,40 @@ const DEFAULT_SETTINGS = {
2222
export function App() {
2323
const [settings, setSettings] = useState<{ showModal: boolean, pollIntervalSeconds: number }>(localStorage.getItem('settings') ? JSON.parse(localStorage.getItem('settings') || '{}') : DEFAULT_SETTINGS);
2424
const [configuringItem, setConfiguringItem] = useState<CatalogItemWithName | null>(null);
25-
// Wrap the entire application with our providers
26-
return (
27-
<ConfigProvider client={client}>
28-
<RequiredImagesProvider client={client}>
29-
<CatalogProvider client={client}>
30-
<MCPClientProvider client={client}>
31-
<AppContent
32-
settings={settings}
33-
setSettings={setSettings}
34-
configuringItem={configuringItem}
35-
setConfiguringItem={setConfiguringItem}
36-
/>
37-
</MCPClientProvider>
38-
</CatalogProvider>
39-
</RequiredImagesProvider>
40-
</ConfigProvider>
41-
);
42-
}
4325

44-
interface AppContentProps {
45-
settings: { showModal: boolean, pollIntervalSeconds: number };
46-
setSettings: React.Dispatch<React.SetStateAction<{ showModal: boolean, pollIntervalSeconds: number }>>;
47-
configuringItem: CatalogItemWithName | null;
48-
setConfiguringItem: React.Dispatch<React.SetStateAction<CatalogItemWithName | null>>;
49-
}
26+
// Use hooks directly in the component
27+
const catalogAll = useCatalogAll(client);
28+
const requiredImages = useRequiredImages(client);
29+
const mcpClient = useMCPClient(client);
30+
const config = useConfig(client);
31+
32+
// Create a context-like combined props object to pass to children
33+
const appProps = {
34+
// Catalog related props
35+
...catalogAll,
36+
37+
// Required images props
38+
...requiredImages,
39+
40+
// MCP Client props
41+
...mcpClient,
5042

51-
function AppContent({ settings, setSettings, setConfiguringItem }: AppContentProps) {
52-
const { secretsLoading, catalogLoading, registryLoading } = useCatalogContext();
53-
const { isLoading: imagesLoading } = useRequiredImagesContext();
43+
// Config props
44+
...config
45+
};
5446

55-
const isLoading = secretsLoading || catalogLoading || registryLoading || imagesLoading;
47+
const isLoading = catalogAll.secretsLoading ||
48+
catalogAll.catalogLoading ||
49+
catalogAll.registryLoading ||
50+
requiredImages.isLoading;
5651

5752
return (
5853
<>
5954
{isLoading ? (
60-
<LoadingState />
55+
<LoadingState appProps={appProps} />
6156
) : (
6257
<CatalogGrid
58+
appProps={appProps}
6359
setConfiguringItem={setConfiguringItem}
6460
showSettings={() => setSettings({ ...settings, showModal: true })}
6561
/>

src/extension/ui/src/components/CatalogGrid.tsx

Lines changed: 16 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
import React, { Suspense, useEffect, useState } from 'react';
22
import { IconButton, Alert, AlertTitle, Stack, Button, Typography, FormGroup, FormControlLabel, Dialog, DialogTitle, DialogContent, Checkbox, Badge, TextField, Tabs, Tab, CircularProgress, Box, Menu, Divider, Switch, MenuItem } from '@mui/material';
33
import { SwapVert, FolderOpenRounded } from '@mui/icons-material';
4-
import { useCatalogContext } from '../context/CatalogContext';
5-
import { useMCPClientContext } from '../context/MCPClientContext';
6-
import { useConfigContext } from '../context/ConfigContext';
74
import { createDockerDesktopClient } from '@docker/extension-api-client';
85
import { ExecResult } from '@docker/extension-api-client-types/dist/v0';
96
import YourClients from './tabs/YourClients';
107
import { CatalogItemWithName } from '../types/catalog';
118
import { CATALOG_LAYOUT_SX } from '../Constants';
9+
import { MCPClientState } from '../MCPClients';
1210

1311
const ToolCatalog = React.lazy(() => import('./tabs/ToolCatalog'));
1412
const YourEnvironment = React.lazy(() => import('./tabs/YourEnvironment'));
@@ -17,6 +15,7 @@ const YourEnvironment = React.lazy(() => import('./tabs/YourEnvironment'));
1715
const client = createDockerDesktopClient();
1816

1917
interface CatalogGridProps {
18+
appProps: any; // We'll use this to pass all our hook data
2019
showSettings: () => void;
2120
setConfiguringItem: (item: CatalogItemWithName) => void;
2221
}
@@ -32,26 +31,22 @@ const parseDDVersion = (ddVersion: string) => {
3231
const NEVER_SHOW_AGAIN_KEY = 'registry-sync-never-show-again';
3332

3433
export const CatalogGrid: React.FC<CatalogGridProps> = ({
34+
appProps,
3535
setConfiguringItem,
3636
}) => {
37+
// Extract all the values we need from appProps
3738
const {
3839
catalogItems,
3940
registryItems,
4041
canRegister,
4142
registerCatalogItem,
4243
unregisterCatalogItem,
4344
tryUpdateSecrets,
44-
secrets
45-
} = useCatalogContext();
46-
47-
const {
45+
secrets,
4846
mcpClientStates,
49-
isLoading: mcpLoading
50-
} = useMCPClientContext();
51-
52-
const {
47+
isLoading: mcpLoading,
5348
config
54-
} = useConfigContext();
49+
} = appProps;
5550

5651
const [showReloadModal, setShowReloadModal] = useState<boolean>(false);
5752
const [search, setSearch] = useState<string>('');
@@ -91,7 +86,7 @@ export const CatalogGrid: React.FC<CatalogGridProps> = ({
9186
}
9287

9388
const hasOutOfCatalog = catalogItems.length > 0 && Object.keys(registryItems).length > 0 && !Object.keys(registryItems).every((i) =>
94-
catalogItems.some((c) => c.name === i)
89+
catalogItems.some((c: CatalogItemWithName) => c.name === i)
9590
)
9691

9792
const sortedCatalogItems = sort !== 'date-desc' ? [...catalogItems].sort((a, b) => {
@@ -111,7 +106,11 @@ export const CatalogGrid: React.FC<CatalogGridProps> = ({
111106
</>
112107
}
113108

114-
const noConfiguredClients = !mcpLoading && !Object.values(mcpClientStates || {}).some(state => state.exists && state.configured);
109+
// Check if there are any configured clients
110+
const noConfiguredClients = !mcpLoading && mcpClientStates ?
111+
!Object.values(mcpClientStates as Record<string, MCPClientState>).some(state =>
112+
state.exists && state.configured
113+
) : false;
115114

116115
return (
117116
<>
@@ -186,12 +185,6 @@ export const CatalogGrid: React.FC<CatalogGridProps> = ({
186185
}} disableRipple>
187186
⏰ Most Recent
188187
</MenuItem>
189-
{/* <MenuItem onClick={() => setOpenMenus({ ...openMenus, 'demo-customized-menu': { anchorEl: null, open: false } })} disableRipple>
190-
️‍🔥 Trending
191-
</MenuItem>
192-
<MenuItem onClick={() => setOpenMenus({ ...openMenus, 'demo-customized-menu': { anchorEl: null, open: false } })} disableRipple>
193-
⬇️ Most Downloads
194-
</MenuItem> */}
195188
<Divider sx={{ my: 0.5 }} />
196189
<MenuItem sx={{ fontWeight: sort === 'name-asc' ? 'bold' : 'normal' }} onClick={() => {
197190
setOpenMenus({ ...openMenus, 'demo-customized-menu': { anchorEl: null, open: false } })
@@ -228,34 +221,14 @@ export const CatalogGrid: React.FC<CatalogGridProps> = ({
228221
config={config || {}}
229222
/>
230223
)}
231-
{/* {tab === 1 && (
232-
<YourTools
233-
registryItems={registryItems}
234-
search={search}
235-
catalogItems={sortedCatalogItems}
236-
unregister={unregisterCatalogItem}
237-
onSecretChange={tryLoadSecrets}
238-
secrets={secrets}
239-
setConfiguringItem={setConfiguringItem}
240-
canRegister={canRegister}
241-
ddVersion={ddVersion}
242-
config={config || {}}
243-
/>
244-
)} */}
245-
{tab === 2 && ddVersion && (
246-
<YourEnvironment
247-
secrets={secrets}
248-
ddVersion={ddVersion}
249-
config={config || {}}
250-
/>
251-
)}
252224
{tab === 1 && (
253225
<YourClients
254-
client={client}
226+
appProps={appProps}
227+
ddVersion={ddVersion}
255228
/>
256229
)}
257230
</Suspense>
258231
</Stack>
259232
</>
260233
);
261-
};
234+
}

0 commit comments

Comments
 (0)