diff --git a/src/components/shared/Dialogs/ComponentDuplicateDialog.test.tsx b/src/components/shared/Dialogs/ComponentDuplicateDialog.test.tsx index 38891bea9..2e23912a8 100644 --- a/src/components/shared/Dialogs/ComponentDuplicateDialog.test.tsx +++ b/src/components/shared/Dialogs/ComponentDuplicateDialog.test.tsx @@ -50,7 +50,6 @@ const createMockComponentLibraryContext = ( removeFromComponentLibrary: vi.fn(), setComponentFavorite: vi.fn(), checkIfUserComponent: vi.fn().mockReturnValue(false), - checkLibraryContainsComponent: vi.fn().mockReturnValue(false), getComponentLibrary: vi.fn(), }; }; diff --git a/src/components/shared/FavoriteComponentToggle.tsx b/src/components/shared/FavoriteComponentToggle.tsx index b9edd3709..77f8863f0 100644 --- a/src/components/shared/FavoriteComponentToggle.tsx +++ b/src/components/shared/FavoriteComponentToggle.tsx @@ -14,9 +14,13 @@ import { Spinner } from "@/components/ui/spinner"; import { useGuaranteedHydrateComponentReference } from "@/hooks/useHydrateComponentReference"; import { cn } from "@/lib/utils"; import { useComponentLibrary } from "@/providers/ComponentLibraryProvider"; -import { isFavoriteComponent } from "@/providers/ComponentLibraryProvider/componentLibrary"; +import { + flattenFolders, + isFavoriteComponent, +} from "@/providers/ComponentLibraryProvider/componentLibrary"; import { hydrateComponentReference } from "@/services/componentService"; -import type { ComponentReference } from "@/utils/componentSpec"; +import { type ComponentReference } from "@/utils/componentSpec"; +import { MINUTES } from "@/utils/constants"; import { getComponentName } from "@/utils/getComponentName"; import { withSuspenseWrapper } from "./SuspenseWrapper"; @@ -132,30 +136,63 @@ const FavoriteToggleButton = withSuspenseWrapper( ), ); -export const ComponentFavoriteToggle = ({ +const useComponentFlags = (component: ComponentReference) => { + const { checkIfUserComponent, componentLibrary } = useComponentLibrary(); + + const isUserComponent = useMemo( + () => checkIfUserComponent(component), + [component, checkIfUserComponent], + ); + + const flatComponentList = useMemo( + () => (componentLibrary ? flattenFolders(componentLibrary) : []), + [componentLibrary], + ); + + const { data: isInLibrary } = useSuspenseQuery({ + queryKey: ["component", "flags", component.digest], + queryFn: async () => { + if (!componentLibrary) return false; + + if (isUserComponent) return true; + + for (const c of flatComponentList) { + if (component.name === "Chicago Taxi Trips dataset") { + console.log(c.name, c.digest, component.digest); + } + + if (c.name && c.name !== component.name) { + // micro optimization to skip components with different names + continue; + } + + const digest = c.digest ?? (await hydrateComponentReference(c))?.digest; + + if (digest === component.digest) { + return true; + } + } + + return false; + }, + staleTime: 10 * MINUTES, + }); + + return { isInLibrary, isUserComponent }; +}; + +const ComponentFavoriteToggleInternal = ({ component, hideDelete = false, }: ComponentFavoriteToggleProps) => { - const { - addToComponentLibrary, - removeFromComponentLibrary, - checkIfUserComponent, - checkLibraryContainsComponent, - } = useComponentLibrary(); + const { addToComponentLibrary, removeFromComponentLibrary } = + useComponentLibrary(); const [isOpen, setIsOpen] = useState(false); const { spec, url } = component; - const isUserComponent = useMemo( - () => checkIfUserComponent(component), - [component, checkIfUserComponent], - ); - - const isInLibrary = useMemo( - () => checkLibraryContainsComponent(component), - [component, checkLibraryContainsComponent], - ); + const { isInLibrary, isUserComponent } = useComponentFlags(component); const displayName = useMemo( () => getComponentName({ spec, url }), @@ -228,3 +265,13 @@ export const ComponentFavoriteToggle = ({ ); }; + +export const ComponentFavoriteToggle = withSuspenseWrapper( + ComponentFavoriteToggleInternal, + () => , + () => ( + + + + ), +); diff --git a/src/providers/ComponentLibraryProvider/ComponentLibraryProvider.test.tsx b/src/providers/ComponentLibraryProvider/ComponentLibraryProvider.test.tsx index 2d31b4203..59934afc4 100644 --- a/src/providers/ComponentLibraryProvider/ComponentLibraryProvider.test.tsx +++ b/src/providers/ComponentLibraryProvider/ComponentLibraryProvider.test.tsx @@ -536,29 +536,6 @@ describe("ComponentLibraryProvider - Component Management", () => { result.current.checkIfUserComponent(standardComponent); expect(isUserComponent).toBe(false); }); - - it("should correctly check if library contains component", async () => { - const libraryComponent: ComponentReference = { - name: "library-component", - digest: "library-digest", - spec: mockComponentSpec, - }; - - mockFlattenFolders.mockReturnValue([libraryComponent]); - mockFilterToUniqueByDigest.mockReturnValue([libraryComponent]); - - const { result } = renderHook(() => useComponentLibrary(), { - wrapper: createWrapper, - }); - - await waitFor(() => { - expect(result.current.isLoading).toBe(false); - }); - - const containsComponent = - result.current.checkLibraryContainsComponent(libraryComponent); - expect(containsComponent).toBe(true); - }); }); describe("Component Favoriting", () => { diff --git a/src/providers/ComponentLibraryProvider/ComponentLibraryProvider.tsx b/src/providers/ComponentLibraryProvider/ComponentLibraryProvider.tsx index 4200c05af..b3fe94be3 100644 --- a/src/providers/ComponentLibraryProvider/ComponentLibraryProvider.tsx +++ b/src/providers/ComponentLibraryProvider/ComponentLibraryProvider.tsx @@ -89,7 +89,6 @@ type ComponentLibraryContextType = { favorited: boolean, ) => void; checkIfUserComponent: (component: ComponentReference) => boolean; - checkLibraryContainsComponent: (component: ComponentReference) => boolean; getComponentLibrary: (libraryName: AvailableComponentLibraries) => Library; }; @@ -340,21 +339,6 @@ export const ComponentLibraryProvider = ({ [userComponentsFolder], ); - const checkLibraryContainsComponent = useCallback( - (component: ComponentReference) => { - if (!componentLibrary) return false; - - if (checkIfUserComponent(component)) return true; - - const uniqueComponents = filterToUniqueByDigest( - flattenFolders(componentLibrary), - ); - - return uniqueComponents.some((c) => c.digest === component.digest); - }, - [componentLibrary, checkIfUserComponent], - ); - /** * Local component library search */ @@ -592,7 +576,6 @@ export const ComponentLibraryProvider = ({ removeFromComponentLibrary, setComponentFavorite, checkIfUserComponent, - checkLibraryContainsComponent, }), [ componentLibrary, @@ -609,7 +592,6 @@ export const ComponentLibraryProvider = ({ removeFromComponentLibrary, setComponentFavorite, checkIfUserComponent, - checkLibraryContainsComponent, ], );