aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/documents/Documents.ts6
-rw-r--r--src/client/util/CurrentUserUtils.ts2
-rw-r--r--src/client/views/DocumentButtonBar.tsx7
-rw-r--r--src/client/views/ViewBoxInterface.ts1
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx12
-rw-r--r--src/client/views/nodes/DocumentView.tsx22
-rw-r--r--src/client/views/nodes/ImageBox.scss28
-rw-r--r--src/client/views/nodes/ImageBox.tsx113
-rw-r--r--src/client/views/pdf/AnchorMenu.tsx12
-rw-r--r--src/client/views/smartdraw/DrawingFillHandler.tsx2
-rw-r--r--src/client/views/smartdraw/SmartDrawHandler.tsx92
-rw-r--r--src/client/views/smartdraw/StickerPalette.tsx17
-rw-r--r--src/server/ApiManagers/FireflyManager.ts1
13 files changed, 235 insertions, 80 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 785af3409..7f1387ff8 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -517,9 +517,9 @@ export class DocumentOptions {
card_sort?: STRt = new StrInfo('way cards are sorted in deck view');
card_sort_isDesc?: BOOLt = new BoolInfo('whether the cards are sorted ascending or descending');
- ai_generated?: boolean; // to mark items as ai generated
- firefly_seed?: number;
- firefly_prompt?: string;
+ ai?: string; // to mark items as ai generated
+ ai_firefly_seed?: number;
+ ai_firefly_prompt?: string;
}
export const DocOptions = new DocumentOptions();
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 9af79a02e..b41fd09dc 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -779,7 +779,7 @@ pie title Minerals in my tap water
{ title: " Size", toolTip: "Size of area pencil eraser", btnType: ButtonType.NumberSliderButton, toolType: InkProperty.EraserWidth,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"NotRadiusEraser()"}, numBtnMin: 1, linearBtnWidth:40},
{ title: "Mask", toolTip: "Make Stroke a Stencil Mask", btnType: ButtonType.ToggleButton, icon: "user-circle", toolType: InkProperty.Mask, scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"IsNoviceMode()" } },
{ title: "Labels", toolTip: "Show Labels Inside Shapes", btnType: ButtonType.ToggleButton, icon: "text-width", toolType: InkProperty.Labels, scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}},
- { title: "Smart Draw", toolTip: "Draw with GPT", btnType: ButtonType.ToggleButton, icon: "user-pen", toolType: InkTool.SmartDraw, scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}'}, funcs: {hidden: "IsNoviceMode()"}},
+ { title: "Smart Draw", toolTip: "Draw with AI", btnType: ButtonType.ToggleButton, icon: "user-pen", toolType: InkTool.SmartDraw, scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}'}, funcs: {hidden: "IsNoviceMode()"}},
];
}
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index b7033af3f..d722b28b5 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -319,12 +319,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (
const targetDoc = this.view0?.Document;
return !targetDoc ? null : (
<Tooltip title={<div className="dash-ai-editor-button">Edit with AI</div>}>
- <div
- className="documentButtonBar-icon"
- style={{ color: 'white' }}
- onClick={() => {
- CalendarManager.Instance.open(this.view0, targetDoc);
- }}>
+ <div className="documentButtonBar-icon" style={{ color: 'white' }} onClick={undoable(() => this.view0?.toggleAIEditor(), 'toggle AI editor')}>
<FontAwesomeIcon className="documentdecorations-icon" icon="robot" />
</div>
</Tooltip>
diff --git a/src/client/views/ViewBoxInterface.ts b/src/client/views/ViewBoxInterface.ts
index b7980d74e..df08f2564 100644
--- a/src/client/views/ViewBoxInterface.ts
+++ b/src/client/views/ViewBoxInterface.ts
@@ -60,4 +60,5 @@ export abstract class ViewBoxInterface<P> extends ObservableReactComponent<React
search?: (str: string, bwd?: boolean, clear?: boolean) => boolean;
dontRegisterView?: () => boolean; // KeyValueBox's don't want to register their views
isUnstyledView?: () => boolean; // SchemaView and KeyValue are unstyled -- not titles, no opacity, no animations
+ componentAIView?: (top: number) => JSX.Element;
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index ef0b80720..9af698ec7 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1290,12 +1290,12 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const docData = doc[DocData];
docData.title = opts.text.match(/^(.*?)~~~.*$/)?.[1] || opts.text;
docData._width = opts.size;
- docData.drawingInput = opts.text;
- docData.drawingComplexity = opts.complexity;
- docData.drawingColored = opts.autoColor;
- docData.drawingSize = opts.size;
- docData.drawingData = gptRes;
- docData.ai_generated = true;
+ docData.ai_drawing_input = opts.text;
+ docData.ai_drawing_complexity = opts.complexity;
+ docData.ai_drawing_colored = opts.autoColor;
+ docData.ai_drawing_size = opts.size;
+ docData.ai_drawing_data = gptRes;
+ docData.ai = 'gpt';
this._drawingContainer = doc;
this.addDocument(doc);
this._batch?.end();
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 048b92c71..ab58023e3 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -123,6 +123,12 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
@observable _componentView: Opt<ViewBoxInterface<FieldViewProps>> = undefined; // needs to be accessed from DocumentView wrapper class
@observable _animateScaleTime: Opt<number> = undefined; // milliseconds for animating between views. defaults to 300 if not uset
@observable _animateScalingTo = 0;
+ @observable public _showAIEditor: boolean = false;
+
+ @action
+ showAIEditor() {
+ this._showAIEditor = !this._showAIEditor;
+ }
get _contentDiv() { return this._mainCont.current; } // prettier-ignore
get _docView() { return this._props.DocumentView?.(); } // prettier-ignore
@@ -552,7 +558,6 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
appearanceItems.splice(0, 0, { description: 'Open in Lightbox', event: () => DocumentView.SetLightboxDoc(this.Document), icon: 'external-link-alt' });
}
appearanceItems.push({ description: 'Pin', event: () => this._props.pinToPres(this.Document, {}), icon: 'map-pin' });
- appearanceItems.push({ description: 'Make Image', event: () => DrawingFillHandler.drawingToImage(this.Document, StrCast(this.Document.title)), icon: 'map-pin' });
!Doc.noviceMode && templateDoc && appearanceItems.push({ description: 'Open Template ', event: () => this._props.addDocTab(templateDoc, OpenWhere.addRight), icon: 'eye' });
!appearance && appearanceItems.length && cm.addItem({ description: 'Appearance...', subitems: appearanceItems, icon: 'compass' });
@@ -711,6 +716,8 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
return this._props.styleProvider?.(doc, props, property);
};
+ rpw = () => this._props.PanelWidth() * 0.6;
+ rph = () => this.panelHeight() * 0.6;
@computed get viewBoxContents() {
TraceMobx();
const isInk = this.layoutDoc._layout_isSvg && !this._props.LayoutTemplateString;
@@ -720,7 +727,9 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
className="documentView-contentsView"
style={{
pointerEvents: (isInk || noBackground ? 'none' : this.contentPointerEvents()) ?? (this._mounted ? 'all' : 'none'),
- height: this.headerMargin ? `calc(100% - ${this.headerMargin}px)` : undefined,
+ width: this._showAIEditor ? this.rpw() : undefined,
+ height: this._showAIEditor ? this.rph() : this.headerMargin ? `calc(100% - ${this.headerMargin}px)` : undefined,
+ justifySelf: 'center',
}}>
<DocumentContentsView
{...this._props}
@@ -728,7 +737,8 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
pointerEvents={this.contentPointerEvents}
setContentViewBox={this.setContentView}
childFilters={this.childFilters}
- PanelHeight={this.panelHeight}
+ PanelHeight={this._showAIEditor ? this.rpw : this.panelHeight}
+ PanelWidth={this._showAIEditor ? this.rph : this._props.PanelWidth}
setHeight={this.setHeight}
isContentActive={this.isContentActive}
ScreenToLocalTransform={this.screenToLocalContent}
@@ -737,6 +747,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
setTitleFocus={this.setTitleFocus}
hideClickBehaviors={BoolCast(this.Document.hideClickBehaviors)}
/>
+ {this._showAIEditor && (this._componentView?.componentAIView?.(this.rph()) ?? null)}
</div>
);
}
@@ -1286,6 +1297,11 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
}
};
+ @action
+ public toggleAIEditor = () => {
+ this._docViewInternal && this._docViewInternal.showAIEditor();
+ };
+
public setTextHtmlOverlay = action((text: string | undefined, effect?: Doc) => {
this._htmlOverlayText = text;
this._htmlOverlayEffect = effect;
diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss
index 3ffda5a35..03314e90f 100644
--- a/src/client/views/nodes/ImageBox.scss
+++ b/src/client/views/nodes/ImageBox.scss
@@ -139,3 +139,31 @@
.imageBox-fadeBlocker-hover {
opacity: 0;
}
+
+.imageBox-aiView {
+ padding: 5px;
+ position: absolute;
+ overflow: scroll;
+ text-align: center;
+ font-weight: bold;
+ margin-top: 5px;
+
+ .imageBox-aiView-subtitle {
+ align-self: start;
+ }
+
+ .imageBox-aiView-regenerate-container,
+ .imageBox-aiView-options-container {
+ font-weight: normal;
+ text-align: start;
+ }
+
+ .imageBox-aiView-regenerate,
+ .imageBox-aiView-options {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ flex-direction: row;
+ gap: 5px;
+ }
+}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 7ce429f0f..f00580d77 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -1,7 +1,7 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
import axios from 'axios';
-import { Colors } from 'browndash-components';
+import { Colors, Type } from 'browndash-components';
import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { extname } from 'path';
@@ -41,6 +41,9 @@ import './ImageBox.scss';
import { OpenWhere } from './OpenWhere';
import { Upload } from '../../../server/SharedMediaTypes';
import { SmartDrawHandler } from '../smartdraw/SmartDrawHandler';
+import { Button } from 'browndash-components';
+import { SettingsManager } from '../../util/SettingsManager';
+import { AiOutlineSend } from 'react-icons/ai';
export class ImageEditorData {
// eslint-disable-next-line no-use-before-define
@@ -352,7 +355,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}),
icon: 'pencil-alt',
});
- this.layoutDoc.ai_generated &&
+ this.layoutDoc.ai &&
funcs.push({
description: 'Regenerate AI Image',
event: action(e => {
@@ -526,6 +529,112 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
);
}
+ @observable private _regenInput = '';
+ @observable private _canInteract = true;
+ @observable private _regenerateLoading = false;
+
+ componentAIView = (top: number) => {
+ const field = Cast(this.dataDoc[this.fieldKey], ImageField);
+ const showRegenerate = this.Document[DocData].ai;
+ return (
+ <div className="imageBox-aiView" style={{ top: top, width: NumCast(this.Document.width), height: NumCast(this.Document.width) - top }}>
+ Edit Image with AI
+ {showRegenerate && (
+ <div className="imageBox-aiView-regenerate-container">
+ <text className="imageBox-aiView-subtitle">Regenerate AI Image</text>
+ <div className="imageBox-aiView-regenerate">
+ <input
+ aria-label="Edit instructions input"
+ // className="smartdraw-input"
+ type="text"
+ value={this._regenInput}
+ onChange={action(e => this._canInteract && (this._regenInput = e.target.value))}
+ // onKeyDown={this.handleKeyPress}
+ placeholder="Prompt (Optional)"
+ />
+ <Button
+ text="Regenerate"
+ type={Type.SEC}
+ // style={{ alignSelf: 'flex-end' }}
+ icon={this._regenerateLoading && this._regenInput !== '' ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <AiOutlineSend />}
+ iconPlacement="right"
+ onClick={action(async () => {
+ this._regenerateLoading = true;
+ await SmartDrawHandler.Instance.regenerate([this.Document], undefined, undefined, this._regenInput);
+ this._regenerateLoading = false;
+ this._regenInput = '';
+ })}
+ />
+ <Button
+ // style={{ alignSelf: 'flex-end' }}
+ text="Get Variations"
+ type={Type.SEC}
+ // icon={this._isLoading && this._regenInput !== '' ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <AiOutlineSend />}
+ iconPlacement="right"
+ // onClick={this.handleSendClick}
+ />
+ </div>
+ </div>
+ )}
+ <div className="imageBox-aiView-options-container">
+ {showRegenerate && <text className="imageBox-aiView-subtitle"> More Image Options </text>}
+ <div className="imageBox-aiView-options">
+ <Button
+ type={Type.TERT}
+ text="Get Text"
+ icon={<FontAwesomeIcon icon="font" />}
+ color={SettingsManager.userBackgroundColor}
+ iconPlacement="right"
+ onClick={() => {
+ Networking.PostToServer('/queryFireflyImageText', {
+ file: (file => {
+ const ext = extname(file);
+ return file.replace(ext, (this._error ? '_o' : this._curSuffix) + ext);
+ })(ImageCast(this.Document[Doc.LayoutFieldKey(this.Document)])?.url.href),
+ }).then(text => alert(text));
+ }}
+ />
+ <Button
+ type={Type.TERT}
+ text="Generative Fill"
+ icon={<FontAwesomeIcon icon="fill" />}
+ color={SettingsManager.userBackgroundColor}
+ // icon={this._isLoading && this._regenInput !== '' ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <AiOutlineSend />}
+ iconPlacement="right"
+ onClick={action(() => {
+ ImageEditorData.Open = true;
+ ImageEditorData.Source = (field && this.choosePath(field.url)) || '';
+ ImageEditorData.AddDoc = this._props.addDocument;
+ ImageEditorData.RootDoc = this.Document;
+ })}
+ />
+ <Button
+ type={Type.TERT}
+ text="Expand"
+ icon={<FontAwesomeIcon icon="expand" />}
+ color={SettingsManager.userBackgroundColor}
+ // icon={this._isLoading && this._regenInput !== '' ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <AiOutlineSend />}
+ iconPlacement="right"
+ onClick={() => {
+ Networking.PostToServer('/expandImage', {
+ prompt: 'sunny skies',
+ file: (file => {
+ const ext = extname(file);
+ return file.replace(ext, (this._error ? '_o' : this._curSuffix) + ext);
+ })(ImageCast(this.Document[Doc.LayoutFieldKey(this.Document)])?.url.href),
+ }).then((info: Upload.ImageInformation) => {
+ const img = Docs.Create.ImageDocument(info.accessPaths.agnostic.client, { title: 'expand:' + this.Document.title });
+ DocUtils.assignImageInfo(info, img);
+ this._props.addDocTab(img, OpenWhere.addRight);
+ });
+ }}
+ />
+ </div>
+ </div>
+ </div>
+ );
+ };
+
@computed get annotationLayer() {
TraceMobx();
return <div className="imageBox-annotationLayer" style={{ height: this._props.PanelHeight() }} ref={this._annotationLayer} />;
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index bb8082061..2e704aa8d 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -153,12 +153,12 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
this.AddDrawingAnnotation(drawing);
const docData = drawing[DocData];
docData.title = opts.text.match(/^(.*?)~~~.*$/)?.[1] || opts.text;
- docData.drawingInput = opts.text;
- docData.drawingComplexity = opts.complexity;
- docData.drawingColored = opts.autoColor;
- docData.drawingSize = opts.size;
- docData.drawingData = gptRes;
- docData.ai_generated = true;
+ docData.ai_drawing_input = opts.text;
+ docData.ai_drawing_complexity = opts.complexity;
+ docData.ai_drawing_colored = opts.autoColor;
+ docData.ai_drawing_size = opts.size;
+ docData.ai_drawing_data = gptRes;
+ docData.ai = 'gpt';
});
pointerDown = (e: React.PointerEvent) => {
diff --git a/src/client/views/smartdraw/DrawingFillHandler.tsx b/src/client/views/smartdraw/DrawingFillHandler.tsx
index 52652d377..8e41ee105 100644
--- a/src/client/views/smartdraw/DrawingFillHandler.tsx
+++ b/src/client/views/smartdraw/DrawingFillHandler.tsx
@@ -35,7 +35,7 @@ export class DrawingFillHandler {
.then((hrefBase64: string) => gptDescribeImage(hrefBase64))
.then((prompt: string) => {
Networking.PostToServer('/queryFireflyImageFromStructure', { prompt: prompt, width: dims.width, height: dims.height, structureUrl: structureUrl, strength: strength, styles: styles }).then((info: Upload.ImageInformation) =>
- DocumentViewInternal.addDocTabFunc(Docs.Create.ImageDocument(info.accessPaths.agnostic.client, { ai_generated: true, nativeWidth: dims.width, nativeHeight: dims.height }), OpenWhere.addRight)
+ DocumentViewInternal.addDocTabFunc(Docs.Create.ImageDocument(info.accessPaths.agnostic.client, { ai: 'firefly', ai_firefly_prompt: prompt, nativeWidth: dims.width, nativeHeight: dims.height }), OpenWhere.addRight)
); // prettier-ignore
});
}
diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx
index 6c9470480..0c67c7a13 100644
--- a/src/client/views/smartdraw/SmartDrawHandler.tsx
+++ b/src/client/views/smartdraw/SmartDrawHandler.tsx
@@ -58,7 +58,7 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
private _lastInput: DrawingOptions = { text: '', complexity: 5, size: 350, autoColor: true, x: 0, y: 0 };
private _lastResponse: string = '';
- private _selectedDoc: Doc | undefined = undefined;
+ private _selectedDocs: Doc[] = [];
private _errorOccurredOnce = false;
@observable private _display: boolean = false;
@@ -144,14 +144,14 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
*/
@action
displayRegenerate = (x: number, y: number) => {
- this._selectedDoc = DocumentView.SelectedDocs()?.lastElement();
+ this._selectedDocs = [DocumentView.SelectedDocs()?.lastElement()];
[this._pageX, this._pageY] = [x, y];
this._display = false;
this.ShowRegenerate = true;
this._showEditBox = false;
- const docData = this._selectedDoc[DocData];
+ const docData = this._selectedDocs[0][DocData];
this._lastResponse = StrCast(docData.drawingData);
- this._lastInput = { text: StrCast(docData.drawingInput), complexity: NumCast(docData.drawingComplexity), size: NumCast(docData.drawingSize), autoColor: BoolCast(docData.drawingColored), x: this._pageX, y: this._pageY };
+ this._lastInput = { text: StrCast(docData.ai_drawing_input), complexity: NumCast(docData.ai_drawing_complexity), size: NumCast(docData.ai_drawing_size), autoColor: BoolCast(docData.ai_drawing_colored), x: this._pageX, y: this._pageY };
};
/**
@@ -205,8 +205,9 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
this._isLoading = true;
this._canInteract = false;
if (this.ShowRegenerate) {
- await this.regenerate();
+ await this.regenerate(this._selectedDocs);
runInAction(() => {
+ this._selectedDocs = [];
this._regenInput = '';
this._showEditBox = false;
});
@@ -253,7 +254,7 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
const strokeData = await this.parseSvg(res, startPt, false, autoColor);
const drawingDoc = strokeData && this.CreateDrawingDoc(strokeData.data, strokeData.lastInput, strokeData.lastRes);
drawingDoc && this.AddDrawing(drawingDoc, this._lastInput, res);
- this._selectedDoc = drawingDoc;
+ drawingDoc && this._selectedDocs.push(drawingDoc);
this._errorOccurredOnce = false;
return strokeData;
} else {
@@ -274,57 +275,62 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
title: input.match(/^(.*?)~~~.*$/)?.[1] || input,
nativeWidth: dims.width,
nativeHeight: dims.height,
- ai_generated: true,
- firefly_seed: img.accessPaths.agnostic.client.match(/\/(\d+)upload/)[1],
- firefly_prompt: input,
+ ai: 'firefly',
+ ai_firefly_seed: img.accessPaths.agnostic.client.match(/\/(\d+)upload/)[1],
+ ai_firefly_prompt: input,
});
DocumentViewInternal.addDocTabFunc(imgDoc, OpenWhere.addRight);
- this._selectedDoc = imgDoc;
+ this._selectedDocs.push(imgDoc);
});
};
/**
* Regenerates drawings with the option to add a specific regenerate prompt/request.
+ * @param doc the drawing Docs to regenerate
*/
@action
- regenerate = async (lastInput?: DrawingOptions, lastResponse?: string, regenInput?: string) => {
+ regenerate = async (drawingDocs: Doc[], lastInput?: DrawingOptions, lastResponse?: string, regenInput?: string) => {
if (lastInput) this._lastInput = lastInput;
if (lastResponse) this._lastResponse = lastResponse;
if (regenInput) this._regenInput = regenInput;
- if (this._generateImage) {
- if (this._regenInput !== '') {
- if (this._selectedDoc) {
- const docData = this._selectedDoc[DocData];
- const newPrompt = `${docData.firefly_prompt}, ${this._regenInput}`;
- const seed: number = docData?.firefly_seed as number;
- await this.createImageWithFirefly(newPrompt, seed);
+ await Promise.all(
+ drawingDocs.map(async doc => {
+ const docData = doc[DocData];
+ if (docData.type == 'image') {
+ const seed: number = docData?.ai_firefly_seed as number;
+ if (this._regenInput !== '') {
+ // if (this._selectedDoc) {
+ const newPrompt = `${docData.ai_firefly_prompt}, ${this._regenInput}`;
+ await this.createImageWithFirefly(newPrompt, seed);
+ // }
+ } else {
+ await this.createImageWithFirefly(this._lastInput.text || StrCast(docData.ai_firefly_prompt));
+ }
}
- } else {
- await this.createImageWithFirefly(this._lastInput.text);
- }
- }
- if (this._generateDrawing) {
- try {
- let res;
- if (this._regenInput !== '') {
- const prompt: string = `This is your previously generated svg code: ${this._lastResponse} for the user input "${this._lastInput.text}". Please regenerate it with the provided specifications.`;
- res = await gptAPICall(`"${this._regenInput}"`, GPTCallType.DRAW, prompt, true);
- this._lastInput.text = `${this._lastInput.text} ~~~ ${this._regenInput}`;
- } else {
- res = await gptAPICall(`"${this._lastInput.text}", "${this._lastInput.complexity}", "${this._lastInput.size}"`, GPTCallType.DRAW, undefined, true);
- }
- if (!res) {
- console.error('GPT call failed');
- return;
+ if (docData.type == 'collection') {
+ try {
+ let res;
+ if (this._regenInput !== '') {
+ const prompt: string = `This is your previously generated svg code: ${this._lastResponse} for the user input "${this._lastInput.text}". Please regenerate it with the provided specifications.`;
+ res = await gptAPICall(`"${this._regenInput}"`, GPTCallType.DRAW, prompt, true);
+ this._lastInput.text = `${this._lastInput.text} ~~~ ${this._regenInput}`;
+ } else {
+ res = await gptAPICall(`"${this._lastInput.text}", "${this._lastInput.complexity}", "${this._lastInput.size}"`, GPTCallType.DRAW, undefined, true);
+ }
+ if (!res) {
+ console.error('GPT call failed');
+ return;
+ }
+ const strokeData = await this.parseSvg(res, { X: this._lastInput.x, Y: this._lastInput.y }, true, lastInput?.autoColor || this._autoColor);
+ this.RemoveDrawing !== unimplementedFunction && this.RemoveDrawing(true, doc);
+ const drawingDoc = strokeData && this.CreateDrawingDoc(strokeData.data, strokeData.lastInput, strokeData.lastRes);
+ drawingDoc && this.AddDrawing(drawingDoc, this._lastInput, res);
+ } catch (err) {
+ console.error('Error regenerating drawing', err);
+ }
}
- const strokeData = await this.parseSvg(res, { X: this._lastInput.x, Y: this._lastInput.y }, true, lastInput?.autoColor || this._autoColor);
- this.RemoveDrawing !== unimplementedFunction && this.RemoveDrawing(true, this._selectedDoc);
- const drawingDoc = strokeData && this.CreateDrawingDoc(strokeData.data, strokeData.lastInput, strokeData.lastRes);
- drawingDoc && this.AddDrawing(drawingDoc, this._lastInput, res);
- } catch (err) {
- console.error('Error regenerating drawing', err);
- }
- }
+ })
+ );
};
/**
diff --git a/src/client/views/smartdraw/StickerPalette.tsx b/src/client/views/smartdraw/StickerPalette.tsx
index 352a02e32..d23763eb9 100644
--- a/src/client/views/smartdraw/StickerPalette.tsx
+++ b/src/client/views/smartdraw/StickerPalette.tsx
@@ -142,19 +142,20 @@ export class StickerPalette extends ObservableReactComponent<StickerPaletteProps
}
/**
- * Calls the draw with GPT functions in SmartDrawHandler to allow users to generate drawings straight from
+ * Calls the draw with AI functions in SmartDrawHandler to allow users to generate drawings straight from
* the sticker palette.
*/
@undoBatch
generateDrawings = action(async () => {
this._isLoading = true;
+ const prevDrawings = DocListCast(this._props.Document[DocData].data);
this._props.Document[DocData].data = undefined;
SmartDrawHandler.Instance.AddDrawing = this.addDrawing;
this._canInteract = false;
await Promise.all(
Array.from({ length: 3 }).map((_, i) => {
return this._showRegenerate
- ? SmartDrawHandler.Instance.regenerate(this._opts, this._gptRes[i], this._userInput)
+ ? SmartDrawHandler.Instance.regenerate(prevDrawings, this._opts, this._gptRes[i], this._userInput)
: SmartDrawHandler.Instance.drawWithGPT({ X: 0, Y: 0 }, this._userInput, this._opts.complexity, this._opts.size, this._opts.autoColor);
})
);
@@ -181,12 +182,12 @@ export class StickerPalette extends ObservableReactComponent<StickerPaletteProps
const focusedDrawing = DocListCast(this._props.Document.data)[cIndex];
const docData = focusedDrawing[DocData];
docData.title = this._opts.text.match(/^(.*?)~~~.*$/)?.[1] || this._opts.text;
- docData.drawingInput = this._opts.text;
- docData.drawingComplexity = this._opts.complexity;
- docData.drawingColored = this._opts.autoColor;
- docData.drawingSize = this._opts.size;
- docData.drawingData = this._gptRes[cIndex];
- docData.ai_generated = true;
+ docData.ai_drawing_input = this._opts.text;
+ docData.ai_drawing_complexity = this._opts.complexity;
+ docData.ai_drawing_colored = this._opts.autoColor;
+ docData.ai_drawing_size = this._opts.size;
+ docData.ai_drawing_data = this._gptRes[cIndex];
+ docData.ai = 'gpt';
focusedDrawing.width = this._opts.size;
docData.x = this._opts.x;
docData.y = this._opts.y;
diff --git a/src/server/ApiManagers/FireflyManager.ts b/src/server/ApiManagers/FireflyManager.ts
index cb5d7c1da..6daa5840e 100644
--- a/src/server/ApiManagers/FireflyManager.ts
+++ b/src/server/ApiManagers/FireflyManager.ts
@@ -70,7 +70,6 @@ export default class FireflyManager extends ApiManager {
);
generateImage = (prompt: string = 'a realistic illustration of a cat coding', width: number = 2048, height: number = 2048, seed?: number) => {
- console.log('DIMENSIONS', width, height);
let body = `{ "prompt": "${prompt}", "size": { "width": ${width}, "height": ${height}} }`;
if (seed) {
console.log('RECEIVED SEED', seed);