From afc6f83d72aee01d481c519b207e74d2c8c38a59 Mon Sep 17 00:00:00 2001
From: psychedelicious <4822129+psychedelicious@users.noreply.github.com>
Date: Sat, 24 Aug 2024 12:32:38 +1000
Subject: [PATCH] fix(ui): lint & fix issues with adding regional ip adapters

---
 .../components/CanvasAddEntityButtons.tsx     | 15 +++++------
 ...onalGuidanceAddPromptsIPAdapterButtons.tsx |  7 ++---
 ...uidanceMenuItemsAddPromptsAndIPAdapter.tsx |  7 ++---
 .../hooks/useLayerControlAdapter.ts           |  2 ++
 .../features/controlLayers/konva/constants.ts |  5 ----
 .../controlLayers/store/canvasV2Slice.ts      |  2 +-
 .../controlLayers/store/regionsReducers.ts    | 27 +++++++++++++------
 7 files changed, 32 insertions(+), 33 deletions(-)

diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CanvasAddEntityButtons.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CanvasAddEntityButtons.tsx
index b98c0e78d6..abb689983a 100644
--- a/invokeai/frontend/web/src/features/controlLayers/components/CanvasAddEntityButtons.tsx
+++ b/invokeai/frontend/web/src/features/controlLayers/components/CanvasAddEntityButtons.tsx
@@ -1,6 +1,5 @@
 import { Button, ButtonGroup, Flex } from '@invoke-ai/ui-library';
 import { useAppDispatch } from 'app/store/storeHooks';
