diff options
author | eleanor-park <eleanor_park@brown.edu> | 2025-01-05 23:47:18 -0500 |
---|---|---|
committer | eleanor-park <eleanor_park@brown.edu> | 2025-01-05 23:47:18 -0500 |
commit | 1d62d867621b293c41ff8488ca5a3bd6010723d5 (patch) | |
tree | 0abc9d9ae2869775cfcc294838c93577fbc0fef9 /src/client/views/nodes/ImageBox.tsx | |
parent | 6e7cb570f9bad527cd4772bb5c715dd588fb77df (diff) |
added AI image editor
Diffstat (limited to 'src/client/views/nodes/ImageBox.tsx')
-rw-r--r-- | src/client/views/nodes/ImageBox.tsx | 113 |
1 files changed, 111 insertions, 2 deletions
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} />; |