From 51a9f85b4ddc38ac825efcefc0c6db23f3b9914e Mon Sep 17 00:00:00 2001
From: eleanor-park <eleanor_park@brown.edu>
Date: Thu, 9 Jan 2025 11:19:31 -0500
Subject: added ai editor to collections

---
 src/client/views/nodes/ImageBox.tsx | 73 ++++++++++++++++++++++---------------
 1 file changed, 44 insertions(+), 29 deletions(-)

(limited to 'src/client/views/nodes/ImageBox.tsx')

diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index fe069eacc..db8bb2c6e 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, Button, Type } from '@dash/components';
+import { Colors, Button, Type, Size } from '@dash/components';
 import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import { extname } from 'path';
@@ -76,6 +76,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         return FieldView.LayoutString(ImageBox, fieldKey);
     }
     _ffref = React.createRef<CollectionFreeFormView>();
+    _oldWheel: HTMLElement | null = null;
     private _ignoreScroll = false;
     private _forcedScroll = false;
     private _dropDisposer?: DragManager.DragDropDisposer;
@@ -94,6 +95,12 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     @observable private _error = '';
     @observable private _isHovering = false; // flag to switch between primary and alternate images on hover
 
+    // variables for AI Image Editor
+    @observable private _regenInput = '';
+    @observable private _canInteract = true;
+    @observable private _regenerateLoading = false;
+    @observable private _prevImgs: FireflyImageData[] = [];
+
     constructor(props: FieldViewProps) {
         super(props);
         makeObservable(this);
@@ -529,25 +536,34 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         );
     }
 
-    @observable private _regenInput = '';
-    @observable private _canInteract = true;
-    @observable private _regenerateLoading = false;
-    @observable private _prevImgs: FireflyImageData[] = [];
+    onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
+
+    protected createDashEventsTarget = (ele: HTMLDivElement | null) => {
+        // this._dropDisposer?.();
+        this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
+        this._oldWheel = ele;
+        // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
+        ele?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
+    };
 
     componentAIViewHistory = () => {
         return (
-            <div className="imageBox-aiView-history">
+            <div className="imageBox-aiView-history" ref={this.createDashEventsTarget}>
+                <Button text="Clear History" type={Type.SEC} size={Size.XSMALL} />
                 {this._prevImgs.map(img => (
-                    <img
-                        key={img.pathname}
-                        className="imageBox-aiView-img"
-                        src={img.href}
-                        onClick={() => {
-                            this.dataDoc[this.fieldKey] = new ImageField(img.pathname);
-                            this.dataDoc.ai_firefly_prompt = img.prompt;
-                            this.dataDoc.ai_firefly_seed = img.seed;
-                        }}
-                    />
+                    <div>
+                        <img
+                            key={img.pathname}
+                            className="imageBox-aiView-img"
+                            src={img.href}
+                            onClick={() => {
+                                this.dataDoc[this.fieldKey] = new ImageField(img.pathname);
+                                this.dataDoc.ai_firefly_prompt = img.prompt;
+                                this.dataDoc.ai_firefly_seed = img.seed;
+                            }}
+                        />
+                        <text>{img.prompt}</text>
+                    </div>
                 ))}
             </div>
         );
@@ -557,7 +573,14 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         const field = this.dataDoc[this.fieldKey] instanceof ImageField ? Cast(this.dataDoc[this.fieldKey], ImageField, null) : new ImageField(String(this.dataDoc[this.fieldKey]));
         const showRegenerate = this.Document[DocData].ai;
         return (
-            <div className="imageBox-aiView">
+            <div
+                className="imageBox-aiView"
+                ref={(ele: HTMLDivElement | null) => {
+                    this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
+                    this._oldWheel = ele;
+                    // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
+                    ele?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
+                }}>
                 Edit Image with AI
                 {showRegenerate && (
                     <div className="imageBox-aiView-regenerate-container">
@@ -566,11 +589,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                             <input
                                 className="imageBox-aiView-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
@@ -587,22 +608,16 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                                             const imgField = new ImageField(url);
                                             this._prevImgs.length === 0 &&
                                                 this._prevImgs.push({ prompt: StrCast(this.dataDoc.ai_firefly_prompt), seed: this.dataDoc.ai_firefly_seed as number, href: this.paths.lastElement(), pathname: field.url.pathname });
-                                            this.dataDoc[this.fieldKey] = imgField;
                                             this._prevImgs.unshift({ prompt: newImgs[0].prompt, seed: newImgs[0].seed, href: this.paths.lastElement(), pathname: url });
+                                            this.dataDoc.ai_firefly_history = `${this._prevImgs}`;
+                                            this.dataDoc[this.fieldKey] = imgField;
                                             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}
-                            />
+                            <Button text="Get Variations" type={Type.SEC} iconPlacement="right" />
                         </div>
                     </div>
                 )}
@@ -704,8 +719,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         const { nativeWidth: width, nativeHeight: height } = await Networking.PostToServer('/inspectImage', { source: this.paths[0] });
         return { width, height };
     };
-
     savedAnnotations = () => this._savedAnnotations;
+
     render() {
         TraceMobx();
         const borderRad = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BorderRounding) as string;
-- 
cgit v1.2.3-70-g09d2

