diff options
Diffstat (limited to 'src/client/views/smartdraw/SmartDrawHandler.tsx')
| -rw-r--r-- | src/client/views/smartdraw/SmartDrawHandler.tsx | 409 |
1 files changed, 0 insertions, 409 deletions
diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx deleted file mode 100644 index d24cc9d50..000000000 --- a/src/client/views/smartdraw/SmartDrawHandler.tsx +++ /dev/null @@ -1,409 +0,0 @@ -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, makeObservable, observable } from 'mobx'; -import { observer } from 'mobx-react'; -import React from 'react'; -import { SettingsManager } from '../../util/SettingsManager'; -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 { 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'; - -export interface DrawingOptions { - text: string; - complexity: number; - size: number; - autoColor: boolean; - x: number; - y: number; -} - -@observer -export class SmartDrawHandler extends ObservableReactComponent<{}> { - static Instance: SmartDrawHandler; - - @observable private _display: boolean = false; - @observable private _pageX: number = 0; - @observable private _pageY: number = 0; - @observable private _yRelativeToTop: boolean = true; - @observable private _isLoading: boolean = false; - @observable private _userInput: string = ''; - @observable private _showOptions: boolean = false; - @observable private _showEditBox: boolean = false; - @observable private _showRegenerate: boolean = false; - @observable private _complexity: number = 5; - @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 = () => {}; - private _deleteFunc: (doc?: Doc) => void = () => {}; - private _lastInput: DrawingOptions = { text: '', complexity: 5, size: 300, autoColor: true, x: 0, y: 0 }; - private _lastResponse: string = ''; - private _selectedDoc: Doc | undefined = undefined; - - constructor(props: any) { - super(props); - makeObservable(this); - SmartDrawHandler.Instance = this; - } - - @action - setUserInput = (input: string) => { - this._userInput = input; - }; - - @action - setRegenInput = (input: string) => { - this._regenInput = input; - }; - - @action - setShowOptions = () => { - this._showOptions = !this._showOptions; - }; - - @action - setComplexity = (val: number) => { - this._complexity = val; - }; - - @action - setSize = (val: number) => { - this._size = val; - }; - - @action - setAutoColor = () => { - 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) => { - this._pageX = x; - this._pageY = y; - this._display = true; - this._addFunc = addFunc; - this._deleteFunc = deleteFunc; - }; - - @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) => { - this._selectedDoc = DocumentView.SelectedDocs().lastElement(); - const docData = this._selectedDoc[DocData]; - this._addFunc = addFunc; - this._deleteFunc = deleteFunc; - this._pageX = x; - this._pageY = y; - 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 }; - }; - - @action - hideSmartDrawHandler = () => { - this._showRegenerate = false; - this._display = false; - this._isLoading = false; - this._showOptions = false; - this._userInput = ''; - this._complexity = 5; - this._size = 300; - this._autoColor = true; - // this._regenInput = '' - }; - - @action - hideRegenerate = () => { - this._showRegenerate = false; - this._isLoading = false; - this._regenInput = ''; - }; - - _errorOccurredOnce = false; - @action - drawWithGPT = async (e: React.PointerEvent<Element>, 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._isLoading = true; - this._showOptions = false; - try { - const res = await gptAPICall(`"${input}", "${this._complexity}", "${this._size}"`, GPTCallType.DRAW, undefined, true); - if (!res) { - console.error('GPT call failed'); - return; - } - console.log(res); - await this.parseResponse(e, res, { X: e.clientX, Y: e.clientY }, false); - this.hideSmartDrawHandler(); - this._showRegenerate = true; - this._errorOccurredOnce = false; - } catch (err) { - if (this._errorOccurredOnce) { - console.error('GPT call failed', err); - this._errorOccurredOnce = false; - } else { - this._errorOccurredOnce = true; - this.drawWithGPT(e, input); - } - } - this._isLoading = false; - }; - - @action - edit = () => { - this._showEditBox = !this._showEditBox; - }; - - @action - regenerate = async (e: React.PointerEvent<Element>) => { - this._isLoading = true; - 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; - } - console.log(res); - this.parseResponse(e, res, { X: this._lastInput.x, Y: this._lastInput.y }, true); - } catch (err) { - console.error('GPT call failed', err); - } - this._isLoading = false; - this._regenInput = ''; - this._showEditBox = false; - }; - - @action - parseResponse = async (e: React.PointerEvent<Element>, res: string, startPoint: { X: number; Y: number }, regenerate: boolean) => { - const svg = res.match(/<svg[^>]*>([\s\S]*?)<\/svg>/g); - 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([ - convertedBezier.map(point => { - return { X: point.X + startPoint.X - this._size / 1.5, Y: point.Y + startPoint.Y - this._size / 2 }; - }), - (regenerate ? this._lastInput.autoColor : this._autoColor) ? child.attributes.stroke : undefined, - (regenerate ? this._lastInput.autoColor : this._autoColor) ? child.attributes.fill : undefined, - ]); - }); - if (regenerate) { - this._deleteFunc(this._selectedDoc); - this._addFunc(e, strokeData, this._lastInput, svg[0], this._selectedDoc); - } else { - this._addFunc(e, strokeData, this._lastInput, svg[0]); - } - } - }; - - render() { - if (this._display) { - return ( - <div - id="label-handler" - className="contextMenu-cont" - style={{ - display: this._display ? '' : 'none', - left: this._pageX, - ...(this._yRelativeToTop ? { top: Math.max(0, this._pageY) } : { bottom: this._pageY }), - background: SettingsManager.userBackgroundColor, - color: SettingsManager.userColor, - }}> - <div> - <IconButton - tooltip={'Cancel'} - onClick={() => { - this.hideSmartDrawHandler(); - this.hideRegenerate(); - }} - icon={<FontAwesomeIcon icon="xmark" />} - color={SettingsManager.userColor} - style={{ width: '19px' }} - /> - <input - aria-label="label-input" - id="new-label" - type="text" - style={{ color: 'black' }} - value={this._userInput} - onChange={e => { - this.setUserInput(e.target.value); - }} - placeholder="Enter item to draw" - /> - <Button - style={{ alignSelf: 'flex-end' }} - text="Send" - icon={this._isLoading ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <AiOutlineSend />} - iconPlacement="right" - color={SettingsManager.userColor} - onClick={e => { - this.drawWithGPT(e as React.PointerEvent<Element>, this._userInput); - }} - /> - </div> - {this._showOptions && ( - <> - <div style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-around' }}> - <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', width: '30%' }}> - Auto color - <Switch - sx={{ - '& .MuiSwitch-switchBase.Mui-checked': { - color: SettingsManager.userColor, - }, - '& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track': { - backgroundColor: SettingsManager.userVariantColor, - }, - }} - defaultChecked={true} - size="small" - onChange={this.setAutoColor} - /> - </div> - <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', width: '31%' }}> - Complexity - <Slider - sx={{ - '& .MuiSlider-thumb': { - color: SettingsManager.userColor, - '&.Mui-focusVisible, &:hover, &.Mui-active': { - boxShadow: `0px 0px 0px 8px${SettingsManager.userColor.slice(0, 7)}10`, - }, - }, - '& .MuiSlider-track': { - color: SettingsManager.userVariantColor, - }, - '& .MuiSlider-rail': { - color: SettingsManager.userColor, - }, - }} - style={{ width: '80%' }} - min={1} - max={10} - step={1} - size="small" - value={this._complexity} - onChange={(e, val) => { - this.setComplexity(val as number); - }} - valueLabelDisplay="auto" - /> - </div> - <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', width: '39%' }}> - Size (in pixels) - <Slider - sx={{ - '& .MuiSlider-thumb': { - color: SettingsManager.userColor, - '&.Mui-focusVisible, &:hover, &.Mui-active': { - boxShadow: `0px 0px 0px 8px${SettingsManager.userColor.slice(0, 7)}20`, - }, - }, - '& .MuiSlider-track': { - color: SettingsManager.userVariantColor, - }, - '& .MuiSlider-rail': { - color: SettingsManager.userColor, - }, - }} - style={{ width: '80%' }} - min={50} - max={700} - step={10} - size="small" - value={this._size} - onChange={(e, val) => { - this.setSize(val as number); - }} - valueLabelDisplay="auto" - /> - </div> - </div> - </> - )} - </div> - ); - } else if (this._showRegenerate) { - return ( - <div - id="smartdraw-options-menu" - className="contextMenu-cont" - style={{ - left: this._pageX, - ...(this._yRelativeToTop ? { top: Math.max(0, this._pageY) } : { bottom: this._pageY }), - background: SettingsManager.userBackgroundColor, - color: SettingsManager.userColor, - }}> - <div - style={{ - display: 'flex', - flexDirection: 'row', - }}> - <IconButton - 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>); - }} - /> - <IconButton tooltip="Edit with GPT" icon={<FontAwesomeIcon icon="pen-to-square" />} color={SettingsManager.userColor} onClick={this.edit} /> - {this._showEditBox && ( - <div - style={{ - display: 'flex', - flexDirection: 'row', - }}> - <input - aria-label="Edit instructions input" - id="regen-input" - type="text" - style={{ color: 'black' }} - value={this._regenInput} - onChange={e => { - this.setRegenInput(e.target.value); - }} - placeholder="Edit instructions" - /> - <Button - style={{ alignSelf: 'flex-end' }} - text="Send" - 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>); - }} - /> - </div> - )} - </div> - </div> - ); - } else { - return <></>; - } - } -} |