-import { useDefaultControlAdapter, useDefaultIPAdapter } from 'features/controlLayers/hooks/useLayerControlAdapter';
 import {
   controlLayerAdded,
   inpaintMaskAdded,
@@ -15,23 +14,21 @@ import { PiPlusBold } from 'react-icons/pi';
 export const CanvasAddEntityButtons = memo(() => {
   const { t } = useTranslation();
   const dispatch = useAppDispatch();
-  const defaultControlAdapter = useDefaultControlAdapter();
-  const defaultIPAdapter = useDefaultIPAdapter();
   const addInpaintMask = useCallback(() => {
-    dispatch(inpaintMaskAdded());
+    dispatch(inpaintMaskAdded({ isSelected: true }));
   }, [dispatch]);
   const addRegionalGuidance = useCallback(() => {
-    dispatch(rgAdded());
+    dispatch(rgAdded({ isSelected: true }));
   }, [dispatch]);
   const addRasterLayer = useCallback(() => {
     dispatch(rasterLayerAdded({ isSelected: true }));
   }, [dispatch]);
   const addControlLayer = useCallback(() => {
-    dispatch(controlLayerAdded({ isSelected: true, overrides: { controlAdapter: defaultControlAdapter } }));
-  }, [defaultControlAdapter, dispatch]);
+    dispatch(controlLayerAdded({ isSelected: true }));
+  }, [dispatch]);
   const addIPAdapter = useCallback(() => {
-    dispatch(ipaAdded({ ipAdapter: defaultIPAdapter }));
-  }, [defaultIPAdapter, dispatch]);
+    dispatch(ipaAdded({ isSelected: true }));
+  }, [dispatch]);
 
   return (
     <Flex flexDir="column" w="full" h="full" alignItems="center" justifyContent="center">
diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceAddPromptsIPAdapterButtons.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceAddPromptsIPAdapterButtons.tsx
index 07104989c0..4533320714 100644
--- a/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceAddPromptsIPAdapterButtons.tsx
+++ b/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceAddPromptsIPAdapterButtons.tsx
@@ -1,8 +1,6 @@
 import { Button, Flex } from '@invoke-ai/ui-library';
 import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
 import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
-import { useDefaultIPAdapter } from 'features/controlLayers/hooks/useLayerControlAdapter';
-import { nanoid } from 'features/controlLayers/konva/util';
 import {
   rgIPAdapterAdded,
   rgNegativePromptChanged,
@@ -20,7 +18,6 @@ type AddPromptButtonProps = {
 export const RegionalGuidanceAddPromptsIPAdapterButtons = ({ id }: AddPromptButtonProps) => {
   const { t } = useTranslation();
   const dispatch = useAppDispatch();
-  const defaultIPAdapter = useDefaultIPAdapter();
   const selectValidActions = useMemo(
     () =>
       createMemoizedSelector(selectCanvasV2Slice, (canvasV2) => {
@@ -40,8 +37,8 @@ export const RegionalGuidanceAddPromptsIPAdapterButtons = ({ id }: AddPromptButt
     dispatch(rgNegativePromptChanged({ id, prompt: '' }));
   }, [dispatch, id]);
   const addIPAdapter = useCallback(() => {
-    dispatch(rgIPAdapterAdded({ id, ipAdapter: { ...defaultIPAdapter, id: nanoid() } }));
-  }, [defaultIPAdapter, dispatch, id]);
+    dispatch(rgIPAdapterAdded({ id }));
+  }, [dispatch, id]);
 
   return (
     <Flex w="full" p={2} justifyContent="space-between">
diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItemsAddPromptsAndIPAdapter.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItemsAddPromptsAndIPAdapter.tsx
index bda94d91de..5556c25929 100644
--- a/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItemsAddPromptsAndIPAdapter.tsx
+++ b/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItemsAddPromptsAndIPAdapter.tsx
@@ -2,8 +2,6 @@ import { MenuItem } from '@invoke-ai/ui-library';
 import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
 import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
 import { useEntityIdentifierContext } from 'features/controlLayers/contexts/EntityIdentifierContext';
-import { useDefaultIPAdapter } from 'features/controlLayers/hooks/useLayerControlAdapter';
-import { nanoid } from 'features/controlLayers/konva/util';
 import {
   rgIPAdapterAdded,
   rgNegativePromptChanged,
@@ -17,7 +15,6 @@ export const RegionalGuidanceMenuItemsAddPromptsAndIPAdapter = memo(() => {
   const { id } = useEntityIdentifierContext();
   const { t } = useTranslation();
   const dispatch = useAppDispatch();
-  const defaultIPAdapter = useDefaultIPAdapter();
   const selectValidActions = useMemo(
     () =>
       createMemoizedSelector(selectCanvasV2Slice, (canvasV2) => {
@@ -37,8 +34,8 @@ export const RegionalGuidanceMenuItemsAddPromptsAndIPAdapter = memo(() => {
     dispatch(rgNegativePromptChanged({ id: id, prompt: '' }));
   }, [dispatch, id]);
   const addIPAdapter = useCallback(() => {
-    dispatch(rgIPAdapterAdded({ id, ipAdapter: { ...defaultIPAdapter, id: nanoid() } }));
-  }, [defaultIPAdapter, dispatch, id]);
+    dispatch(rgIPAdapterAdded({ id }));
+  }, [dispatch, id]);
 
   return (
     <>
diff --git a/invokeai/frontend/web/src/features/controlLayers/hooks/useLayerControlAdapter.ts b/invokeai/frontend/web/src/features/controlLayers/hooks/useLayerControlAdapter.ts
index 9f876d5e56..827174c2df 100644
--- a/invokeai/frontend/web/src/features/controlLayers/hooks/useLayerControlAdapter.ts
+++ b/invokeai/frontend/web/src/features/controlLayers/hooks/useLayerControlAdapter.ts
@@ -27,6 +27,7 @@ export const useControlLayerControlAdapter = (entityIdentifier: CanvasEntityIden
   return controlAdapter;
 };
 
+/** @knipignore */
 export const useDefaultControlAdapter = (): ControlNetConfig | T2IAdapterConfig => {
   const [modelConfigs] = useControlNetAndT2IAdapterModels();
 
@@ -47,6 +48,7 @@ export const useDefaultControlAdapter = (): ControlNetConfig | T2IAdapterConfig
   return defaultControlAdapter;
 };
 
+/** @knipignore */
 export const useDefaultIPAdapter = (): IPAdapterConfig => {
   const [modelConfigs] = useIPAdapterModels();
 
diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/constants.ts b/invokeai/frontend/web/src/features/controlLayers/konva/constants.ts
index 1af95a77fa..398ff4b12e 100644
--- a/invokeai/frontend/web/src/features/controlLayers/konva/constants.ts
+++ b/invokeai/frontend/web/src/features/controlLayers/konva/constants.ts
@@ -15,11 +15,6 @@ export const BRUSH_BORDER_INNER_COLOR = 'rgba(0,0,0,1)';
  */
 export const BRUSH_BORDER_OUTER_COLOR = 'rgba(255,255,255,0.8)';
 
-/**
- * The border width for the brush preview.
- */
-export const BRUSH_ERASER_BORDER_WIDTH = 1;
-
 /**
  * The target spacing of individual points of brush strokes, as a percentage of the brush size.
  */
diff --git a/invokeai/frontend/web/src/features/controlLayers/store/canvasV2Slice.ts b/invokeai/frontend/web/src/features/controlLayers/store/canvasV2Slice.ts
index 702e42786b..425e7529ae 100644
--- a/invokeai/frontend/web/src/features/controlLayers/store/canvasV2Slice.ts
+++ b/invokeai/frontend/web/src/features/controlLayers/store/canvasV2Slice.ts
@@ -175,7 +175,7 @@ function selectAllEntitiesOfType(state: CanvasV2State, type: CanvasEntityState['
   }
 }
 
-export function selectAllEntities(state: CanvasV2State): CanvasEntityState[] {
+function selectAllEntities(state: CanvasV2State): CanvasEntityState[] {
   // These are in the same order as they are displayed in the list!
   return [
     ...state.inpaintMasks.entities.toReversed(),
diff --git a/invokeai/frontend/web/src/features/controlLayers/store/regionsReducers.ts b/invokeai/frontend/web/src/features/controlLayers/store/regionsReducers.ts
index faf12dd3f7..96d47395d6 100644
--- a/invokeai/frontend/web/src/features/controlLayers/store/regionsReducers.ts
+++ b/invokeai/frontend/web/src/features/controlLayers/store/regionsReducers.ts
@@ -1,4 +1,5 @@
 import type { PayloadAction, SliceCaseReducers } from '@reduxjs/toolkit';
+import { deepClone } from 'common/util/deepClone';
 import { getPrefixedId } from 'features/controlLayers/konva/util';
 import type {
   CanvasV2State,
@@ -8,7 +9,7 @@ import type {
   RegionalGuidanceIPAdapterConfig,
   RgbColor,
 } from 'features/controlLayers/store/types';
-import { getEntityIdentifier, imageDTOToImageWithDims } from 'features/controlLayers/store/types';
+import { getEntityIdentifier, imageDTOToImageWithDims, initialIPAdapter } from 'features/controlLayers/store/types';
 import { zModelIdentifierField } from 'features/nodes/types/common';
 import { isEqual, merge } from 'lodash-es';
 import type { ImageDTO, IPAdapterModelConfig } from 'services/api/types';
@@ -134,13 +135,23 @@ export const regionsReducers = {
     }
     rg.autoNegative = !rg.autoNegative;
   },
-  rgIPAdapterAdded: (state, action: PayloadAction<{ id: string; ipAdapter: RegionalGuidanceIPAdapterConfig }>) => {
-    const { id, ipAdapter } = action.payload;
-    const entity = selectRegionalGuidanceEntity(state, id);
-    if (!entity) {
-      return;
-    }
-    entity.ipAdapters.push(ipAdapter);
+  rgIPAdapterAdded: {
+    reducer: (
+      state,
+      action: PayloadAction<{ id: string; ipAdapterId: string; overrides?: Partial<RegionalGuidanceIPAdapterConfig> }>
+    ) => {
+      const { id, overrides, ipAdapterId } = action.payload;
+      const entity = selectRegionalGuidanceEntity(state, id);
+      if (!entity) {
+        return;
+      }
+      const ipAdapter = { ...deepClone(initialIPAdapter), id: ipAdapterId };
+      merge(ipAdapter, overrides);
+      entity.ipAdapters.push(ipAdapter);
+    },
+    prepare: (payload: { id: string; overrides?: Partial<RegionalGuidanceIPAdapterConfig> }) => ({
+      payload: { ...payload, ipAdapterId: getPrefixedId('regional_guidance_ip_adapter') },
+    }),
   },
   rgIPAdapterDeleted: (state, action: PayloadAction<{ id: string; ipAdapterId: string }>) => {
     const { id, ipAdapterId } = action.payload;