diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageViewer/NoContentForViewer.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageViewer/NoContentForViewer.tsx index 9a33313808..23b69dff73 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageViewer/NoContentForViewer.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageViewer/NoContentForViewer.tsx @@ -4,7 +4,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { IAINoContentFallback } from 'common/components/IAIImageFallback'; import { InvokeLogoIcon } from 'common/components/InvokeLogoIcon'; import { LOADING_SYMBOL, useHasImages } from 'features/gallery/hooks/useHasImages'; -import { $installModelsTab } from 'features/modelManagerV2/store/installModelsStore'; +import { setInstallModelsTabByName } from 'features/modelManagerV2/store/installModelsStore'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; import { selectIsLocal } from 'features/system/store/configSlice'; import { selectActiveTab } from 'features/ui/store/uiSelectors'; @@ -133,12 +133,12 @@ const StarterBundlesCallout = () => { const handleClickDownloadStarterModels = useCallback(() => { dispatch(setActiveTab('models')); - $installModelsTab.set(3); + setInstallModelsTabByName('starterModels'); }, [dispatch]); const handleClickImportModels = useCallback(() => { dispatch(setActiveTab('models')); - $installModelsTab.set(0); + setInstallModelsTabByName('urlOrLocal'); }, [dispatch]); return ( diff --git a/invokeai/frontend/web/src/features/modelManagerV2/hooks/useStarterModelsToast.tsx b/invokeai/frontend/web/src/features/modelManagerV2/hooks/useStarterModelsToast.tsx index 331644593b..2287453f08 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/hooks/useStarterModelsToast.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/hooks/useStarterModelsToast.tsx @@ -1,6 +1,6 @@ import { Button, Text, useToast } from '@invoke-ai/ui-library'; import { useAppDispatch } from 'app/store/storeHooks'; -import { $installModelsTab } from 'features/modelManagerV2/store/installModelsStore'; +import { setInstallModelsTabByName } from 'features/modelManagerV2/store/installModelsStore'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; import { setActiveTab } from 'features/ui/store/uiSlice'; import { useCallback, useEffect, useState } from 'react'; @@ -45,7 +45,7 @@ const ToastDescription = () => { const onClick = useCallback(() => { dispatch(setActiveTab('models')); - $installModelsTab.set(3); + setInstallModelsTabByName('launchpad'); toast.close(TOAST_ID); }, [dispatch, toast]); diff --git a/invokeai/frontend/web/src/features/modelManagerV2/store/installModelsStore.ts b/invokeai/frontend/web/src/features/modelManagerV2/store/installModelsStore.ts index c6813c422f..b99a1212fe 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/store/installModelsStore.ts +++ b/invokeai/frontend/web/src/features/modelManagerV2/store/installModelsStore.ts @@ -1,7 +1,16 @@ import { atom } from 'nanostores'; -/** - * Atom to manage the active tab index for the Install Models panel. - * Moved to separate file to avoid circular dependencies. - */ -export const $installModelsTab = atom(0); +type InstallModelsTabName = 'launchpad' | 'urlOrLocal' | 'huggingface' | 'scanFolder' | 'starterModels'; + +const TAB_TO_INDEX_MAP: Record = { + launchpad: 0, + urlOrLocal: 1, + huggingface: 2, + scanFolder: 3, + starterModels: 4, +}; + +export const setInstallModelsTabByName = (tab: InstallModelsTabName) => { + $installModelsTabIndex.set(TAB_TO_INDEX_MAP[tab]); +}; +export const $installModelsTabIndex = atom(0); diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/LaunchpadForm/LaunchpadForm.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/LaunchpadForm/LaunchpadForm.tsx index 0168ef08d5..03874ff9e9 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/LaunchpadForm/LaunchpadForm.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/LaunchpadForm/LaunchpadForm.tsx @@ -1,7 +1,7 @@ import { Box, Button, Flex, Grid, Heading, Text } from '@invoke-ai/ui-library'; import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent'; import { useStarterBundleInstall } from 'features/modelManagerV2/hooks/useStarterBundleInstall'; -import { $installModelsTab } from 'features/modelManagerV2/store/installModelsStore'; +import { setInstallModelsTabByName } from 'features/modelManagerV2/store/installModelsStore'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { PiFolderOpenBold, PiLinkBold, PiStarBold } from 'react-icons/pi'; @@ -31,19 +31,19 @@ export const LaunchpadForm = memo(() => { ); const navigateToUrlTab = useCallback(() => { - $installModelsTab.set(1); // URL/Local Path tab (now index 1) + setInstallModelsTabByName('urlOrLocal'); }, []); const navigateToHuggingFaceTab = useCallback(() => { - $installModelsTab.set(2); // HuggingFace tab (now index 2) + setInstallModelsTabByName('huggingface'); }, []); const navigateToScanFolderTab = useCallback(() => { - $installModelsTab.set(3); // Scan Folder tab (now index 3) + setInstallModelsTabByName('scanFolder'); }, []); const navigateToStarterModelsTab = useCallback(() => { - $installModelsTab.set(4); // Starter Models tab (now index 4) + setInstallModelsTabByName('starterModels'); }, []); const handleSD15BundleClick = useCallback(() => { diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/InstallModels.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/InstallModels.tsx index 1ec1ee8c41..9cc7812014 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/InstallModels.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/InstallModels.tsx @@ -1,6 +1,6 @@ import { Box, Button, Flex, Heading, Tab, TabList, TabPanel, TabPanels, Tabs, Text } from '@invoke-ai/ui-library'; import { useStore } from '@nanostores/react'; -import { $installModelsTab } from 'features/modelManagerV2/store/installModelsStore'; +import { $installModelsTabIndex } from 'features/modelManagerV2/store/installModelsStore'; import { StarterModelsForm } from 'features/modelManagerV2/subpanels/AddModelPanel/StarterModels/StarterModelsForm'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; @@ -14,10 +14,7 @@ import { ScanModelsForm } from './AddModelPanel/ScanFolder/ScanFolderForm'; export const InstallModels = memo(() => { const { t } = useTranslation(); - const index = useStore($installModelsTab); - const onChange = useCallback((index: number) => { - $installModelsTab.set(index); - }, []); + const tabIndex = useStore($installModelsTabIndex); const onClickLearnMore = useCallback(() => { window.open('https://support.invoke.ai/support/solutions/articles/151000170961-supported-models'); @@ -31,7 +28,14 @@ export const InstallModels = memo(() => { {t('modelManager.learnMoreAboutSupportedModels')} - + {t('modelManager.launchpadTab')} {t('modelManager.urlOrLocalPath')} diff --git a/invokeai/frontend/web/src/features/parameters/components/ModelPicker.tsx b/invokeai/frontend/web/src/features/parameters/components/ModelPicker.tsx index bb0ada4755..c642491e4e 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ModelPicker.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ModelPicker.tsx @@ -18,7 +18,7 @@ import type { Group, PickerContextState } from 'common/components/Picker/Picker' import { buildGroup, getRegex, Picker, usePickerContext } from 'common/components/Picker/Picker'; import { useDisclosure } from 'common/hooks/useBoolean'; import { typedMemo } from 'common/util/typedMemo'; -import { $installModelsTab } from 'features/modelManagerV2/store/installModelsStore'; +import { setInstallModelsTabByName } from 'features/modelManagerV2/store/installModelsStore'; import { BASE_COLOR_MAP } from 'features/modelManagerV2/subpanels/ModelManagerPanel/ModelBaseBadge'; import ModelImage from 'features/modelManagerV2/subpanels/ModelManagerPanel/ModelImage'; import { NavigateToModelManagerButton } from 'features/parameters/components/MainModel/NavigateToModelManagerButton'; @@ -38,7 +38,7 @@ const ModelManagerLink = memo((props: ButtonProps) => { const dispatch = useAppDispatch(); const onClick = useCallback(() => { dispatch(setActiveTab('models')); - $installModelsTab.set(3); + setInstallModelsTabByName('launchpad'); }, [dispatch]); return ( diff --git a/invokeai/frontend/web/src/features/parameters/components/PostProcessing/PostProcessingPopover.tsx b/invokeai/frontend/web/src/features/parameters/components/PostProcessing/PostProcessingPopover.tsx index b1778fda30..3a8cae1aca 100644 --- a/invokeai/frontend/web/src/features/parameters/components/PostProcessing/PostProcessingPopover.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/PostProcessing/PostProcessingPopover.tsx @@ -11,7 +11,7 @@ import { } from '@invoke-ai/ui-library'; import { adHocPostProcessingRequested } from 'app/store/middleware/listenerMiddleware/listeners/addAdHocPostProcessingRequestedListener'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { $installModelsTab } from 'features/modelManagerV2/store/installModelsStore'; +import { setInstallModelsTabByName } from 'features/modelManagerV2/store/installModelsStore'; import ParamPostProcessingModel from 'features/parameters/components/PostProcessing/ParamPostProcessingModel'; import { selectPostProcessingModel } from 'features/parameters/store/upscaleSlice'; import { useIsQueueMutationInProgress } from 'features/queue/hooks/useIsQueueMutationInProgress'; @@ -78,7 +78,7 @@ const MissingModelWarning = () => { const handleGoToModelManager = useCallback(() => { dispatch(setActiveTab('models')); - $installModelsTab.set(3); + setInstallModelsTabByName('launchpad'); }, [dispatch]); return ( diff --git a/invokeai/frontend/web/src/features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleWarning.tsx b/invokeai/frontend/web/src/features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleWarning.tsx index 49344b3934..b4abe47cf8 100644 --- a/invokeai/frontend/web/src/features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleWarning.tsx +++ b/invokeai/frontend/web/src/features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleWarning.tsx @@ -1,7 +1,7 @@ import { Button, Flex, ListItem, Text, UnorderedList } from '@invoke-ai/ui-library'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { selectModel } from 'features/controlLayers/store/paramsSlice'; -import { $installModelsTab } from 'features/modelManagerV2/store/installModelsStore'; +import { setInstallModelsTabByName } from 'features/modelManagerV2/store/installModelsStore'; import { useIsTooLargeToUpscale } from 'features/parameters/hooks/useIsTooLargeToUpscale'; import { selectTileControlNetModel, @@ -69,7 +69,7 @@ export const UpscaleWarning = () => { const handleGoToModelManager = useCallback(() => { dispatch(setActiveTab('models')); - $installModelsTab.set(3); + setInstallModelsTabByName('launchpad'); }, [dispatch]); if (isBaseModelCompatible && modelWarnings.length > 0 && isModelsTabDisabled) {