diff --git a/dist/manifest.json b/dist/manifest.json index f0604cf..657ea62 100644 --- a/dist/manifest.json +++ b/dist/manifest.json @@ -30,7 +30,48 @@ "type": "panel", "id": "contextmanager", "label": { - "default": "Context Manager" + "default": "AI Manager" + }, + "minimumSize": { + "width": 400, + "height": 150 + }, + "maximumSize": { + "width": 1340, + "height": 1516 + }, + "preferredDockedSize": { + "width": 340, + "height": 516 + }, + "preferredFloatingSize": { + "width": 340, + "height": 315 + }, + "icons": [ + { + "width": 23, + "height": 23, + "path": "icons/bashful_23.png", + "scale": [1, 2], + "theme": ["dark", "darkest"], + "species": ["chrome"] + }, + { + "width": 23, + "height": 23, + "path": "icons/bashful_23.png", + "scale": [1, 2], + "theme": ["lightest", "light"], + "species": ["chrome"] + } + ] + }, + { + "type": "panel", + "id": "contextpalette", + "label": { + "default": "AI Brush" }, "minimumSize": { "width": 400, diff --git a/plugin/manifest.json b/plugin/manifest.json index f0604cf..657ea62 100644 --- a/plugin/manifest.json +++ b/plugin/manifest.json @@ -30,7 +30,48 @@ "type": "panel", "id": "contextmanager", "label": { - "default": "Context Manager" + "default": "AI Manager" + }, + "minimumSize": { + "width": 400, + "height": 150 + }, + "maximumSize": { + "width": 1340, + "height": 1516 + }, + "preferredDockedSize": { + "width": 340, + "height": 516 + }, + "preferredFloatingSize": { + "width": 340, + "height": 315 + }, + "icons": [ + { + "width": 23, + "height": 23, + "path": "icons/bashful_23.png", + "scale": [1, 2], + "theme": ["dark", "darkest"], + "species": ["chrome"] + }, + { + "width": 23, + "height": 23, + "path": "icons/bashful_23.png", + "scale": [1, 2], + "theme": ["lightest", "light"], + "species": ["chrome"] + } + ] + }, + { + "type": "panel", + "id": "contextpalette", + "label": { + "default": "AI Brush" }, "minimumSize": { "width": 400, diff --git a/src/common/types/htmlTypes.ts b/src/common/types/htmlTypes.ts index ccd35e1..4008be9 100644 --- a/src/common/types/htmlTypes.ts +++ b/src/common/types/htmlTypes.ts @@ -1,3 +1,4 @@ export interface ExtendedHTMLDialogElement extends HTMLDialogElement { uxpShowModal(options: any): Promise; + uxpShow(options: any): Promise; } diff --git a/src/components/Context/ContextInfoColumn.tsx b/src/components/Context/ContextInfoColumn.tsx index fcfffef..cd759c1 100644 --- a/src/components/Context/ContextInfoColumn.tsx +++ b/src/components/Context/ContextInfoColumn.tsx @@ -14,6 +14,7 @@ import ContextLabel from './ContextLabel'; export type ContextInfoColumnProps = { contextID: string; + contextType: ContextType; }; function DefaultContextInfoColumn() { @@ -26,8 +27,8 @@ function DefaultContextInfoColumn() { } export default function ContextInfoColumn(props: ContextInfoColumnProps) { - let layerContext = useContextStore((state: ContextStoreState) => - state.getContextFromStore(props.contextID, ContextType.LAYER) + let genAISettings = useContextStore((state: ContextStoreState) => + state.getContextFromStore(props.contextID, props.contextType) ); let getContextFromStore = useContextStore( @@ -39,7 +40,7 @@ export default function ContextInfoColumn(props: ContextInfoColumnProps) { ); let { loading, value } = useAsyncEffect(async () => { - if (layerContext.is_cloud_run == false) { + if (!(genAISettings?.is_cloud_run)) { // While this does work, this is for the future where we batch run the models, currently // we would have to make sure each local user swaps out the models when they want to use // a different model on a specific layer. We will collect the selection of models for them @@ -50,13 +51,13 @@ export default function ContextInfoColumn(props: ContextInfoColumnProps) { } else { return getAvailableModelConfigs(); } - }, [layerContext.is_cloud_run]); + }, [genAISettings?.is_cloud_run]); function getDropDownOptions() { if (loading) { return ['loading models...']; } else { - if (layerContext.is_cloud_run == false) { + if (genAISettings.is_cloud_run == false) { return value .map((modelObj: ModelResponse) => { return modelObj.title; @@ -75,7 +76,7 @@ export default function ContextInfoColumn(props: ContextInfoColumnProps) { function saveSelectedModelConfig(selectedConfigObj: ModelConfigResponse) { let copyOfContext = getContextFromStore( props.contextID, - ContextType.LAYER + props.contextType ).copy(); copyOfContext.model_config = selectedConfigObj.name; saveContextToStore(copyOfContext); @@ -88,7 +89,7 @@ export default function ContextInfoColumn(props: ContextInfoColumnProps) { } function getCorrectContextKey() { - if (!layerContext.is_cloud_run) { + if (!genAISettings.is_cloud_run) { return 'generationModelName' as keyof typeof LayerAIContext; } @@ -99,14 +100,14 @@ export default function ContextInfoColumn(props: ContextInfoColumnProps) { return (
{loading ? ( ) : ( @@ -114,12 +115,12 @@ export default function ContextInfoColumn(props: ContextInfoColumnProps) { { diff --git a/src/components/Context/ContextItem.tsx b/src/components/Context/LayerContextItem.tsx similarity index 71% rename from src/components/Context/ContextItem.tsx rename to src/components/Context/LayerContextItem.tsx index a99dfa9..8e9fb05 100644 --- a/src/components/Context/ContextItem.tsx +++ b/src/components/Context/LayerContextItem.tsx @@ -2,7 +2,7 @@ import React from 'react'; import ContextInfoColumn from './ContextInfoColumn'; import ContextToolColumn from './ContextToolColumn'; -import ContextToolBar from './ContextToolBar'; +import LayerContextToolBar from './LayerContextToolBar'; import ContextSlider from './ContextSlider'; import _ from 'lodash'; @@ -10,25 +10,27 @@ import LayerAIContext from 'models/LayerAIContext'; import ContextTextarea from './ContextTextarea'; import { ContextType } from 'bashConstants'; import ContextTagArea from './ContextTagArea'; +import ContextObject from 'models/ContextObject'; export type ContextItemProps = { contextID: string; + contextType: ContextType; }; -export default function ContextItem(props: ContextItemProps) { +export default function LayerContextItem(props: ContextItemProps) { return (
- +
- +
Consistency Strength @@ -36,17 +38,17 @@ export default function ContextItem(props: ContextItemProps) { Styling Strength diff --git a/src/components/Context/ContextToolBar.tsx b/src/components/Context/LayerContextToolBar.tsx similarity index 94% rename from src/components/Context/ContextToolBar.tsx rename to src/components/Context/LayerContextToolBar.tsx index 846d0f2..1dd2e82 100644 --- a/src/components/Context/ContextToolBar.tsx +++ b/src/components/Context/LayerContextToolBar.tsx @@ -12,15 +12,16 @@ import { toggleOffContextHidingTool, toggleOnContextHidingTool, } from 'services/tools_service'; -import { popUpModal } from 'utils/general_utils'; +import { popUp, popUpModal } from 'utils/general_utils'; import { ExtendedHTMLDialogElement } from 'common/types/htmlTypes'; import photoshop from 'photoshop'; import Spectrum, { Checkbox, Label } from 'react-uxp-spectrum'; import Tool from 'components/Tool'; import RegenerationTool from 'components/RegenerationTool'; -import ContextPainterModal from 'components/modals/ContextPainterModal'; +import ContextPainterModal from 'components/modals/ContextPaletteModal'; import { ContextType } from 'bashConstants'; import { Layer } from 'photoshop/dom/Layer'; +import { entrypoints } from 'uxp'; const events = [ 'make', @@ -56,7 +57,7 @@ export type ContexToolBarColumnProps = { contextID: string; }; -export default function ContextToolBar(props: ContexToolBarColumnProps) { +export default function LayerContextToolBar(props: ContexToolBarColumnProps) { const getContextFromStore = useContextStore( (state: ContextStoreState) => state.getContextFromStore ); @@ -190,13 +191,16 @@ export default function ContextToolBar(props: ContexToolBarColumnProps) { } /> - + {/* - popUpModal( + { + + console.log(popupRef.current); + popUpModal( popupRef, , 'Context Painter' ) + } } /> - + */} diff --git a/src/components/Context/PromptContextItem.tsx b/src/components/Context/PromptContextItem.tsx new file mode 100644 index 0000000..ccaf75f --- /dev/null +++ b/src/components/Context/PromptContextItem.tsx @@ -0,0 +1,62 @@ +import React from 'react'; + +import ContextInfoColumn from './ContextInfoColumn'; +import ContextToolColumn from './ContextToolColumn'; +import LayerContextToolBar from './LayerContextToolBar'; +import ContextSlider from './ContextSlider'; + +import _ from 'lodash'; +import LayerAIContext from 'models/LayerAIContext'; +import ContextTextarea from './ContextTextarea'; +import { ContextType } from 'bashConstants'; +import ContextTagArea from './ContextTagArea'; +import ContextObject from 'models/ContextObject'; +import RegenerationTool from 'components/RegenerationTool'; +import { RefreshIcon } from 'components/Icons/index'; +import PromptContextToolBar from './PromptContextToolBar'; +export type ContextItemProps = { + contextID: string; + contextType: ContextType; +}; + +export default function PromptContextItem(props: ContextItemProps) { + return ( +
+ + + {/*
+ + +
*/} +
+ + Consistency Strength + + + Styling Strength + + +
+
+ ); +} diff --git a/src/components/Context/PromptContextToolBar.tsx b/src/components/Context/PromptContextToolBar.tsx new file mode 100644 index 0000000..cfcca0f --- /dev/null +++ b/src/components/Context/PromptContextToolBar.tsx @@ -0,0 +1,110 @@ +import React, { FC, useRef, useState, useEffect } from 'react'; +import { + VisibilityOffRounded, + VisibilityRounded, + PaletteIcon, + GridViewIcon, + RefreshIcon, + DeleteIcon, +} from 'components/Icons'; +import { ContextStoreState, useContextStore } from 'store/contextStore'; +import { + toggleOffContextHidingTool, + toggleOnContextHidingTool, +} from 'services/tools_service'; +import { popUp, popUpModal } from 'utils/general_utils'; +import { ExtendedHTMLDialogElement } from 'common/types/htmlTypes'; +import photoshop from 'photoshop'; +import Spectrum, { Checkbox, Label, Radio } from 'react-uxp-spectrum'; +import Tool from 'components/Tool'; +import RegenerationTool from 'components/RegenerationTool'; +import ContextPainterModal from 'components/modals/ContextPaletteModal'; +import { ContextType } from 'bashConstants'; +import { Layer } from 'photoshop/dom/Layer'; +import { entrypoints } from 'uxp'; + +const events = [ + 'make', + 'select', + 'delete', + 'selectNoLayers', + 'move', + 'undoEvent', + 'undoEnum', + 'openDocument', +]; + +const ToolbarDivider = () => { + return ( +
+ ); +}; + +interface ToolSectionProps { + children: React.ReactNode; +} + +interface LayerDTO { + name: string; + id: number; +} + +const ToolSection: FC = ({ children }) => { + return
{children}
; +}; + +export type ContexToolBarColumnProps = { + contextID: string; +}; + +export default function PromptContextToolBar(props: ContexToolBarColumnProps) { + const getContextFromStore = useContextStore( + (state: ContextStoreState) => state.getContextFromStore + ); + const removeContextFromStore = useContextStore( + (state: ContextStoreState) => state.removeContextFromStore + ); + let saveContextToStore = useContextStore( + (state: ContextStoreState) => state.saveContextToStore + ); + + + let genAISettings = getContextFromStore(props.contextID, ContextType.PROMPT); + + + return ( +
+ + + + { + let copyOfContext = getContextFromStore(props.contextID, ContextType.PROMPT).copy(); + copyOfContext.is_cloud_run = + !copyOfContext.is_cloud_run; + saveContextToStore(copyOfContext); + }} + /> + + + + + removeContextFromStore( + genAISettings.id, + ContextType.PROMPT + ) + } + /> + + + +
+ ); +} diff --git a/src/components/ContextManager.tsx b/src/components/ContextManager.tsx index 7be4278..4155ab6 100644 --- a/src/components/ContextManager.tsx +++ b/src/components/ContextManager.tsx @@ -1,11 +1,12 @@ import LayerAIContext from 'models/LayerAIContext'; import React, { useEffect } from 'react'; import { ContextStoreState, useContextStore } from 'store/contextStore'; -import ContextItem from './Context/ContextItem'; +import LayerContextItem from './Context/LayerContextItem'; import { Button, Divider } from 'react-uxp-spectrum'; import { BashfulHeader } from 'components/BashfulHeader'; import ContextToolBar from './ContextManagerToolBar'; import _ from 'lodash'; +import { ContextType } from 'bashConstants'; export default function ContextManager() { const saveContextToStore = useContextStore( @@ -62,7 +63,7 @@ function ContextItems() { let context = contexts[key]; return ( <> - + void; +} + +interface DropDownOption { + displayName: string; + value: string; +} + +export default function ModelDropDown(props: ModalProps) { + + const getContextFromStore = useContextStore( + (state: ContextStoreState) => state.getContextFromStore + ); + + + const saveContextToStore = useContextStore( + (state) => state.saveContextToStore + ); + + + let { loading, value } = useAsyncEffect(async () => { + + if (props.isCloudGenerating) { + // While this does work, this is for the future where we batch run the models, currently + // we would have to make sure each local user swaps out the models when they want to use + // a different model on a specific layer. We will collect the selection of models for them + // queue them up and run them in sequence using the currently loaded model and swap only when + // necessary. + // return getAvailableModels(); + return []; + } else { + return getAvailableModelConfigs(); + } + }); + + function getDropDownOptions() { + if (loading) { + return ['loading models...']; + } else { + if (props.isCloudGenerating) { + return value + .map((modelObj: ModelResponse) => { + return modelObj.title; + }) + .filter((name: string) => name != null); + } else { + return value + .map((modelObj: ModelConfigResponse) => { + return modelObj.display_name; + }) + .filter((name: string) => name != null); + } + } + } + + function getOptionValue(optionName: string) { + + if (props.isCloudGenerating) { + return value.find((modelObj: ModelResponse) => { + return modelObj.title === optionName; + }); + + } else { + return value.find((modelObj: ModelConfigResponse) => { + return modelObj.display_name === optionName; + } + ); + } + + } + + + const [selectedOption, setSelectedOption] = React.useState(null); + + return ( +
+ + {loading ? ( + + + + + {value} + + + + ) : ( + + + {getDropDownOptions() && + getDropDownOptions().map((value: string) => { + try { + return ( + { + let newDropDownOption: DropDownOption = { + displayName: value, + value: getOptionValue(value), + }; + setSelectedOption(value) + event.target.value = newDropDownOption; + props?.onChange?.(event); + }} + selected={selectedOption == value} + + > + {value} + + ); + } catch (e) { + console.error(e); + } + })} + + ) } + + +
+w + ); +} + + diff --git a/src/components/RegenerationTool.tsx b/src/components/RegenerationTool.tsx index 2a44b16..df4e345 100644 --- a/src/components/RegenerationTool.tsx +++ b/src/components/RegenerationTool.tsx @@ -15,7 +15,8 @@ type RegenerationToolProps = { icon?: FC; label?: string; contextId: string; - newLayerDTOSelectionFunc: Function; + contextType: ContextType; + newLayerDTOSelectionFunc?: Function; }; export default function RegenerationTool(props: RegenerationToolProps) { @@ -25,43 +26,53 @@ export default function RegenerationTool(props: RegenerationToolProps) { const saveContextToStore = useContextStore( (state: ContextStoreState) => state.saveContextToStore ); - const [isHovered, setIsHovered] = useState(false); - const layerContext = getContextFromStore( + const genAISettings = getContextFromStore( props.contextId, - ContextType.LAYER + props.contextType ); - let animationRef = useRef(null); - let [animation, setAnimationTimeline] = useState(null); + async function regenerateMask(){ + // get updated context to apply + const genAISettings = getContextFromStore( + props.contextId, + props.contextType + ); + + // get mask from photoshop selection + // get layer from photoshop selection + + // save layer as image and send to server + // save selection as image and send to server + } + async function regenerateLayer( deleteOldLayer: boolean = false, - contextID: string ) { let duplicatedLayer = null; try { - const layerContext = getContextFromStore( - contextID, - ContextType.LAYER + const genAISettings = getContextFromStore( + props.contextId, + props.contextType ); - const oldLayer = layerContext.currentLayer; - let copyOfContext = layerContext.copy(); - let newLayercontext = getContextFromStore( - contextID, - ContextType.LAYER + const oldLayer = genAISettings.currentLayer; + let copyOfContext = genAISettings.copy(); + let newGenAISettings = getContextFromStore( + props.contextId, + props.contextType ); - let copyOfNewContext = newLayercontext.copy(); + let copyOfNewContext = newGenAISettings.copy(); copyOfNewContext.isGenerating = true; saveContextToStore(copyOfNewContext); - if (await layerContext.hasLayerMask()) { - duplicatedLayer = await layerContext.duplicateCurrentLayer(); + if (await genAISettings.hasLayerMask()) { + duplicatedLayer = await genAISettings.duplicateCurrentLayer(); copyOfContext.currentLayerName = duplicatedLayer.name; await copyOfContext.applyLayerMask(); } - const newLayer = await generateAILayer(layerContext); + const newLayer = await generateAILayer(genAISettings); copyOfContext.isGenerating = false; copyOfContext.currentLayerName = newLayer.name; saveContextToStore(copyOfContext); @@ -89,7 +100,13 @@ export default function RegenerationTool(props: RegenerationToolProps) { } async function handleButtonClick() { - await regenerateLayer(false, props.contextId); + if (props.contextType === ContextType.LAYER){ + await regenerateLayer(false); + + } + else if (props.contextType === ContextType.PROMPT){ + // await regenerateMaskedSection(true) + } } return ( @@ -98,8 +115,8 @@ export default function RegenerationTool(props: RegenerationToolProps) { onClick={handleButtonClick} > {/* I don't know why the logic is backwards here. */} - {!getContextFromStore(props.contextId, ContextType.LAYER) - .isGenerating ? ( + {!(getContextFromStore(props.contextId, props.contextType) + ?.isGenerating) ? (
state.getContextFromStore - ); - - let saveContextToStore = useContextStore( - (state: ContextStoreState) => state.saveContextToStore - ); - const [generatedImages, setGeneratedImages] = useState([]); - const [loadingImages, setLoadingImages] = useState(false); - const [prompt, setPrompt] = useState(''); - - // // The prompt that goes here is from this component where the user will generate images from - // // text to put into the UI - // const generateImages = async (prompt: string) => { - // if (!prompt) return; - // if (generatedImages.length > 0) setGeneratedImages([]); - // try { - // setLoadingImages(true); - // let copyOfContext = layerContext.copy(); - // copyOfContext.currentPrompt = prompt; - // copyOfContext.batchSize = 5; - // const data = await txt2img(copyOfContext); - // for (const image of data.images) { - // setGeneratedImages((oldImages) => [ - // ...oldImages, - // formatBase64Image(image), - // ]); - // } - // } catch (error) { - // console.log(error); - // } finally { - // setLoadingImages(false); - // } - // }; - return ( -
-