aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/smartdraw/SmartDrawHandler.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/smartdraw/SmartDrawHandler.tsx')
-rw-r--r--src/client/views/smartdraw/SmartDrawHandler.tsx95
1 files changed, 59 insertions, 36 deletions
diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx
index d24cc9d50..24046bb83 100644
--- a/src/client/views/smartdraw/SmartDrawHandler.tsx
+++ b/src/client/views/smartdraw/SmartDrawHandler.tsx
@@ -7,15 +7,16 @@ import { ObservableReactComponent } from '../ObservableReactComponent';
import { Button, IconButton } from 'browndash-components';
import ReactLoading from 'react-loading';
import { AiOutlineSend } from 'react-icons/ai';
-// import './ImageLabelHandler.scss';
import { gptAPICall, GPTCallType } from '../../apis/gpt/GPT';
-import { InkData } from '../../../fields/InkField';
+import { InkData, InkTool } from '../../../fields/InkField';
import { SVGToBezier } from '../../util/bezierFit';
const { parse } = require('svgson');
import { Slider, Switch } from '@mui/material';
import { Doc } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { DocumentView } from '../nodes/DocumentView';
+import { BoolCast, NumCast, StrCast } from '../../../fields/Types';
+import './SmartDrawHandler.scss';
export interface DrawingOptions {
text: string;
@@ -43,7 +44,8 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
@observable private _size: number = 200;
@observable private _autoColor: boolean = true;
@observable private _regenInput: string = '';
- private _addFunc: (e: React.PointerEvent<Element>, strokeList: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void = () => {};
+ @observable private _canInteract: boolean = true;
+ private _addFunc: (strokeList: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void = () => {};
private _deleteFunc: (doc?: Doc) => void = () => {};
private _lastInput: DrawingOptions = { text: '', complexity: 5, size: 300, autoColor: true, x: 0, y: 0 };
private _lastResponse: string = '';
@@ -57,12 +59,12 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
@action
setUserInput = (input: string) => {
- this._userInput = input;
+ if (this._canInteract) this._userInput = input;
};
@action
setRegenInput = (input: string) => {
- this._regenInput = input;
+ if (this._canInteract) this._regenInput = input;
};
@action
@@ -72,21 +74,21 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
@action
setComplexity = (val: number) => {
- this._complexity = val;
+ if (this._canInteract) this._complexity = val;
};
@action
setSize = (val: number) => {
- this._size = val;
+ if (this._canInteract) this._size = val;
};
@action
setAutoColor = () => {
- this._autoColor = !this._autoColor;
+ if (this._canInteract) this._autoColor = !this._autoColor;
};
@action
- displaySmartDrawHandler = (x: number, y: number, addFunc: (e: React.PointerEvent<Element>, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void, deleteFunc: (doc?: Doc) => void) => {
+ displaySmartDrawHandler = (x: number, y: number, addFunc: (strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void, deleteFunc: (doc?: Doc) => void) => {
this._pageX = x;
this._pageY = y;
this._display = true;
@@ -95,16 +97,18 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
};
@action
- displayRegenerate = (x: number, y: number, addFunc: (e: React.PointerEvent<Element>, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void, deleteFunc: (doc?: Doc) => void) => {
+ displayRegenerate = (x: number, y: number, addFunc: (strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void, deleteFunc: (doc?: Doc) => void) => {
this._selectedDoc = DocumentView.SelectedDocs().lastElement();
const docData = this._selectedDoc[DocData];
this._addFunc = addFunc;
this._deleteFunc = deleteFunc;
this._pageX = x;
this._pageY = y;
+ this._display = false;
this._showRegenerate = true;
- this._lastResponse = docData.drawingData as string;
- this._lastInput = { text: docData.drawingInput as string, complexity: docData.drawingComplexity as number, size: docData.drawingSize as number, autoColor: docData.drawingColored as boolean, x: this._pageX, y: this._pageY };
+ this._showEditBox = false;
+ 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 };
};
@action
@@ -117,7 +121,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
this._complexity = 5;
this._size = 300;
this._autoColor = true;
- // this._regenInput = ''
+ Doc.ActiveTool = InkTool.None;
};
@action
@@ -127,12 +131,25 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
this._regenInput = '';
};
+ @action
+ handleKeyPress = async (event: React.KeyboardEvent) => {
+ if (event.key === 'Enter') {
+ if (this._showRegenerate) {
+ this.regenerate();
+ } else {
+ await this.drawWithGPT({ X: this._pageX, Y: this._pageY }, this._userInput);
+ this._userInput = '';
+ }
+ }
+ };
+
_errorOccurredOnce = false;
@action
- drawWithGPT = async (e: React.PointerEvent<Element>, input: string) => {
+ drawWithGPT = async (startPt: { X: number; Y: number }, input: string) => {
if (input === '') return;
- this._lastInput = { text: input, complexity: this._complexity, size: this._size, autoColor: this._autoColor, x: e.clientX, y: e.clientY };
+ this._lastInput = { text: input, complexity: this._complexity, size: this._size, autoColor: this._autoColor, x: startPt.X, y: startPt.Y };
this._isLoading = true;
+ this._canInteract = false;
this._showOptions = false;
try {
const res = await gptAPICall(`"${input}", "${this._complexity}", "${this._size}"`, GPTCallType.DRAW, undefined, true);
@@ -141,20 +158,22 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
return;
}
console.log(res);
- await this.parseResponse(e, res, { X: e.clientX, Y: e.clientY }, false);
+ const strokeData = await this.parseResponse(res, startPt, false);
this.hideSmartDrawHandler();
this._showRegenerate = true;
this._errorOccurredOnce = false;
+ this._isLoading = false;
+ this._canInteract = true;
+ return strokeData;
} catch (err) {
if (this._errorOccurredOnce) {
console.error('GPT call failed', err);
this._errorOccurredOnce = false;
} else {
this._errorOccurredOnce = true;
- this.drawWithGPT(e, input);
+ this.drawWithGPT(startPt, input);
}
}
- this._isLoading = false;
};
@action
@@ -163,14 +182,15 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
};
@action
- regenerate = async (e: React.PointerEvent<Element>) => {
+ regenerate = async () => {
this._isLoading = true;
+ this._canInteract = false;
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}`;
+ 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);
}
@@ -179,25 +199,26 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
return;
}
console.log(res);
- this.parseResponse(e, res, { X: this._lastInput.x, Y: this._lastInput.y }, true);
+ this.parseResponse(res, { X: this._lastInput.x, Y: this._lastInput.y }, true);
} catch (err) {
console.error('GPT call failed', err);
}
this._isLoading = false;
+ this._canInteract = true;
this._regenInput = '';
this._showEditBox = false;
};
@action
- parseResponse = async (e: React.PointerEvent<Element>, res: string, startPoint: { X: number; Y: number }, regenerate: boolean) => {
+ parseResponse = async (res: string, startPoint: { X: number; Y: number }, regenerate: boolean) => {
const svg = res.match(/<svg[^>]*>([\s\S]*?)<\/svg>/g);
+ console.log(svg);
console.log('start point is', startPoint);
if (svg) {
this._lastResponse = svg[0];
const svgObject = await parse(svg[0]);
const svgStrokes: any = svgObject.children;
const strokeData: [InkData, string, string][] = [];
- console.log('autocolor is', this._autoColor);
svgStrokes.forEach((child: any) => {
const convertedBezier: InkData = SVGToBezier(child.name, child.attributes);
strokeData.push([
@@ -210,10 +231,11 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
});
if (regenerate) {
this._deleteFunc(this._selectedDoc);
- this._addFunc(e, strokeData, this._lastInput, svg[0], this._selectedDoc);
+ this._addFunc(strokeData, this._lastInput, svg[0], this._selectedDoc);
} else {
- this._addFunc(e, strokeData, this._lastInput, svg[0]);
+ this._addFunc(strokeData, this._lastInput, svg[0]);
}
+ return { data: strokeData, lastInput: this._lastInput, lastRes: svg[0] };
}
};
@@ -222,7 +244,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
return (
<div
id="label-handler"
- className="contextMenu-cont"
+ className="smart-draw-handler"
style={{
display: this._display ? '' : 'none',
left: this._pageX,
@@ -242,8 +264,9 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
style={{ width: '19px' }}
/>
<input
- aria-label="label-input"
- id="new-label"
+ aria-label="Smart Draw Input"
+ className="smartdraw-input"
+ id="smartdraw-input"
type="text"
style={{ color: 'black' }}
value={this._userInput}
@@ -251,7 +274,9 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
this.setUserInput(e.target.value);
}}
placeholder="Enter item to draw"
+ onKeyDown={this.handleKeyPress}
/>
+ <IconButton tooltip="Advanced Options" icon={<FontAwesomeIcon icon={this._showOptions ? 'caret-down' : 'caret-right'} />} color={SettingsManager.userColor} style={{ width: '14px' }} onClick={this.setShowOptions} />
<Button
style={{ alignSelf: 'flex-end' }}
text="Send"
@@ -259,7 +284,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
iconPlacement="right"
color={SettingsManager.userColor}
onClick={e => {
- this.drawWithGPT(e as React.PointerEvent<Element>, this._userInput);
+ this.drawWithGPT({ X: e.clientX, Y: e.clientY }, this._userInput);
}}
/>
</div>
@@ -349,7 +374,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
return (
<div
id="smartdraw-options-menu"
- className="contextMenu-cont"
+ className="smart-draw-handler"
style={{
left: this._pageX,
...(this._yRelativeToTop ? { top: Math.max(0, this._pageY) } : { bottom: this._pageY }),
@@ -365,9 +390,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
tooltip="Regenerate"
icon={this._isLoading && this._regenInput === '' ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <FontAwesomeIcon icon={'rotate'} />}
color={SettingsManager.userColor}
- onClick={e => {
- this.regenerate(e as React.PointerEvent<Element>);
- }}
+ onClick={this.regenerate}
/>
<IconButton tooltip="Edit with GPT" icon={<FontAwesomeIcon icon="pen-to-square" />} color={SettingsManager.userColor} onClick={this.edit} />
{this._showEditBox && (
@@ -378,6 +401,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
}}>
<input
aria-label="Edit instructions input"
+ className="smartdraw-input"
id="regen-input"
type="text"
style={{ color: 'black' }}
@@ -385,6 +409,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
onChange={e => {
this.setRegenInput(e.target.value);
}}
+ onKeyDown={this.handleKeyPress}
placeholder="Edit instructions"
/>
<Button
@@ -393,9 +418,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
icon={this._isLoading && this._regenInput !== '' ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <AiOutlineSend />}
iconPlacement="right"
color={SettingsManager.userColor}
- onClick={e => {
- this.regenerate(e as React.PointerEvent<Element>);
- }}
+ onClick={this.regenerate}
/>
</div>
)}