diff options
author | bobzel <zzzman@gmail.com> | 2025-02-28 14:52:39 -0500 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2025-02-28 14:52:39 -0500 |
commit | 532f0fa22281fef1e35e3d0a6064ee57e4673253 (patch) | |
tree | f9c8c9db02bdc5de70467226681784482d1e978d /src/client/views/nodes/ImageBox.tsx | |
parent | 2838b8d98ab88df974fd52ba96cf5046d99298cb (diff) |
added drop target for regenerating images
Diffstat (limited to 'src/client/views/nodes/ImageBox.tsx')
-rw-r--r-- | src/client/views/nodes/ImageBox.tsx | 90 |
1 files changed, 61 insertions, 29 deletions
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 55474cb7e..d122ca5b0 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -36,7 +36,7 @@ import { OverlayView } from '../OverlayView'; import { AnchorMenu } from '../pdf/AnchorMenu'; import { PinDocView, PinProps } from '../PinFuncs'; import { DrawingFillHandler } from '../smartdraw/DrawingFillHandler'; -import { FireflyImageData, isFireflyImageData } from '../smartdraw/FireflyConstants'; +import { FireflyImageData, FireflyImageDimensions, isFireflyImageData } from '../smartdraw/FireflyConstants'; import { SmartDrawHandler } from '../smartdraw/SmartDrawHandler'; import { StickerPalette } from '../smartdraw/StickerPalette'; import { StyleProp } from '../StyleProp'; @@ -45,6 +45,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import { FocusViewOptions } from './FocusViewOptions'; import './ImageBox.scss'; import { OpenWhere } from './OpenWhere'; +import { RichTextField } from '../../../fields/RichTextField'; export class ImageEditorData { // eslint-disable-next-line no-use-before-define @@ -83,6 +84,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { private _disposers: { [name: string]: IReactionDisposer } = {}; private _getAnchor: (savedAnnotations: Opt<ObservableMap<number, HTMLDivElement[]>>, addAsAnnotation: boolean) => Opt<Doc> = () => undefined; private _overlayIconRef = React.createRef<HTMLDivElement>(); + private _regenerateIconRef = React.createRef<HTMLDivElement>(); private _mainCont: HTMLDivElement | null = null; private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef(); imageRef: HTMLImageElement | null = null; // <video> ref @@ -196,36 +198,47 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { this._searchInput = selection; }; - drop = undoable((e: Event, de: DragManager.DropEvent) => { - if (de.complete.docDragData) { - let added: boolean | undefined; - const targetIsBullseye = (ele: HTMLElement): boolean => { - if (!ele) return false; - if (ele === this._overlayIconRef.current) return true; - return targetIsBullseye(ele.parentElement as HTMLElement); - }; - if (de.metaKey || targetIsBullseye(e.target as HTMLElement)) { - added = de.complete.docDragData.droppedDocuments.reduce((last: boolean, drop: Doc) => { - this.layoutDoc[this.fieldKey + '_usePath'] = 'alternate:hover'; - return last && Doc.AddDocToList(this.dataDoc, this.fieldKey + '_alternates', drop); - }, true); - } else if (de.altKey || !this.dataDoc[this.fieldKey]) { - const layoutDoc = de.complete.docDragData?.draggedDocuments[0]; - const targetField = Doc.LayoutFieldKey(layoutDoc); - const targetDoc = layoutDoc[DocData]; - if (targetDoc[targetField] instanceof ImageField) { - added = true; - this.dataDoc[this.fieldKey] = ObjectField.MakeCopy(targetDoc[targetField] as ImageField); - Doc.SetNativeWidth(this.dataDoc, Doc.NativeWidth(targetDoc), this.fieldKey); - Doc.SetNativeHeight(this.dataDoc, Doc.NativeHeight(targetDoc), this.fieldKey); + drop = undoable( + action((e: Event, de: DragManager.DropEvent) => { + if (de.complete.docDragData) { + let added: boolean | undefined; + const hitDropTarget = (ele: HTMLElement, dropTarget: HTMLDivElement | null): boolean => { + if (!ele) return false; + if (ele === dropTarget) return true; + return hitDropTarget(ele.parentElement as HTMLElement, dropTarget); + }; + if (de.metaKey || hitDropTarget(e.target as HTMLElement, this._overlayIconRef.current)) { + added = de.complete.docDragData.droppedDocuments.reduce((last: boolean, drop: Doc) => { + this.layoutDoc[this.fieldKey + '_usePath'] = 'alternate:hover'; + return last && Doc.AddDocToList(this.dataDoc, this.fieldKey + '_alternates', drop); + }, true); + } else if (hitDropTarget(e.target as HTMLElement, this._regenerateIconRef.current)) { + this._regenerateLoading = true; + const drag = de.complete.docDragData.draggedDocuments.lastElement(); + const dragField = drag[Doc.LayoutFieldKey(drag)]; + const oldPrompt = StrCast(this.Document.ai_firefly_prompt, StrCast(this.Document.title)); + const newPrompt = (text: string) => (oldPrompt ? `${oldPrompt} ~~~ ${text}` : text); + DrawingFillHandler.drawingToImage(this.Document, 100, newPrompt(dragField instanceof RichTextField ? dragField.Text : ''), drag)?.then(action(() => (this._regenerateLoading = false))); + added = false; + } else if (de.altKey || !this.dataDoc[this.fieldKey]) { + const layoutDoc = de.complete.docDragData?.draggedDocuments[0]; + const targetField = Doc.LayoutFieldKey(layoutDoc); + const targetDoc = layoutDoc[DocData]; + if (targetDoc[targetField] instanceof ImageField) { + added = true; + this.dataDoc[this.fieldKey] = ObjectField.MakeCopy(targetDoc[targetField] as ImageField); + Doc.SetNativeWidth(this.dataDoc, Doc.NativeWidth(targetDoc), this.fieldKey); + Doc.SetNativeHeight(this.dataDoc, Doc.NativeHeight(targetDoc), this.fieldKey); + } } + added === false && e.preventDefault(); + added !== undefined && e.stopPropagation(); + return added; } - added === false && e.preventDefault(); - added !== undefined && e.stopPropagation(); - return added; - } - return false; - }, 'image drop'); + return false; + }), + 'image drop' + ); @undoBatch resolution = () => { @@ -485,6 +498,24 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { </Tooltip> ); } + @computed get regenerateImageIcon() { + return ( + <div + className="imageBox-regenerateDropTarget" + ref={this._regenerateIconRef} + onClick={() => DocumentView.showDocument(DocCast(this.Document.ai_firefly_generatedDocs), { openLocation: OpenWhere.addRight })} + style={{ + display: (this._props.isContentActive() && (SnappingManager.CanEmbed || this.Document.ai_firefly_generatedDocs)) || this._regenerateLoading ? 'block' : 'none', + transform: `scale(${this.uiBtnScaling})`, + width: this._sideBtnWidth, + height: this._sideBtnWidth, + background: 'transparent', + // color: SettingsManager.userBackgroundColor, + }}> + {this._regenerateLoading ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width="100%" height="100%" /> : <FontAwesomeIcon icon="portrait" color={SettingsManager.userColor} size="lg" />} + </div> + ); + } @computed get paths() { const field = this.dataDoc[this.fieldKey] instanceof ImageField ? Cast(this.dataDoc[this.fieldKey], ImageField, null) : new ImageField(String(this.dataDoc[this.fieldKey])); // retrieve the primary image URL that is being rendered from the data doc @@ -807,6 +838,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { <ReactLoading type="spin" height={50} width={50} color={'blue'} /> </div> ) : null} + {this.regenerateImageIcon} {this.overlayImageIcon} {this.annotationLayer} {!this._mainCont || !this.DocumentView || !this._annotationLayer.current ? null : ( |