diff options
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 2 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/smartdraw/SmartDrawHandler.tsx | 488 |
3 files changed, 196 insertions, 296 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index cdf5505f8..ec8898b93 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -386,7 +386,6 @@ pie title Minerals in my tap water {key: "Script", creator: opts => Docs.Create.ScriptingDocument(null, opts), opts: { _width: 200, _height: 250, }}, {key: "DataViz", creator: opts => Docs.Create.DataVizDocument("/users/rz/Downloads/addresses.csv", opts), opts: { _width: 300, _height: 300 }}, {key: "Chat", creator: Docs.Create.ChatDocument, opts: { _width: 300, _height: 300, }}, - {key: "AnnoPalette",creator: Docs.Create.AnnoPaletteDocument, opts: {_width: 300, _height: 300, _dropAction: dropActionType.move }}, {key: "Header", creator: headerTemplate, opts: { _width: 300, _height: 120, _header_pointerEvents: "all", _header_height: 50, _header_fontSize: 9,_layout_autoHeightMargins: 50, _layout_autoHeight: true, treeView_HideUnrendered: true}}, {key: "ViewSlide", creator: slideView, opts: { _width: 400, _height: 300, _xMargin: 3, _yMargin: 3,}}, {key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 30, _type_collection: CollectionViewType.Stacking, dropAction: dropActionType.embed, treeView_HideTitle: true, _layout_fitWidth:true, layout_boxShadow: "0 0" }}, @@ -429,7 +428,6 @@ pie title Minerals in my tap water { toolTip: "Tap or drag to create a bullet slide", title: "PPT Slide", icon: "person-chalkboard", dragFactory: doc.emptySlide as Doc, clickFactory: DocCast(doc.emptySlide), openFactoryLocation: OpenWhere.overlay,funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a view slide", title: "View Slide", icon: "address-card", dragFactory: doc.emptyViewSlide as Doc, clickFactory: DocCast(doc.emptyViewSlide), openFactoryLocation: OpenWhere.overlay,funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a data note", title: "DataNote", icon: "window-maximize", dragFactory: doc.emptyHeader as Doc, clickFactory: DocCast(doc.emptyHeader), openFactoryAsDelegate: true, funcs: { hidden: "IsNoviceMode()"} }, - { toolTip: "Tap or drag to create an annotation palette",title: "Annotation Palette", icon: "palette", dragFactory: doc.emptyAnnoPalette as Doc, clickFactory: DocCast(doc.emptyAnnoPalette)}, { toolTip: "Toggle a Calculator REPL", title: "replviewer", icon: "calculator", clickFactory: '<ScriptingRepl />' as unknown as Doc, openFactoryLocation: OpenWhere.overlay}, // hack: clickFactory is not a Doc but will get interpreted as a custom UI by the openDoc() onClick script // { toolTip: "Toggle an UndoStack", title: "undostacker", icon: "calculator", clickFactory: "<UndoStack />" as any, openFactoryLocation: OpenWhere.overlay}, ].map(tuple => ( diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index c0f01383d..76549a423 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -2006,7 +2006,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection SmartDrawHandler.Instance.CreateDrawingDoc = this.createDrawingDoc; SmartDrawHandler.Instance.AddDrawing = this.addDrawing; SmartDrawHandler.Instance.RemoveDrawing = this.removeDrawing; - !SmartDrawHandler.Instance._showRegenerate ? SmartDrawHandler.Instance.displayRegenerate(this._downX, this._downY - 10) : SmartDrawHandler.Instance.hideRegenerate(); + !SmartDrawHandler.Instance.ShowRegenerate ? SmartDrawHandler.Instance.displayRegenerate(this._downX, this._downY - 10) : SmartDrawHandler.Instance.hideRegenerate(); }), icon: 'pen-to-square', }); diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx index aa10dcead..59d362d26 100644 --- a/src/client/views/smartdraw/SmartDrawHandler.tsx +++ b/src/client/views/smartdraw/SmartDrawHandler.tsx @@ -1,29 +1,29 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Slider, Switch } from '@mui/material'; +import { Button, IconButton } from 'browndash-components'; 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 { gptAPICall, GPTCallType, gptDrawingColor } from '../../apis/gpt/GPT'; -import { InkData, InkField, InkTool } from '../../../fields/InkField'; -import { SVGToBezier, SVGType } from '../../util/bezierFit'; +import ReactLoading from 'react-loading'; import { INode, parse } from 'svgson'; -import { Slider, Switch } from '@mui/material'; +import { unimplementedFunction } from '../../../Utils'; import { Doc, DocListCast } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; -import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, DocumentView } from '../nodes/DocumentView'; +import { InkData, InkField, InkTool } from '../../../fields/InkField'; import { BoolCast, ImageCast, NumCast, StrCast } from '../../../fields/Types'; -import './SmartDrawHandler.scss'; -import { unimplementedFunction } from '../../../Utils'; +import { ImageField } from '../../../fields/URLField'; +import { GPTCallType, gptAPICall, gptDrawingColor } from '../../apis/gpt/GPT'; import { Docs } from '../../documents/Documents'; -import { MarqueeView } from '../collections/collectionFreeForm'; -import { ImageField, URLField } from '../../../fields/URLField'; -import { CollectionCardView } from '../collections/CollectionCardDeckView'; +import { SettingsManager } from '../../util/SettingsManager'; +import { undoable } from '../../util/UndoManager'; +import { SVGToBezier, SVGType } from '../../util/bezierFit'; import { InkingStroke } from '../InkingStroke'; -import { undoBatch } from '../../util/UndoManager'; +import { ObservableReactComponent } from '../ObservableReactComponent'; +import { CollectionCardView } from '../collections/CollectionCardDeckView'; +import { MarqueeView } from '../collections/collectionFreeForm'; +import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, DocumentView } from '../nodes/DocumentView'; +import './SmartDrawHandler.scss'; export interface DrawingOptions { text: string; @@ -35,10 +35,14 @@ export interface DrawingOptions { } @observer -// eslint-disable-next-line @typescript-eslint/no-empty-object-type -export class SmartDrawHandler extends ObservableReactComponent<{}> { +export class SmartDrawHandler extends ObservableReactComponent<object> { static Instance: SmartDrawHandler; + private _lastInput: DrawingOptions = { text: '', complexity: 5, size: 350, autoColor: true, x: 0, y: 0 }; + private _lastResponse: string = ''; + private _selectedDoc: Doc | undefined = undefined; + private _errorOccurredOnce = false; + @observable private _display: boolean = false; @observable private _pageX: number = 0; @observable private _pageY: number = 0; @@ -47,18 +51,21 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { @observable private _userInput: string = ''; @observable private _showOptions: boolean = false; @observable private _showEditBox: boolean = false; - @observable public _showRegenerate: boolean = false; @observable private _complexity: number = 5; @observable private _size: number = 200; @observable private _autoColor: boolean = true; @observable private _regenInput: string = ''; @observable private _canInteract: boolean = true; - private _lastInput: DrawingOptions = { text: '', complexity: 5, size: 350, autoColor: true, x: 0, y: 0 }; - private _lastResponse: string = ''; - private _selectedDoc: Doc | undefined = undefined; - private _errorOccurredOnce = false; + @observable public ShowRegenerate: boolean = false; + + constructor(props: object) { + super(props); + makeObservable(this); + SmartDrawHandler.Instance = this; + } + public AddDrawing: (doc: Doc, opts: DrawingOptions, gptRes: string) => void = unimplementedFunction; public RemoveDrawing: (doc?: Doc) => void = unimplementedFunction; public CreateDrawingDoc: (strokeList: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => Doc | undefined = (strokeList: [InkData, string, string][], opts: DrawingOptions) => { const drawing: Doc[] = []; @@ -85,67 +92,21 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { drawing.push(inkDoc); }); - const collection = MarqueeView.getCollection(drawing, undefined, true, { left: 1, top: 1, width: 1, height: 1 }); - return collection; - }; - public AddDrawing: (doc: Doc, opts: DrawingOptions, gptRes: string) => void = unimplementedFunction; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - constructor(props: any) { - super(props); - makeObservable(this); - SmartDrawHandler.Instance = this; - } - - @action - setUserInput = (input: string) => { - if (this._canInteract) this._userInput = input; - }; - - @action - setRegenInput = (input: string) => { - if (this._canInteract) this._regenInput = input; - }; - - @action - setShowOptions = () => { - this._showOptions = !this._showOptions; - }; - - @action - setComplexity = (val: number) => { - if (this._canInteract) this._complexity = val; - }; - - @action - setSize = (val: number) => { - if (this._canInteract) this._size = val; - }; - - @action - setAutoColor = () => { - if (this._canInteract) this._autoColor = !this._autoColor; - }; - - @action - setEdit = () => { - this._showEditBox = !this._showEditBox; + return MarqueeView.getCollection(drawing, undefined, true, { left: 1, top: 1, width: 1, height: 1 }); }; @action displaySmartDrawHandler = (x: number, y: number) => { - this._pageX = x; - this._pageY = y; + [this._pageX, this._pageY] = [x, y]; this._display = true; }; @action displayRegenerate = (x: number, y: number) => { this._selectedDoc = DocumentView.SelectedDocs()?.lastElement(); - this._pageX = x; - this._pageY = y; + [this._pageX, this._pageY] = [x, y]; this._display = false; - this._showRegenerate = true; + this.ShowRegenerate = true; this._showEditBox = false; const docData = this._selectedDoc[DocData]; this._lastResponse = StrCast(docData.drawingData); @@ -154,7 +115,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { @action hideSmartDrawHandler = () => { - this._showRegenerate = false; + this.ShowRegenerate = false; this._display = false; this._isLoading = false; this._showOptions = false; @@ -168,17 +129,16 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { @action hideRegenerate = () => { if (!this._isLoading) { - this._showRegenerate = false; + this.ShowRegenerate = false; this._isLoading = false; this._regenInput = ''; this._lastInput = { text: '', complexity: 5, size: 350, autoColor: true, x: 0, y: 0 }; } }; - @action - handleKeyPress = async (event: React.KeyboardEvent) => { + handleKeyPress = (event: React.KeyboardEvent) => { if (event.key === 'Enter') { - await this.handleSendClick(); + this.handleSendClick(); } }; @@ -186,7 +146,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { handleSendClick = async () => { this._isLoading = true; this._canInteract = false; - if (this._showRegenerate) { + if (this.ShowRegenerate) { await this.regenerate(); this._regenInput = ''; this._showEditBox = false; @@ -195,7 +155,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { try { await this.drawWithGPT({ X: this._pageX, Y: this._pageY }, this._userInput, this._complexity, this._size, this._autoColor); this.hideSmartDrawHandler(); - this._showRegenerate = true; + this.ShowRegenerate = true; } catch (err) { if (this._errorOccurredOnce) { console.error('GPT call failed', err); @@ -222,10 +182,8 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { console.error('GPT call failed'); return; } - console.log(res); const strokeData = await this.parseSvg(res, startPt, false, autoColor); const drawingDoc = strokeData && this.CreateDrawingDoc(strokeData?.data, strokeData?.lastInput, strokeData?.lastRes); - // eslint-disable-next-line @typescript-eslint/no-unused-expressions drawingDoc && this.AddDrawing(drawingDoc, this._lastInput, res); this._errorOccurredOnce = false; @@ -254,12 +212,9 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { console.error('GPT call failed'); return; } - console.log(res); const strokeData = await this.parseSvg(res, { X: this._lastInput.x, Y: this._lastInput.y }, true, lastInput?.autoColor || this._autoColor); - // eslint-disable-next-line @typescript-eslint/no-unused-expressions this.RemoveDrawing !== unimplementedFunction && this.RemoveDrawing(this._selectedDoc); const drawingDoc = strokeData && this.CreateDrawingDoc(strokeData?.data, strokeData?.lastInput, strokeData?.lastRes); - // eslint-disable-next-line @typescript-eslint/no-unused-expressions drawingDoc && this.AddDrawing(drawingDoc, this._lastInput, res); return strokeData; } catch (err) { @@ -278,13 +233,10 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { const svgObject = await parse(svg[0]); const svgStrokes: INode[] = svgObject.children; const strokeData: [InkData, string, string][] = []; - // eslint-disable-next-line @typescript-eslint/no-explicit-any svgStrokes.forEach(child => { const convertedBezier: InkData = SVGToBezier(child.name as SVGType, 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 }; - }), + convertedBezier.map(point => ({ X: point.X + startPoint.X - this._size / 1.5, Y: point.Y + startPoint.Y - this._size / 2 })), (regenerate ? this._lastInput.autoColor : autoColor) ? child.attributes.stroke : '', (regenerate ? this._lastInput.autoColor : autoColor) ? child.attributes.fill : '', ]); @@ -298,7 +250,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { */ colorWithGPT = async (drawing: Doc) => { const img = await this.getIcon(drawing); - const { href } = (img as URLField).url; + const { href } = ImageCast(img).url; const hrefParts = href.split('.'); const hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`; try { @@ -308,20 +260,9 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { strokes.forEach((stroke, i) => { const inkingStroke = DocumentView.getDocumentView(stroke)?.ComponentView as InkingStroke; const { inkData } = inkingStroke.inkScaledData(); - coords.push( - `${i + 1}. ${inkData - .filter((point, index) => { - return index % 4 === 0 || index == inkData.length - 1; - }) - .map(point => { - return `(${point.X.toString()}, ${point.Y.toString()})`; - })}` - ); + coords.push(`${i + 1}. ${inkData.filter((point, index) => index % 4 === 0 || index == inkData.length - 1).map(point => `(${point.X.toString()}, ${point.Y.toString()})`)}`); }); - const response = await gptDrawingColor(hrefBase64, coords); - console.log(response); - const colorResponse = await gptAPICall(response, GPTCallType.COLOR, undefined); - console.log(colorResponse); + const colorResponse = await gptDrawingColor(hrefBase64, coords).then(response => gptAPICall(response, GPTCallType.COLOR, undefined)); this.colorStrokes(colorResponse, drawing); } catch (error) { console.log('GPT call failed', error); @@ -331,8 +272,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { /** * Function that parses the GPT color response and sets the selected stroke(s) to the new color. */ - @undoBatch - colorStrokes = (res: string, drawing: Doc) => { + colorStrokes = undoable((res: string, drawing: Doc) => { const colorList = res.match(/\{.*?\}/g); const strokes = DocListCast(drawing[DocData].data); colorList?.forEach((colors, index) => { @@ -341,213 +281,175 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { strokes[index][DocData].color = strokeAndFill[0]; const inkStroke = DocumentView.getDocumentView(strokes[index])?.ComponentView as InkingStroke; const { inkData } = inkStroke.inkScaledData(); - // eslint-disable-next-line @typescript-eslint/no-unused-expressions InkingStroke.IsClosed(inkData) ? (strokes[index][DocData].fillColor = strokeAndFill[1]) : (strokes[index][DocData].fillColor = undefined); } }); - }; + }, 'color strokes'); /** * Gets an image snapshot of a doc. In this class, it's used to snapshot a selected ink stroke/group to use for GPT color. */ async getIcon(doc: Doc) { const docView = DocumentView.getDocumentView(doc); - console.log(doc); if (docView) { - console.log(docView); docView.ComponentView?.updateIcon?.(); return new Promise<ImageField | undefined>(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 1000)); } return undefined; } - render() { - if (this._display) { - return ( - <div - id="label-handler" - className="smart-draw-handler" - 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="Smart Draw Input" - className="smartdraw-input" - id="smartdraw-input" - type="text" - style={{ color: 'black' }} - value={this._userInput} - onChange={e => { - 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" - icon={this._isLoading ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <AiOutlineSend />} - iconPlacement="right" - color={SettingsManager.userColor} - onClick={this.handleSendClick} - /> - </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} - value={this._autoColor} - 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> - </> - )} + renderDisplay() { + return ( + <div + id="label-handler" + className="smart-draw-handler" + 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="Smart Draw Input" + className="smartdraw-input" + type="text" + style={{ color: 'black' }} + value={this._userInput} + onChange={action(e => this._canInteract && (this._userInput = 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={action(() => (this._showOptions = !this._showOptions))} + /> + <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={this.handleSendClick} + /> </div> - ); - } else if (this._showRegenerate) { - return ( - <div - id="smartdraw-options-menu" - className="smart-draw-handler" - 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={this.handleSendClick} - /> - <IconButton tooltip="Edit with GPT" icon={<FontAwesomeIcon icon="pen-to-square" />} color={SettingsManager.userColor} onClick={this.setEdit} /> - {this._showEditBox && ( - <div - style={{ - display: 'flex', - flexDirection: 'row', - }}> - <input - aria-label="Edit instructions input" - className="smartdraw-input" - id="regen-input" - type="text" - style={{ color: 'black' }} - value={this._regenInput} - onChange={e => { - this.setRegenInput(e.target.value); - }} - onKeyDown={this.handleKeyPress} - 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={this.handleSendClick} - /> - </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} + value={this._autoColor} + size="small" + onChange={action(e => this._canInteract && (this._autoColor = !this._autoColor))} + /> + </div> + <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', width: '31%' }}> + Complexity + <Slider + sx={{ + '& .MuiSlider-track': { color: SettingsManager.userVariantColor }, + '& .MuiSlider-rail': { color: SettingsManager.userColor }, + '& .MuiSlider-thumb': { color: SettingsManager.userColor, '&.Mui-focusVisible, &:hover, &.Mui-active': { boxShadow: `0px 0px 0px 8px${SettingsManager.userColor.slice(0, 7)}10` } }, + }} + style={{ width: '80%' }} + min={1} + max={10} + step={1} + size="small" + value={this._complexity} + onChange={action((e, val) => this._canInteract && (this._complexity = val as number))} + valueLabelDisplay="auto" + /> + </div> + <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', width: '39%' }}> + Size (in pixels) + <Slider + sx={{ + '& .MuiSlider-track': { color: SettingsManager.userVariantColor }, + '& .MuiSlider-rail': { color: SettingsManager.userColor }, + '& .MuiSlider-thumb': { color: SettingsManager.userColor, '&.Mui-focusVisible, &:hover, &.Mui-active': { boxShadow: `0px 0px 0px 8px${SettingsManager.userColor.slice(0, 7)}20` } }, + }} + style={{ width: '80%' }} + min={50} + max={700} + step={10} + size="small" + value={this._size} + onChange={action((e, val) => this._canInteract && (this._size = val as number))} + valueLabelDisplay="auto" + /> + </div> </div> + )} + </div> + ); + } + + renderRegenerate() { + return ( + <div + className="smart-draw-handler" + 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={this.handleSendClick} + /> + <IconButton tooltip="Edit with GPT" icon={<FontAwesomeIcon icon="pen-to-square" />} color={SettingsManager.userColor} onClick={action(() => (this._showEditBox = !this._showEditBox))} /> + {this._showEditBox && ( + <div style={{ display: 'flex', flexDirection: 'row' }}> + <input + aria-label="Edit instructions input" + className="smartdraw-input" + type="text" + style={{ color: 'black' }} + value={this._regenInput} + onChange={action(e => this._canInteract && (this._regenInput = e.target.value))} + onKeyDown={this.handleKeyPress} + 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={this.handleSendClick} + /> + </div> + )} </div> - ); - } else { - return <></>; - } + </div> + ); + } + + render() { + return this._display ? this.renderDisplay() : this.ShowRegenerate ? this.renderRegenerate() : null; } } |