diff --git a/invokeai/frontend/web/src/app/types/invokeai.ts b/invokeai/frontend/web/src/app/types/invokeai.ts index b79504d8f2..d0e5437d36 100644 --- a/invokeai/frontend/web/src/app/types/invokeai.ts +++ b/invokeai/frontend/web/src/app/types/invokeai.ts @@ -326,11 +326,11 @@ export type AppFeature = /** * A disable-able Stable Diffusion feature */ -export type StableDiffusionFeature = - | 'noiseConfig' - | 'variations' +export type SDFeature = + | 'noise' + | 'variation' | 'symmetry' - | 'tiling' + | 'seamless' | 'hires'; /** @@ -348,6 +348,7 @@ export type AppConfig = { shouldFetchImages: boolean; disabledTabs: InvokeTabName[]; disabledFeatures: AppFeature[]; + disabledSDFeatures: SDFeature[]; canRestoreDeletedImagesFromBin: boolean; sd: { iterations: { diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx index 2a3d12ce91..e76f3fa41e 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx @@ -152,6 +152,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { } = useAppSelector(currentImageButtonsSelector); const isLightboxEnabled = useFeatureStatus('lightbox').isFeatureEnabled; + const isCanvasEnabled = useFeatureStatus('unifiedCanvas').isFeatureEnabled; const isUpscalingEnabled = useFeatureStatus('upscaling').isFeatureEnabled; const isFaceRestoreEnabled = useFeatureStatus('faceRestore').isFeatureEnabled; @@ -429,13 +430,15 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { > {t('parameters.sendToImg2Img')} - } - > - {t('parameters.sendToUnifiedCanvas')} - + {isCanvasEnabled && ( + } + > + {t('parameters.sendToUnifiedCanvas')} + + )} {/* { const toast = useToast(); const { t } = useTranslation(); - const { isFeatureEnabled: isLightboxEnabled } = useFeatureStatus('lightbox'); + + const isLightboxEnabled = useFeatureStatus('lightbox').isFeatureEnabled; + const isCanvasEnabled = useFeatureStatus('unifiedCanvas').isFeatureEnabled; + const { recallSeed, recallPrompt, recallInitialImage, recallAllParameters } = useParameters(); @@ -250,9 +253,11 @@ const HoverableImage = memo((props: HoverableImageProps) => { > {t('parameters.sendToImg2Img')} - } onClickCapture={handleSendToCanvas}> - {t('parameters.sendToUnifiedCanvas')} - + {isCanvasEnabled && ( + } onClickCapture={handleSendToCanvas}> + {t('parameters.sendToUnifiedCanvas')} + + )} } onClickCapture={onDeleteDialogOpen}> {t('gallery.deleteImage')} diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Hires/ParamHiresCollapse.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Hires/ParamHiresCollapse.tsx index 9c1f3a3f14..b4b077ad6c 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Hires/ParamHiresCollapse.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Hires/ParamHiresCollapse.tsx @@ -6,6 +6,7 @@ import IAICollapse from 'common/components/IAICollapse'; import { memo } from 'react'; import { ParamHiresStrength } from './ParamHiresStrength'; import { setHiresFix } from 'features/parameters/store/postprocessingSlice'; +import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; const ParamHiresCollapse = () => { const { t } = useTranslation(); @@ -13,10 +14,16 @@ const ParamHiresCollapse = () => { (state: RootState) => state.postprocessing.hiresFix ); + const isHiresEnabled = useFeatureStatus('hires').isFeatureEnabled; + const dispatch = useAppDispatch(); const handleToggle = () => dispatch(setHiresFix(!hiresFix)); + if (!isHiresEnabled) { + return null; + } + return ( { const { t } = useTranslation(); + + const isNoiseEnabled = useFeatureStatus('noise').isFeatureEnabled; + const shouldUseNoiseSettings = useAppSelector( (state: RootState) => state.generation.shouldUseNoiseSettings ); @@ -19,6 +23,10 @@ const ParamNoiseCollapse = () => { const handleToggle = () => dispatch(setShouldUseNoiseSettings(!shouldUseNoiseSettings)); + if (!isNoiseEnabled) { + return null; + } + return ( { const { t } = useTranslation(); const { shouldUseSeamless } = useAppSelector(selector); + const isSeamlessEnabled = useFeatureStatus('seamless').isFeatureEnabled; + const dispatch = useAppDispatch(); const handleToggle = () => dispatch(setSeamless(!shouldUseSeamless)); + if (!isSeamlessEnabled) { + return null; + } + return ( { const { t } = useTranslation(); @@ -15,10 +16,16 @@ const ParamSymmetryCollapse = () => { (state: RootState) => state.generation.shouldUseSymmetry ); + const isSymmetryEnabled = useFeatureStatus('symmetry').isFeatureEnabled; + const dispatch = useAppDispatch(); const handleToggle = () => dispatch(setShouldUseSymmetry(!shouldUseSymmetry)); + if (!isSymmetryEnabled) { + return null; + } + return ( { const { t } = useTranslation(); @@ -14,11 +15,17 @@ const ParamVariationCollapse = () => { (state: RootState) => state.generation.shouldGenerateVariations ); + const isVariationEnabled = useFeatureStatus('variation').isFeatureEnabled; + const dispatch = useAppDispatch(); const handleToggle = () => dispatch(setShouldGenerateVariations(!shouldGenerateVariations)); + if (!isVariationEnabled) { + return null; + } + return ( { + const disabledTabs = useAppSelector( + (state: RootState) => state.config.disabledTabs + ); -export const useFeatureStatus = (feature: AppFeature) => { const disabledFeatures = useAppSelector( (state: RootState) => state.config.disabledFeatures ); + const disabledSDFeatures = useAppSelector( + (state: RootState) => state.config.disabledSDFeatures + ); + const isFeatureDisabled = useMemo( - () => disabledFeatures.includes(feature), - [disabledFeatures, feature] + () => + disabledFeatures.includes(feature as AppFeature) || + disabledSDFeatures.includes(feature as SDFeature) || + disabledTabs.includes(feature as InvokeTabName), + [disabledFeatures, disabledSDFeatures, disabledTabs, feature] ); const isFeatureEnabled = useMemo( - () => !disabledFeatures.includes(feature), - [disabledFeatures, feature] + () => + !( + disabledFeatures.includes(feature as AppFeature) || + disabledSDFeatures.includes(feature as SDFeature) || + disabledTabs.includes(feature as InvokeTabName) + ), + [disabledFeatures, disabledSDFeatures, disabledTabs, feature] ); return { isFeatureDisabled, isFeatureEnabled }; diff --git a/invokeai/frontend/web/src/features/system/store/configSlice.ts b/invokeai/frontend/web/src/features/system/store/configSlice.ts index b773692908..7b3a1b1eea 100644 --- a/invokeai/frontend/web/src/features/system/store/configSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/configSlice.ts @@ -8,6 +8,7 @@ export const initialConfigState: AppConfig = { shouldFetchImages: false, disabledTabs: [], disabledFeatures: [], + disabledSDFeatures: [], canRestoreDeletedImagesFromBin: true, sd: { iterations: {