aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/apis/gpt/GPT.ts2
-rw-r--r--src/client/documents/Documents.ts1
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss29
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx270
-rw-r--r--src/client/views/nodes/DocumentView.scss2
-rw-r--r--src/client/views/nodes/DocumentView.tsx4
-rw-r--r--src/client/views/nodes/ImageBox.scss2
-rw-r--r--src/client/views/nodes/ImageBox.tsx104
-rw-r--r--src/client/views/smartdraw/DrawingFillHandler.tsx2
-rw-r--r--src/client/views/smartdraw/SmartDrawHandler.tsx4
10 files changed, 293 insertions, 127 deletions
diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts
index 4b0d58cc1..cf3a28a8e 100644
--- a/src/client/apis/gpt/GPT.ts
+++ b/src/client/apis/gpt/GPT.ts
@@ -260,7 +260,7 @@ const gptDescribeImage = async (image: string): Promise<string> => {
content: [
{
type: 'text',
- text: `Briefly identify what this drawing is, naming all the drawing elements and their location within the image. Do not include anything about the drawing style.`,
+ text: `Very briefly identify what this drawing is and list all the drawing elements and their location within the image. Do not include anything about the drawing style.`,
},
{
type: 'image_url',
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 7f1387ff8..0bff74ac1 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -19,6 +19,7 @@ import { DocServer } from '../DocServer';
import { dropActionType } from '../util/DropActionTypes';
import { CollectionViewType, DocumentType } from './DocumentTypes';
import { Id } from '../../fields/FieldSymbols';
+import { FireflyImageData } from '../views/smartdraw/FireflyConstants';
class EmptyBox {
public static LayoutString() {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index 2c94446fb..dff2cb282 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -304,3 +304,32 @@
display: none;
}
}
+
+.collectionFreeformView-aiView {
+ text-align: center;
+ font-weight: bold;
+ width: 100%;
+
+ .collectionfreeformview-aiView-prompt {
+ height: 25px;
+ }
+
+ .collectionFreeFormView-aiView-strength {
+ text-align: center;
+ }
+
+ .collectionFreeformView-aiView-options-container,
+ .collectionFreeFormView-aiView-regenerate-container {
+ text-align: start;
+ font-weight: normal;
+ padding: 5px;
+ }
+ .collectionFreeformView-aiView-options,
+ .collectionFreeFormView-aiView-regenerate {
+ display: flex;
+ flex-direction: row;
+ gap: 10px;
+ justify-content: center;
+ align-items: center;
+ }
+}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 20b91b6e4..112bfd178 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,5 +1,5 @@
import { Bezier } from 'bezier-js';
-import { Colors } from '@dash/components';
+import { Button, Colors, Type } from '@dash/components';
import { Property } from 'csstype';
import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
@@ -67,6 +67,11 @@ import { CollectionFreeFormPannableContents } from './CollectionFreeFormPannable
import { CollectionFreeFormRemoteCursors } from './CollectionFreeFormRemoteCursors';
import './CollectionFreeFormView.scss';
import { MarqueeView } from './MarqueeView';
+import ReactLoading from 'react-loading';
+import { SettingsManager } from '../../../util/SettingsManager';
+import { Slider } from '@mui/material';
+import { AiOutlineSend } from 'react-icons/ai';
+import { DrawingFillHandler } from '../../smartdraw/DrawingFillHandler';
@observer
class CollectionFreeFormOverlayView extends React.Component<{ elements: () => ViewDefResult[] }> {
@@ -2186,84 +2191,203 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
</div>
);
}
- render() {
- TraceMobx();
+
+ @observable private _regenInput = '';
+ @observable private _drawingFillInput = '';
+ @observable private _canInteract = true;
+ @observable private _regenLoading = false;
+ @observable private _drawingFillLoading = false;
+ @observable private _fireflyRefStrength = 50;
+ // _oldDrag: HTMLElement | null = null;
+
+ // onPassiveDrag = (e: PointerEvent) => e.stopPropagation();
+ // protected createDashEventsTarget = (ele: HTMLDivElement | null) => {
+ // // this._dropDisposer?.();
+ // this._oldDrag?.removeEventListener('pointerdown', this.onPassiveDrag);
+ // this._oldDrag = ele;
+ // // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
+ // ele?.addEventListener('pointerdown', this.onPassiveDrag, { passive: false });
+ // };
+
+ componentAIViewHistory = () => {
return (
- <div
- className="collectionfreeformview-container"
- id={this._paintedId}
- ref={r => {
- this.createDashEventsTarget(r);
- this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
- this._oldWheel = r;
- // prevent wheel events from passivly propagating up through containers
- r?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
- r?.addEventListener('mouseleave', this.onMouseLeave);
- r?.addEventListener('mouseenter', this.onMouseEnter);
- }}
- onWheel={this.onPointerWheel}
- onClick={this.onClick}
- onPointerDown={this.onPointerDown}
- onPointerMove={this.onCursorMove}
- onDrop={this.onExternalDrop}
- onDragOver={e => e.preventDefault()}
- onContextMenu={this.onContextMenu}
- style={{
- pointerEvents: this._props.isContentActive() && SnappingManager.IsDragging ? 'all' : this._props.pointerEvents?.(),
- textAlign: this.isAnnotationOverlay ? 'initial' : undefined,
- transform: `scale(${this.nativeDimScaling})`,
- width: `${100 / this.nativeDimScaling}%`,
- height: this._props.getScrollHeight?.() ?? `${100 / this.nativeDimScaling}%`,
- }}>
- {Doc.ActiveTool === InkTool.Eraser && Doc.ActiveEraser === InkEraserTool.Radius && this._showEraserCircle && (
- <div
- onPointerMove={this.onCursorMove}
- style={{
- position: 'fixed',
- left: this._eraserX,
- top: this._eraserY,
- width: (ActiveEraserWidth() + 5) * 2,
- height: (ActiveEraserWidth() + 5) * 2,
- borderRadius: '50%',
- border: '1px solid gray',
- transform: 'translate(-50%, -50%)',
+ <div className="imageBox-aiView-history">
+ {/* {this._prevImgs.map(img => (
+ <img
+ className="imageBox-aiView-img"
+ src={img.href}
+ onClick={() => {
+ this.dataDoc[this.fieldKey] = new ImageField(img.pathname);
+ this.dataDoc.ai_firefly_prompt = img.prompt;
+ this.dataDoc.ai_firefly_seed = img.seed;
}}
/>
+ ))} */}
+ </div>
+ );
+ };
+
+ componentAIView = () => {
+ const showRegenerate = this.Document[DocData].ai;
+ return (
+ <div className="collectionfreeformview-aiView" onPointerDown={e => e.stopPropagation()}>
+ Edit Collection with AI
+ {showRegenerate && (
+ <div className="collectionfreeformview-aiView-regenerate-container">
+ <text className="collectionfreeformview-aiView-subtitle">Regenerate AI Image</text>
+ <div className="collectionfreeformview-aiView-regenerate">
+ <input
+ className="collectionfreeformview-aiView-input"
+ aria-label="Edit instructions input"
+ type="text"
+ value={this._regenInput}
+ onChange={action(e => this._canInteract && (this._regenInput = e.target.value))}
+ placeholder="Prompt (Optional)"
+ />
+ <Button
+ text="Regenerate"
+ type={Type.SEC}
+ icon={this._regenLoading ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <AiOutlineSend />}
+ iconPlacement="right"
+ onClick={action(async () => {
+ this._regenLoading = true;
+ SmartDrawHandler.Instance.CreateDrawingDoc = this.createDrawingDoc;
+ SmartDrawHandler.Instance.AddDrawing = this.addDrawing;
+ SmartDrawHandler.Instance.RemoveDrawing = this.removeDrawing;
+ await SmartDrawHandler.Instance.regenerate([this.Document], undefined, undefined, this._regenInput, true);
+ this._regenLoading = false;
+ })}
+ />
+ </div>
+ </div>
)}
- {this.paintFunc ? (
- <FormattedTextBox {...this.props} /> // need this so that any live dashfieldviews will update the underlying text that the code eval reads
- ) : this._lightboxDoc ? (
- <div style={{ padding: 15, width: '100%', height: '100%' }}>
- <DocumentView
- {...this._props}
- Document={this._lightboxDoc}
- containerViewPath={this.DocumentView?.().docViewPath}
- TemplateDataDocument={undefined}
- PanelWidth={this.lightboxPanelWidth}
- PanelHeight={this.lightboxPanelHeight}
- NativeWidth={returnZero}
- NativeHeight={returnZero}
- onClickScript={this.onChildClickHandler}
- onKey={this.onKeyDown}
- onDoubleClickScript={this.onChildDoubleClickHandler}
- childFilters={this.childDocFilters}
- childFiltersByRanges={this.childDocRangeFilters}
- searchFilterDocs={this.searchFilterDocs}
- isDocumentActive={this._props.childDocumentsActive?.() ? this._props.isDocumentActive : this.isContentActive}
- isContentActive={this._props.childContentsActive ?? emptyFunction}
- addDocTab={this.addDocTab}
- ScreenToLocalTransform={this.lightboxScreenToLocal}
- fitContentsToBox={undefined}
- focus={this.focus}
+ <div className="collectionfreeformview-aiView-options-container">
+ <text className="collectionfreeformview-aiView-subtitle"> Create Image with Firefly </text>
+ <div className="collectionfreeformview-aiView-options">
+ <input className="collectionfreeformview-aiView-prompt" placeholder="Prompt (Optional)" type="text" value={this._drawingFillInput} onChange={action(e => this._canInteract && (this._drawingFillInput = e.target.value))} />
+ <div className="collectionfreeformview-aiView-strength">
+ Reference Strength
+ <Slider
+ className="collectionfreeformview-aiView-slider"
+ sx={{
+ '& .MuiSlider-track': { color: SettingsManager.userVariantColor },
+ '& .MuiSlider-rail': { color: SettingsManager.userBackgroundColor },
+ '& .MuiSlider-thumb': { color: SettingsManager.userVariantColor, '&.Mui-focusVisible, &:hover, &.Mui-active': { boxShadow: `0px 0px 0px 8px${SettingsManager.userColor.slice(0, 7)}10` } },
+ }}
+ min={1}
+ max={100}
+ step={1}
+ size="small"
+ value={this._fireflyRefStrength}
+ onChange={action((e, val) => this._canInteract && (this._fireflyRefStrength = val as number))}
+ valueLabelDisplay="auto"
+ />
+ </div>
+ <Button
+ text="Send"
+ type={Type.SEC}
+ icon={this._drawingFillLoading && this._drawingFillInput !== '' ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <AiOutlineSend />}
+ iconPlacement="right"
+ onClick={undoable(
+ action(() => {
+ this._drawingFillLoading = true;
+ DrawingFillHandler.drawingToImage(
+ this.props.Document,
+ this._fireflyRefStrength,
+ this._drawingFillInput !== '' ? this._drawingFillInput : StrCast(this.props.Document.title) !== 'grouping' ? StrCast(this.props.Document.title) : ''
+ );
+ this._drawingFillInput = '';
+ this._drawingFillLoading = false;
+ }),
+ 'create image'
+ )}
/>
</div>
- ) : (
- <>
- {this._firstRender ? this.placeholder : this.marqueeView}
- {this._props.noOverlay ? null : <CollectionFreeFormOverlayView elements={this.elementFunc} />}
- {!this.GroupChildDrag ? null : <div className="collectionFreeForm-groupDropper" />}
- </>
- )}
+ </div>
+ </div>
+ );
+ };
+
+ render() {
+ TraceMobx();
+ return (
+ <div>
+ <div
+ className="collectionfreeformview-container"
+ id={this._paintedId}
+ ref={r => {
+ this.createDashEventsTarget(r);
+ this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
+ this._oldWheel = r;
+ // prevent wheel events from passivly propagating up through containers
+ r?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
+ r?.addEventListener('mouseleave', this.onMouseLeave);
+ r?.addEventListener('mouseenter', this.onMouseEnter);
+ }}
+ onWheel={this.onPointerWheel}
+ onClick={this.onClick}
+ onPointerDown={this.onPointerDown}
+ onPointerMove={this.onCursorMove}
+ onDrop={this.onExternalDrop}
+ onDragOver={e => e.preventDefault()}
+ onContextMenu={this.onContextMenu}
+ style={{
+ pointerEvents: this._props.isContentActive() && SnappingManager.IsDragging ? 'all' : this._props.pointerEvents?.(),
+ textAlign: this.isAnnotationOverlay ? 'initial' : undefined,
+ transform: `scale(${this.nativeDimScaling})`,
+ width: `${100 / this.nativeDimScaling}%`,
+ height: this._props.getScrollHeight?.() ?? `${100 / this.nativeDimScaling}%`,
+ }}>
+ {Doc.ActiveTool === InkTool.Eraser && Doc.ActiveEraser === InkEraserTool.Radius && this._showEraserCircle && (
+ <div
+ onPointerMove={this.onCursorMove}
+ style={{
+ position: 'fixed',
+ left: this._eraserX,
+ top: this._eraserY,
+ width: (ActiveEraserWidth() + 5) * 2,
+ height: (ActiveEraserWidth() + 5) * 2,
+ borderRadius: '50%',
+ border: '1px solid gray',
+ transform: 'translate(-50%, -50%)',
+ }}
+ />
+ )}
+ {this.paintFunc ? (
+ <FormattedTextBox {...this.props} /> // need this so that any live dashfieldviews will update the underlying text that the code eval reads
+ ) : this._lightboxDoc ? (
+ <div style={{ padding: 15, width: '100%', height: '100%' }}>
+ <DocumentView
+ {...this._props}
+ Document={this._lightboxDoc}
+ containerViewPath={this.DocumentView?.().docViewPath}
+ TemplateDataDocument={undefined}
+ PanelWidth={this.lightboxPanelWidth}
+ PanelHeight={this.lightboxPanelHeight}
+ NativeWidth={returnZero}
+ NativeHeight={returnZero}
+ onClickScript={this.onChildClickHandler}
+ onKey={this.onKeyDown}
+ onDoubleClickScript={this.onChildDoubleClickHandler}
+ childFilters={this.childDocFilters}
+ childFiltersByRanges={this.childDocRangeFilters}
+ searchFilterDocs={this.searchFilterDocs}
+ isDocumentActive={this._props.childDocumentsActive?.() ? this._props.isDocumentActive : this.isContentActive}
+ isContentActive={this._props.childContentsActive ?? emptyFunction}
+ addDocTab={this.addDocTab}
+ ScreenToLocalTransform={this.lightboxScreenToLocal}
+ fitContentsToBox={undefined}
+ focus={this.focus}
+ />
+ </div>
+ ) : (
+ <>
+ {this._firstRender ? this.placeholder : this.marqueeView}
+ {this._props.noOverlay ? null : <CollectionFreeFormOverlayView elements={this.elementFunc} />}
+ {!this.GroupChildDrag ? null : <div className="collectionFreeForm-groupDropper" />}
+ </>
+ )}
+ </div>
</div>
);
}
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index 82195b9c1..a3d47290a 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -281,6 +281,8 @@
.documentView-editorView {
width: 100%;
overflow-y: scroll;
+ justify-items: center;
+ background-color: rgb(223, 223, 223);
.documentView-editorView-resizer {
height: 5px;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 622eccc4f..d656bcf50 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -716,8 +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;
+ rpw = () => this._props.PanelWidth() / 2;
+ rph = () => this.panelHeight() / 2;
@computed get viewBoxContents() {
TraceMobx();
const isInk = this.layoutDoc._layout_isSvg && !this._props.LayoutTemplateString;
diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss
index e083f52b4..9532f4ad3 100644
--- a/src/client/views/nodes/ImageBox.scss
+++ b/src/client/views/nodes/ImageBox.scss
@@ -159,8 +159,6 @@
.imageBox-aiView {
text-align: center;
font-weight: bold;
- align-content: center;
- height: 100%;
.imageBox-aiView-subtitle {
position: relative;
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 778d52a8d..db8bb2c6e 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, Button, Type } from '@dash/components';
+import { Colors, Button, Type, Size } from '@dash/components';
import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { extname } from 'path';
@@ -76,6 +76,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return FieldView.LayoutString(ImageBox, fieldKey);
}
_ffref = React.createRef<CollectionFreeFormView>();
+ _oldWheel: HTMLElement | null = null;
private _ignoreScroll = false;
private _forcedScroll = false;
private _dropDisposer?: DragManager.DragDropDisposer;
@@ -94,6 +95,12 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@observable private _error = '';
@observable private _isHovering = false; // flag to switch between primary and alternate images on hover
+ // variables for AI Image Editor
+ @observable private _regenInput = '';
+ @observable private _canInteract = true;
+ @observable private _regenerateLoading = false;
+ @observable private _prevImgs: FireflyImageData[] = [];
+
constructor(props: FieldViewProps) {
super(props);
makeObservable(this);
@@ -529,25 +536,34 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
);
}
- @observable private _regenInput = '';
- @observable private _canInteract = true;
- @observable private _regenerateLoading = false;
- @observable private _prevImgs: FireflyImageData[] = [];
+ onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
+
+ protected createDashEventsTarget = (ele: HTMLDivElement | null) => {
+ // this._dropDisposer?.();
+ this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
+ this._oldWheel = ele;
+ // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
+ ele?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
+ };
componentAIViewHistory = () => {
return (
- <div className="imageBox-aiView-history">
+ <div className="imageBox-aiView-history" ref={this.createDashEventsTarget}>
+ <Button text="Clear History" type={Type.SEC} size={Size.XSMALL} />
{this._prevImgs.map(img => (
- <img
- key={img.pathname}
- className="imageBox-aiView-img"
- src={img.href}
- onClick={() => {
- this.dataDoc[this.fieldKey] = new ImageField(img.pathname);
- this.dataDoc.ai_firefly_prompt = img.prompt;
- this.dataDoc.ai_firefly_seed = img.seed;
- }}
- />
+ <div>
+ <img
+ key={img.pathname}
+ className="imageBox-aiView-img"
+ src={img.href}
+ onClick={() => {
+ this.dataDoc[this.fieldKey] = new ImageField(img.pathname);
+ this.dataDoc.ai_firefly_prompt = img.prompt;
+ this.dataDoc.ai_firefly_seed = img.seed;
+ }}
+ />
+ <text>{img.prompt}</text>
+ </div>
))}
</div>
);
@@ -557,7 +573,14 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const field = this.dataDoc[this.fieldKey] instanceof ImageField ? Cast(this.dataDoc[this.fieldKey], ImageField, null) : new ImageField(String(this.dataDoc[this.fieldKey]));
const showRegenerate = this.Document[DocData].ai;
return (
- <div className="imageBox-aiView">
+ <div
+ className="imageBox-aiView"
+ ref={(ele: HTMLDivElement | null) => {
+ this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
+ this._oldWheel = ele;
+ // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
+ ele?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
+ }}>
Edit Image with AI
{showRegenerate && (
<div className="imageBox-aiView-regenerate-container">
@@ -566,11 +589,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
<input
className="imageBox-aiView-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
@@ -579,33 +600,24 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// style={{ alignSelf: 'flex-end' }}
icon={this._regenerateLoading ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <AiOutlineSend />}
iconPlacement="right"
- onClick={undoable(
- action(async () => {
- this._regenerateLoading = true;
- await SmartDrawHandler.Instance.regenerate([this.Document], undefined, undefined, this._regenInput, true).then(newImgs => {
- if (newImgs[0]) {
- const url = newImgs[0].pathname;
- const imgField = new ImageField(url);
- this._prevImgs.length === 0 &&
- this._prevImgs.push({ prompt: StrCast(this.dataDoc.ai_firefly_prompt), seed: NumCast(this.dataDoc.ai_firefly_seed), href: this.paths.lastElement(), pathname: field.url.pathname });
- this.dataDoc[this.fieldKey] = imgField;
- this._prevImgs.unshift({ prompt: newImgs[0].prompt, seed: newImgs[0].seed, href: this.paths.lastElement(), pathname: url });
- this._regenerateLoading = false;
- this._regenInput = '';
- }
- });
- }),
- 'regenerate image'
- )}
- />
- <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}
+ onClick={action(async () => {
+ this._regenerateLoading = true;
+ SmartDrawHandler.Instance.regenerate([this.Document], undefined, undefined, this._regenInput, true).then(newImgs => {
+ if (newImgs[0]) {
+ const url = newImgs[0].pathname;
+ const imgField = new ImageField(url);
+ this._prevImgs.length === 0 &&
+ this._prevImgs.push({ prompt: StrCast(this.dataDoc.ai_firefly_prompt), seed: this.dataDoc.ai_firefly_seed as number, href: this.paths.lastElement(), pathname: field.url.pathname });
+ this._prevImgs.unshift({ prompt: newImgs[0].prompt, seed: newImgs[0].seed, href: this.paths.lastElement(), pathname: url });
+ this.dataDoc.ai_firefly_history = `${this._prevImgs}`;
+ this.dataDoc[this.fieldKey] = imgField;
+ this._regenerateLoading = false;
+ this._regenInput = '';
+ }
+ });
+ })}
/>
+ <Button text="Get Variations" type={Type.SEC} iconPlacement="right" />
</div>
</div>
)}
@@ -707,8 +719,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const { nativeWidth: width, nativeHeight: height } = await Networking.PostToServer('/inspectImage', { source: this.paths[0] });
return { width, height };
};
-
savedAnnotations = () => this._savedAnnotations;
+
render() {
TraceMobx();
const borderRad = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BorderRounding) as string;
diff --git a/src/client/views/smartdraw/DrawingFillHandler.tsx b/src/client/views/smartdraw/DrawingFillHandler.tsx
index 96b21123b..423e3b2ac 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 => {
Networking.PostToServer('/queryFireflyImageFromStructure',
- { prompt: user_prompt || prompt, width: dims.width, height: dims.height, structureUrl, strength, styles })
+ { prompt: `${user_prompt}, ${prompt}`, width: dims.width, height: dims.height, structureUrl, strength, styles })
.then((info: Upload.ImageInformation) =>
DocumentViewInternal.addDocTabFunc(Docs.Create.ImageDocument(info.accessPaths.agnostic.client,
{ ai: 'firefly', ai_firefly_prompt: user_prompt || prompt, _width: 500, data_nativeWidth: info.nativeWidth, data_nativeHeight: info.nativeHeight }), OpenWhere.addRight)
diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx
index e9d88b315..4052ea852 100644
--- a/src/client/views/smartdraw/SmartDrawHandler.tsx
+++ b/src/client/views/smartdraw/SmartDrawHandler.tsx
@@ -272,14 +272,14 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
this._lastInput.text = input;
const dims = FireflyDimensionsMap[this._imgDims];
return Networking.PostToServer('/queryFireflyImage', { prompt: input, width: dims.width, height: dims.height, seed: seed }).then(img => {
+ const seed = img.accessPaths.agnostic.client.match(/\/(\d+)upload/)[1];
if (!changeInPlace) {
- const aiseed = img.accessPaths.agnostic.client.match(/\/(\d+)upload/)[1];
const imgDoc: Doc = Docs.Create.ImageDocument(img.accessPaths.agnostic.client, {
title: input.match(/^(.*?)~~~.*$/)?.[1] || input,
nativeWidth: dims.width,
nativeHeight: dims.height,
ai: 'firefly',
- ai_firefly_seed: aiseed,
+ ai_firefly_seed: seed,
ai_firefly_prompt: input,
});
DocumentViewInternal.addDocTabFunc(imgDoc, OpenWhere.addRight);