From 314f62bb5335e3fb3f25501823d41cf0cdc53cac Mon Sep 17 00:00:00 2001
From: Sophie Zhang <sophie_zhang@brown.edu>
Date: Sun, 13 Aug 2023 17:02:58 -0400
Subject: update

---
 .../collectionFreeForm/CollectionFreeFormView.tsx      | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index ba31916a7..34f707b30 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -237,7 +237,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     onChildClickHandler = () => this.props.childClickScript || ScriptCast(this.Document.onChildClick);
     onChildDoubleClickHandler = () => this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick);
     elementFunc = () => this._layoutElements;
-    shrinkWrap = () => {
+    fitContentOnce = () => {
         if (this.props.DocumentView?.().nativeWidth) return;
         const vals = this.fitToContentVals;
         this.layoutDoc._freeform_panX = vals.bounds.cx;
@@ -1592,6 +1592,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                     elements => (this._layoutElements = elements || []),
                     { fireImmediately: true, name: 'doLayout' }
                 );
+
+                this._disposers.fitContent = reaction(
+                    () => this.rootDoc.fitContentOnce,
+                    fitContentOnce => {
+                        if (fitContentOnce) this.fitContentOnce();
+                    },
+                    { fireImmediately: true, name: 'fitContent' }
+                );
             })
         );
     }
@@ -1782,6 +1790,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             !Doc.noviceMode &&
             optionItems.push({ description: (this._showAnimTimeline ? 'Close' : 'Open') + ' Animation Timeline', event: action(() => (this._showAnimTimeline = !this._showAnimTimeline)), icon: 'eye' });
         this.props.renderDepth && optionItems.push({ description: 'Use Background Color as Default', event: () => (Cast(Doc.UserDoc().emptyCollection, Doc, null)._backgroundColor = StrCast(this.layoutDoc._backgroundColor)), icon: 'palette' });
+        this.props.renderDepth &&
+            optionItems.push({
+                description: 'Fit Content Once',
+                event: () => {
+                    this.fitContentOnce();
+                },
+                icon: 'object-group',
+            });
         if (!Doc.noviceMode) {
             optionItems.push({ description: (!Doc.NativeWidth(this.layoutDoc) || !Doc.NativeHeight(this.layoutDoc) ? 'Freeze' : 'Unfreeze') + ' Aspect', event: this.toggleNativeDimensions, icon: 'snowflake' });
         }
-- 
cgit v1.2.3-70-g09d2


From d3ecace5f03233e5d5ab2354c3f482418287ca9a Mon Sep 17 00:00:00 2001
From: Sophie Zhang <sophie_zhang@brown.edu>
Date: Thu, 17 Aug 2023 16:14:53 -0400
Subject: broken version

---
 package-lock.json                                  |  97 +++++++++++++++--
 src/client/util/CurrentUserUtils.ts                |   2 +
 src/client/views/MainView.tsx                      |   2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   1 +
 src/client/views/global/globalScripts.ts           |   8 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |  28 +++++
 src/client/views/nodes/ImageBox.tsx                |   6 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |  76 +++++++-------
 .../views/nodes/generativeFill/GenerativeFill.tsx  | 115 +++++++++++++--------
 .../nodes/generativeFill/GenerativeFillButtons.tsx |   6 +-
 src/client/views/pdf/AnchorMenu.tsx                |   1 +
 src/client/views/pdf/GPTPopup/GPTPopup.scss        |   2 +
 src/client/views/pdf/GPTPopup/GPTPopup.tsx         |  99 +++++++++---------
 src/client/views/pdf/PDFViewer.tsx                 |   4 -
 14 files changed, 301 insertions(+), 146 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/package-lock.json b/package-lock.json
index 658e783f9..20d582e5b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6507,9 +6507,9 @@
             }
         },
         "browndash-components": {
-            "version": "0.0.92",
-            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.0.92.tgz",
-            "integrity": "sha512-eE/6WQNZiLnaXUKyoaMm0PDYjExUsFJ9VTAIIxROpYPosIBKWNZ743xaOfmehib5us9hEXJb0CvUFJQb8rzDVw==",
+            "version": "0.0.93",
+            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.0.93.tgz",
+            "integrity": "sha512-JL9Hi7Nq+zHZtjLCQSuGhID0Hd7X6sARutyJqbECfsLWACsIC/JfeEQZdUeH5CqO+R7pJKeoWM82AIkWGtN2Xw==",
             "requires": {
                 "@emotion/react": "^11.11.1",
                 "@emotion/styled": "^11.11.0",
@@ -7063,12 +7063,97 @@
                                         "strip-ansi": "^7.0.1"
                                     }
                                 },
+                                "string-width-cjs": {
+                                    "version": "npm:string-width@4.2.3",
+                                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+                                    "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+                                    "requires": {
+                                        "emoji-regex": "^8.0.0",
+                                        "is-fullwidth-code-point": "^3.0.0",
+                                        "strip-ansi": "^6.0.1"
+                                    },
+                                    "dependencies": {
+                                        "ansi-regex": {
+                                            "version": "5.0.1",
+                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+                                        },
+                                        "emoji-regex": {
+                                            "version": "8.0.0",
+                                            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+                                            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+                                        },
+                                        "strip-ansi": {
+                                            "version": "6.0.1",
+                                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+                                            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+                                            "requires": {
+                                                "ansi-regex": "^5.0.1"
+                                            }
+                                        }
+                                    }
+                                },
                                 "strip-ansi": {
                                     "version": "7.1.0",
                                     "bundled": true,
                                     "requires": {
                                         "ansi-regex": "^6.0.1"
                                     }
+                                },
+                                "strip-ansi-cjs": {
+                                    "version": "npm:strip-ansi@6.0.1",
+                                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+                                    "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+                                    "requires": {
+                                        "ansi-regex": "^5.0.1"
+                                    },
+                                    "dependencies": {
+                                        "ansi-regex": {
+                                            "version": "5.0.1",
+                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+                                        }
+                                    }
+                                },
+                                "wrap-ansi-cjs": {
+                                    "version": "npm:wrap-ansi@7.0.0",
+                                    "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+                                    "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+                                    "requires": {
+                                        "ansi-styles": "^4.0.0",
+                                        "string-width": "^4.1.0",
+                                        "strip-ansi": "^6.0.0"
+                                    },
+                                    "dependencies": {
+                                        "ansi-regex": {
+                                            "version": "5.0.1",
+                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+                                        },
+                                        "emoji-regex": {
+                                            "version": "8.0.0",
+                                            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+                                            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+                                        },
+                                        "string-width": {
+                                            "version": "4.2.3",
+                                            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+                                            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+                                            "requires": {
+                                                "emoji-regex": "^8.0.0",
+                                                "is-fullwidth-code-point": "^3.0.0",
+                                                "strip-ansi": "^6.0.1"
+                                            }
+                                        },
+                                        "strip-ansi": {
+                                            "version": "6.0.1",
+                                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+                                            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+                                            "requires": {
+                                                "ansi-regex": "^5.0.1"
+                                            }
+                                        }
+                                    }
                                 }
                             }
                         },
@@ -8573,7 +8658,7 @@
                             }
                         },
                         "string-width-cjs": {
-                            "version": "npm:string-width@4.2.3",
+                            "version": "npm:string-width-cjs@4.2.3",
                             "bundled": true,
                             "requires": {
                                 "emoji-regex": "^8.0.0",
@@ -8596,7 +8681,7 @@
                             }
                         },
                         "strip-ansi-cjs": {
-                            "version": "npm:strip-ansi@6.0.1",
+                            "version": "npm:strip-ansi-cjs@6.0.1",
                             "bundled": true,
                             "requires": {
                                 "ansi-regex": "^5.0.1"
@@ -8755,7 +8840,7 @@
                             }
                         },
                         "wrap-ansi-cjs": {
-                            "version": "npm:wrap-ansi@7.0.0",
+                            "version": "npm:wrap-ansi-cjs@7.0.0",
                             "bundled": true,
                             "requires": {
                                 "ansi-styles": "^4.0.0",
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index c9a5175bb..6592ecffc 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -633,6 +633,8 @@ export class CurrentUserUtils {
             { title: "Snap", icon: "th",                    toolTip: "Show Snap Lines",     btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"snaplines",  funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
             { title: "Grid",          icon: "border-all",   toolTip: "Show Grid",           btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"grid",       funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
             { title: "View All",   icon: "object-group", toolTip: "Fit all Docs to View",   btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"viewAll",    funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
+            // want the same style as toggle button, but don't want it to act as an actual toggle, so set disableToggle to true,
+            { title: "Fit All",   icon: "arrows-left-right", toolTip: "Fit all Docs to View (persistent)", btnType: ButtonType.IconClickButton, ignoreClick: false, expertMode: false, toolType:"viewAllPersist",    funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
             { title: "Clusters",      icon: "braille",      toolTip: "Show Doc Clusters",   btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"clusters",   funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
             { title: "Cards",         icon: "brain",        toolTip: "Flashcards",          btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"flashcards", funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
             { title: "Arrange",icon:"arrow-down-short-wide",toolTip:"Toggle Auto Arrange",  btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"arrange",    funcs: {hidden: 'IsNoviceMode()'}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 60eb64caa..8fba9b886 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -80,7 +80,6 @@ export class MainView extends React.Component {
     @observable public imageEditorSource: string = '';
     @action public setImageEditorSource = (source: string) => (this.imageEditorSource = source);
     @observable public imageRootDoc: Doc | undefined;
-    @action public setImageRootDoc = (doc: Doc) => (this.imageRootDoc = doc);
     @observable public addDoc: ((doc: Doc | Doc[], annotationKey?: string) => boolean) | undefined;
 
     @observable public LastButton: Opt<Doc>;
@@ -350,6 +349,7 @@ export class MainView extends React.Component {
                 fa.faMousePointer,
                 fa.faMusic,
                 fa.faObjectGroup,
+                fa.faArrowsLeftRight,
                 fa.faPause,
                 fa.faPen,
                 fa.faPenNib,
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 29122cb91..f353dfab7 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1599,6 +1599,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                     () => this.rootDoc.fitContentOnce,
                     fitContentOnce => {
                         if (fitContentOnce) this.fitContentOnce();
+                        this.rootDoc.fitContentOnce = false;
                     },
                     { fireImmediately: true, name: 'fitContent' }
                 );
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts
index 256377758..38bf1042d 100644
--- a/src/client/views/global/globalScripts.ts
+++ b/src/client/views/global/globalScripts.ts
@@ -85,10 +85,10 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
     selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log('[FontIconBox.tsx] toggleOverlay failed');
 });
 
-ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll', checkResult?: boolean) {
+ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'viewAllPersist', checkResult?: boolean) {
     const selected = SelectionManager.Docs().lastElement();
     // prettier-ignore
-    const map: Map<'flashcards' | 'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc) => void;}> = new Map([
+    const map: Map<'flashcards' | 'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll' | 'viewAllPersist', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc) => void;}> = new Map([
         ['grid', {
             checkResult: (doc:Doc) => BoolCast(doc._freeform_backgroundGrid, false),
             setDoc: (doc:Doc) => doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid,
@@ -101,6 +101,10 @@ ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'grid' | 'snapli
             checkResult: (doc:Doc) => BoolCast(doc._freeform_fitContentsToBox, false),
             setDoc: (doc:Doc) => doc._freeform_fitContentsToBox = !doc._freeform_fitContentsToBox,
         }],
+        ['viewAllPersist', {
+            checkResult: (doc:Doc) => false,
+            setDoc: (doc:Doc) => doc.fitContentOnce = true
+        }],
         ['clusters', {
             waitForRender: true, // flags that undo batch should terminate after a re-render giving the script the chance to fire
             checkResult: (doc:Doc) => BoolCast(doc._freeform_useClusters, false),
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 91eac675f..90ec212fc 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -29,6 +29,7 @@ export enum ButtonType {
     DropdownList = 'dropdownList',
     DropdownButton = 'dropdownBtn',
     ClickButton = 'clickBtn',
+    IconClickButton = 'iconClickBtn',
     ToggleButton = 'toggleBtn',
     ColorButton = 'colorBtn',
     ToolButton = 'toolBtn',
@@ -346,6 +347,32 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         );
     }
 
+    @computed get iconClickButton() {
+        // Determine the type of toggle button
+        const buttonText: string = StrCast(this.rootDoc.buttonText);
+        const tooltip: string = StrCast(this.rootDoc.toolTip);
+
+        const script = ScriptCast(this.rootDoc.onClick);
+        const toggleStatus = script ? script.script.run({ this: this.layoutDoc, self: this.rootDoc, value: undefined, _readOnly_: true }).result : false;
+        // Colors
+        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+
+        return (
+            <Toggle
+                tooltip={`${tooltip}`}
+                toggleType={ToggleType.BUTTON}
+                type={Type.PRIM}
+                toggleStatus={toggleStatus}
+                text={buttonText}
+                color={color}
+                icon={this.Icon(color)!}
+                label={this.label}
+                onPointerDown={() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value: !toggleStatus, _readOnly_: false })}
+            />
+        );
+    }
+
     /**
      * Default
      */
@@ -393,6 +420,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             case ButtonType.DropdownButton:     return this.dropdownButton;
             case ButtonType.MultiToggleButton:  return this.multiToggleButton;
             case ButtonType.ToggleButton:       return this.toggleButton;
+            case ButtonType.IconClickButton: return this.iconClickButton;
             case ButtonType.ClickButton:
             case ButtonType.ToolButton: return <IconButton {...btnProps} size={Size.LARGE} color={color} />;
             case ButtonType.TextButton: return <Button     {...btnProps} text={StrCast(this.rootDoc.buttonText)}/>;
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 4ce359f3f..352e0fbdc 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -252,8 +252,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
             funcs.push({
                 description: 'Open Image Editor',
                 event: action(() => {
-                    MainView.Instance.setImageEditorOpen(true);
-                    MainView.Instance.setImageEditorSource(this.choosePath(field.url));
+                    MainView.Instance.imageEditorOpen = true;
+                    MainView.Instance.imageEditorSource = this.choosePath(field.url);
                     MainView.Instance.addDoc = this.props.addDocument;
                     MainView.Instance.imageRootDoc = this.rootDoc;
                 }),
@@ -306,7 +306,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     choosePath(url: URL) {
         const lower = url.href.toLowerCase();
         if (url.protocol === 'data') return url.href;
-        if (url.href.indexOf(window.location.origin) === -1 && url.href.indexOf("dashblobstore") === -1) return Utils.CorsProxy(url.href);
+        if (url.href.indexOf(window.location.origin) === -1 && url.href.indexOf('dashblobstore') === -1) return Utils.CorsProxy(url.href);
         if (!/\.(png|jpg|jpeg|gif|webp)$/.test(lower)) return `/assets/unknown-file-icon-hi.png`;
 
         const ext = extname(url.href);
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 332f0f467..5acc45d02 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -946,44 +946,46 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
         console.log('Generate image from text: ', (this.dataDoc.text as RichTextField)?.Text);
         GPTPopup.Instance?.setTextAnchor(this.getAnchor(false));
         GPTPopup.Instance?.setImgTargetDoc(this.rootDoc);
-        GPTPopup.Instance.setImgUrls([]);
-        GPTPopup.Instance.setMode(GPTPopupMode.IMAGE);
-        GPTPopup.Instance.setVisible(true);
+        // GPTPopup.Instance.setImgUrls([]);
+        // GPTPopup.Instance.setMode(GPTPopupMode.IMAGE);
+        // GPTPopup.Instance.setVisible(true);
         GPTPopup.Instance.addToCollection = this.props.addDocument;
-        GPTPopup.Instance.setLoading(true);
-
-        try {
-            // make this support multiple images
-            let image_urls = await gptImageCall((this.dataDoc.text as RichTextField)?.Text);
-            console.log(image_urls);
-            if (image_urls) {
-                const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [image_urls[0]] });
-                const source = Utils.prepend(result.accessPaths.agnostic.client);
-                GPTPopup.Instance.setImgUrls([source]);
-
-                // const newDoc = Docs.Create.ImageDocument(source, {
-                //     x: NumCast(this.rootDoc.x) + NumCast(this.layoutDoc._width) + 10,
-                //     y: NumCast(this.rootDoc.y),
-                //     _height: 200,
-                //     _width: 200,
-                //     data_nativeWidth: result.nativeWidth,
-                //     data_nativeHeight: result.nativeHeight,
-                // });
-                // if (Doc.IsInMyOverlay(this.rootDoc)) {
-                //     newDoc.overlayX = this.rootDoc.x;
-                //     newDoc.overlayY = NumCast(this.rootDoc.y) + NumCast(this.rootDoc._height);
-                //     Doc.AddToMyOverlay(newDoc);
-                // } else {
-                //     this.props.addDocument?.(newDoc);
-                // }
-                // // Create link between prompt and image
-                // DocUtils.MakeLink(this.rootDoc, newDoc, { link_relationship: 'Image Prompt' });
-            }
-        } catch (err) {
-            console.log(err);
-            return '';
-        }
-        GPTPopup.Instance.setLoading(false);
+        // GPTPopup.Instance.setLoading(true);
+        GPTPopup.Instance.setImgDesc((this.dataDoc.text as RichTextField)?.Text);
+        GPTPopup.Instance.generateImage();
+
+        // try {
+        //     // make this support multiple images
+        //     let image_urls = await gptImageCall((this.dataDoc.text as RichTextField)?.Text);
+        //     console.log(image_urls);
+        //     if (image_urls) {
+        //         const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [image_urls[0]] });
+        //         const source = Utils.prepend(result.accessPaths.agnostic.client);
+        //         GPTPopup.Instance.setImgUrls([source]);
+
+        //         // const newDoc = Docs.Create.ImageDocument(source, {
+        //         //     x: NumCast(this.rootDoc.x) + NumCast(this.layoutDoc._width) + 10,
+        //         //     y: NumCast(this.rootDoc.y),
+        //         //     _height: 200,
+        //         //     _width: 200,
+        //         //     data_nativeWidth: result.nativeWidth,
+        //         //     data_nativeHeight: result.nativeHeight,
+        //         // });
+        //         // if (Doc.IsInMyOverlay(this.rootDoc)) {
+        //         //     newDoc.overlayX = this.rootDoc.x;
+        //         //     newDoc.overlayY = NumCast(this.rootDoc.y) + NumCast(this.rootDoc._height);
+        //         //     Doc.AddToMyOverlay(newDoc);
+        //         // } else {
+        //         //     this.props.addDocument?.(newDoc);
+        //         // }
+        //         // // Create link between prompt and image
+        //         // DocUtils.MakeLink(this.rootDoc, newDoc, { link_relationship: 'Image Prompt' });
+        //     }
+        // } catch (err) {
+        //     console.log(err);
+        //     return '';
+        // }
+        // GPTPopup.Instance.setLoading(false);
     };
 
     breakupDictation = () => {
diff --git a/src/client/views/nodes/generativeFill/GenerativeFill.tsx b/src/client/views/nodes/generativeFill/GenerativeFill.tsx
index f8f9fe077..99068d647 100644
--- a/src/client/views/nodes/generativeFill/GenerativeFill.tsx
+++ b/src/client/views/nodes/generativeFill/GenerativeFill.tsx
@@ -3,7 +3,7 @@ import React = require('react');
 import { useEffect, useRef, useState } from 'react';
 import { APISuccess, ImageUtility } from './generativeFillUtils/ImageHandler';
 import { BrushHandler } from './generativeFillUtils/BrushHandler';
-import { Box, IconButton, Slider, TextField } from '@mui/material';
+import { Box, Checkbox, FormControlLabel, IconButton, Slider, TextField } from '@mui/material';
 import { CursorData, Point } from './generativeFillUtils/generativeFillInterfaces';
 import { activeColor, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './generativeFillUtils/generativeFillConstants';
 import { PointerHandler } from './generativeFillUtils/PointerHandler';
@@ -19,6 +19,7 @@ import { Cast, DocCast, NumCast } from '../../../../fields/Types';
 import { CollectionDockingView } from '../../collections/CollectionDockingView';
 import { OpenWhere, OpenWhereMod } from '../DocumentView';
 import { Oval } from 'react-loader-spinner';
+import { CheckBox } from '../../search/CheckBox';
 
 /**
  * For images not 1024x1024 fill in the rest in solid black, or a
@@ -72,6 +73,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
     const [input, setInput] = useState('');
     const [loading, setLoading] = useState(false);
     const [saveLoading, setSaveLoading] = useState(false);
+    const [isNewCollection, setIsNewCollection] = useState(false);
     // the current image in the main canvas
     const currImg = useRef<HTMLImageElement | null>(null);
     // the unedited version of each generation (parent)
@@ -81,9 +83,6 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
     // stores redo stack
     const redoStack = useRef<string[]>([]);
 
-    // early stage properly, likely will get rid of
-    const freeformPosition = useRef<number[]>([0, 0]);
-
     // which urls were already saved to canvas
     const savedSrcs = useRef<Set<string>>(new Set());
 
@@ -91,7 +90,6 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
     const newCollectionRef = useRef<Doc | null>(null);
     const parentDoc = useRef<Doc | null>(null);
     const childrenDocs = useRef<Doc[]>([]);
-    const addToExistingCollection = useRef<boolean>(false);
 
     // Undo and Redo
     const handleUndo = () => {
@@ -111,10 +109,13 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
     };
 
     const handleRedo = () => {
-        // TODO: handle undo as well
+        const ctx = ImageUtility.getCanvasContext(canvasRef);
+        if (!ctx || !currImg.current || !canvasRef.current) return;
+
         const target = redoStack.current[redoStack.current.length - 1];
         if (!target) {
         } else {
+            undoStack.current = [...undoStack.current, canvasRef.current?.toDataURL()];
             const img = new Image();
             img.src = target;
             ImageUtility.drawImgToCanvas(img, canvasRef);
@@ -188,7 +189,6 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
         ImageUtility.drawImgToCanvas(img, canvasRef);
         currImg.current = img;
         originalImg.current = img;
-        freeformPosition.current = [0, 0];
 
         return () => {
             console.log('cleanup');
@@ -197,7 +197,6 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
             childrenDocs.current = [];
             currImg.current = null;
             originalImg.current = null;
-            freeformPosition.current = [0, 0];
             undoStack.current = [];
             redoStack.current = [];
         };
@@ -266,24 +265,25 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
 
             // create first image
             if (!newCollectionRef.current) {
-                if (addToExistingCollection.current) {
+                if (!isNewCollection) {
+                    // newcollection should stay null
+                } else {
+                    if (!(originalImg.current && imageRootDoc)) return;
+                    // create new collection and add it to the view
+                    newCollectionRef.current = Docs.Create.FreeformDocument([], {
+                        x: NumCast(imageRootDoc.x) + NumCast(imageRootDoc._width) + offsetX,
+                        y: NumCast(imageRootDoc.y),
+                        _width: newCollectionSize,
+                        _height: newCollectionSize,
+                        title: 'Image edit collection',
+                    });
+                    DocUtils.MakeLink(imageRootDoc, newCollectionRef.current, { link_relationship: 'Image Edit Version History', link_displayLine: false });
+                    // add the doc to the main freeform
+                    addDoc?.(newCollectionRef.current);
+                    await createNewImgDoc(originalImg.current, true);
                 }
-                if (!(originalImg.current && imageRootDoc)) return;
-                console.log('creating first image');
-                // create new collection and add it to the view
-                newCollectionRef.current = Docs.Create.FreeformDocument([], {
-                    x: NumCast(imageRootDoc.x) + NumCast(imageRootDoc._width) + offsetX,
-                    y: NumCast(imageRootDoc.y),
-                    _width: newCollectionSize,
-                    _height: newCollectionSize,
-                    title: 'Image edit collection',
-                });
-                DocUtils.MakeLink(imageRootDoc, newCollectionRef.current, { link_relationship: 'Image Edit Version History', link_displayLine: false });
-                // add the doc to the main freeform
-                // addDoc?.(newCollectionRef.current);
-                await createNewImgDoc(originalImg.current, true);
             } else {
-                parentDoc.current = childrenDocs.current[childrenDocs.current.length - 1];
+                // parentDoc.current = childrenDocs.current[childrenDocs.current.length - 1];
                 childrenDocs.current = [];
             }
 
@@ -292,12 +292,24 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
             const { urls } = res as APISuccess;
             const image = new Image();
             image.src = urls[0];
+
+            // need to crop images agh
+            // save to dash
+
+            // const imageRes = await Promise.all(
+            //     urls.map(async url => {
+            //         const newImg = new Image();
+            //         newImg.src = url;
+            //         await onSave(newImg);
+            //     })
+            // );
+
+            // map each url to [url, imgDoc]
             setEdits(urls);
+
             ImageUtility.drawImgToCanvas(image, canvasRef);
             currImg.current = image;
-            onSave();
-            freeformPosition.current[0] += 1;
-            freeformPosition.current[1] = 0;
+            // onSave(currImg.current);
         } catch (err) {
             console.log(err);
         }
@@ -324,7 +336,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
 
     // creates a new image document and returns its reference
     const createNewImgDoc = async (img: HTMLImageElement, firstDoc: boolean): Promise<Doc | undefined> => {
-        if (!newCollectionRef.current || !imageRootDoc) return;
+        if (!imageRootDoc) return;
         const src = img.src;
         const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [src] });
         const source = Utils.prepend(result.accessPaths.agnostic.client);
@@ -332,7 +344,6 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
         if (firstDoc) {
             const x = 0;
             const initialY = 0;
-            console.log('first doc');
 
             const newImg = Docs.Create.ImageDocument(source, {
                 x: x,
@@ -343,16 +354,19 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
                 data_nativeHeight: result.nativeHeight,
             });
 
-            Doc.AddDocToList(newCollectionRef.current, undefined, newImg);
+            if (isNewCollection && newCollectionRef.current) {
+                Doc.AddDocToList(newCollectionRef.current, undefined, newImg);
+            } else {
+                addDoc?.(newImg);
+            }
+
             parentDoc.current = newImg;
             return newImg;
         } else {
             if (!parentDoc.current) return;
             const x = NumCast(parentDoc.current.x) + freeformRenderSize + offsetX;
             // dummy position
-            console.log('creating child elements');
             const initialY = 0;
-
             const newImg = Docs.Create.ImageDocument(source, {
                 x: x,
                 y: initialY,
@@ -363,21 +377,26 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
             });
 
             childrenDocs.current.push(newImg);
+
+            if (isNewCollection && newCollectionRef.current) {
+                Doc.AddDocToList(newCollectionRef.current, undefined, newImg);
+            } else {
+                addDoc?.(newImg);
+            }
+
             DocUtils.MakeLink(parentDoc.current, newImg, { link_relationship: 'Image Edit', link_displayLine: true });
             adjustImgPositions();
-
-            Doc.AddDocToList(newCollectionRef.current, undefined, newImg);
             return newImg;
         }
     };
 
     // need to maybe call on every img click, not just when the save btn is clicked
-    const onSave = async () => {
+    const onSave = async (img: HTMLImageElement) => {
         setSaveLoading(true);
-        if (!currImg.current || !originalImg.current || !imageRootDoc) return;
+        // if (!currImg.current || !originalImg.current || !imageRootDoc) return;
         try {
             console.log('creating another image');
-            await createNewImgDoc(currImg.current, false);
+            await createNewImgDoc(img, false);
         } catch (err) {
             console.log(err);
         }
@@ -387,7 +406,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
     const handleViewClose = () => {
         if (newCollectionRef.current) {
             newCollectionRef.current.fitContentOnce = true;
-            CollectionDockingView.AddSplit(newCollectionRef.current, OpenWhereMod.right);
+            // CollectionDockingView.AddSplit(newCollectionRef.current, OpenWhereMod.right);
         }
         MainView.Instance.setImageEditorOpen(false);
         MainView.Instance.setImageEditorSource('');
@@ -399,7 +418,20 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
             <div className="generativeFillControls">
                 <h1>AI Image Editor</h1>
                 <div style={{ display: 'flex', alignItems: 'center', gap: '1.5rem' }}>
-                    <Buttons canvasRef={canvasRef} currImg={currImg} getEdit={getEdit} loading={loading} onSave={onSave} onReset={handleReset} />
+                    <FormControlLabel
+                        control={
+                            <Checkbox
+                                checked={isNewCollection}
+                                onChange={e => {
+                                    setIsNewCollection(prev => !prev);
+                                }}
+                            />
+                        }
+                        label={'Create New Collection'}
+                        labelPlacement="end"
+                        sx={{ whiteSpace: 'nowrap' }}
+                    />
+                    <Buttons canvasRef={canvasRef} currImg={currImg} getEdit={getEdit} loading={loading} onReset={handleReset} />
                     <IconButton onClick={handleViewClose}>
                         <BsX color={activeColor} />
                     </IconButton>
@@ -491,13 +523,14 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
                             height={100}
                             src={edit}
                             onClick={async () => {
-                                // if (savedSrcs.current.has(edit)) return;
                                 const img = new Image();
                                 img.src = edit;
                                 ImageUtility.drawImgToCanvas(img, canvasRef);
                                 currImg.current = img;
                                 savedSrcs.current.add(edit);
-                                await onSave();
+                                undoStack.current = [];
+                                redoStack.current = [];
+                                await onSave(img);
                             }}
                         />
                     ))}
diff --git a/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx b/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx
index 53c6cec84..b4d56b408 100644
--- a/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx
+++ b/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx
@@ -11,14 +11,10 @@ interface ButtonContainerProps {
     currImg: React.MutableRefObject<HTMLImageElement | null>;
     getEdit: () => Promise<void>;
     loading: boolean;
-    onSave: () => Promise<void>;
     onReset: () => void;
 }
 
-const Buttons = ({ canvasRef, currImg, loading, getEdit, onSave, onReset }: ButtonContainerProps) => {
-    const handleSave = () => {
-        onSave();
-    };
+const Buttons = ({ canvasRef, currImg, loading, getEdit, onReset }: ButtonContainerProps) => {
 
     return (
         <div className="generativeFillBtnContainer">
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index 7404650d6..1be8fe6ab 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -130,6 +130,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
      * @param e pointer down event
      */
     gptSummarize = async (e: React.PointerEvent) => {
+        // move this logic to gptpopup, need to implement generate again
         GPTPopup.Instance.setVisible(true);
         this.setHighlightRange(undefined);
         GPTPopup.Instance.setMode(GPTPopupMode.SUMMARY);
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss
index 478b7d4ba..5d966395c 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.scss
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss
@@ -123,9 +123,11 @@ $highlightedText: #82e0ff;
         cursor: pointer;
 
         .img-container {
+            pointer-events: none;
             position: relative;
 
             img {
+                pointer-events: all;
                 position: relative;
             }
         }
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
index fc6fc1af8..943c38d42 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
@@ -10,6 +10,11 @@ import { DocUtils, Docs } from '../../../documents/Documents';
 import { Button, IconButton, Type } from 'browndash-components';
 import { NumCast, StrCast } from '../../../../fields/Types';
 import { CgClose } from 'react-icons/cg';
+import { AnchorMenu } from '../AnchorMenu';
+import { gptAPICall, gptImageCall } from '../../../apis/gpt/GPT';
+import { RichTextField } from '../../../../fields/RichTextField';
+import { Networking } from '../../../Network';
+import { Utils } from '../../../../Utils';
 
 export enum GPTPopupMode {
     SUMMARY,
@@ -43,10 +48,17 @@ export class GPTPopup extends React.Component<GPTPopupProps> {
     };
 
     @observable
-    public imageUrls: string[] = [];
+    public imgDesc: string = '';
     @action
-    public setImgUrls = (imgs: string[]) => {
-        this.imageUrls = imgs;
+    public setImgDesc = (text: string) => {
+        this.imgDesc = text;
+    };
+
+    @observable
+    public imgUrls: string[][] = [];
+    @action
+    public setImgUrls = (imgs: string[][]) => {
+        this.imgUrls = imgs;
     };
 
     @observable
@@ -102,6 +114,30 @@ export class GPTPopup extends React.Component<GPTPopupProps> {
     public addDoc: (doc: Doc | Doc[], sidebarKey?: string | undefined) => boolean = () => false;
     public addToCollection: ((doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) | undefined;
 
+    generateImage = async () => {
+        if (this.imgDesc === '') return;
+        this.setImgUrls([]);
+        this.setMode(GPTPopupMode.IMAGE);
+        this.setVisible(true);
+        this.setLoading(true);
+
+        try {
+            // make this support multiple images
+            let image_urls = await gptImageCall(this.imgDesc);
+            console.log(image_urls);
+            if (image_urls && image_urls[0]) {
+                const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [image_urls[0]] });
+                const source = Utils.prepend(result.accessPaths.agnostic.client);
+                console.log('Source', source);
+                this.setImgUrls([[image_urls[0], source]]);
+            }
+        } catch (err) {
+            console.log(err);
+            return '';
+        }
+        GPTPopup.Instance.setLoading(false);
+    };
+
     /**
      * Transfers the summarization text to a sidebar annotation text document.
      */
@@ -113,8 +149,9 @@ export class GPTPopup extends React.Component<GPTPopupProps> {
             _layout_autoHeight: true,
         });
         this.addDoc(newDoc, this.sidebarId);
-        if (this.targetAnchor) {
-            DocUtils.MakeLink(newDoc, this.targetAnchor, {
+        const anchor = AnchorMenu.Instance?.GetAnchor(undefined, false);
+        if (anchor) {
+            DocUtils.MakeLink(newDoc, anchor, {
                 link_relationship: 'GPT Summary',
             });
         }
@@ -163,17 +200,22 @@ export class GPTPopup extends React.Component<GPTPopupProps> {
             <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
                 {this.heading('GENERATED IMAGE')}
                 <div className="image-content-wrapper">
-                    {this.imageUrls.map(rawSrc => (
+                    {this.imgUrls.map(rawSrc => (
                         <div className="img-wrapper">
                             <div className="img-container">
-                                <img key={rawSrc} src={this.getPreviewUrl(rawSrc)} width={150} height={150} alt="dalle generation" />
+                                <img key={rawSrc[0]} src={rawSrc[0]} width={150} height={150} alt="dalle generation" />
                             </div>
                             <div className="btn-container">
-                                <Button text="Save Image" onClick={() => this.transferToImage(rawSrc)} color={StrCast(Doc.UserDoc().userColor)} type={Type.TERT} />
+                                <Button text="Save Image" onClick={() => this.transferToImage(rawSrc[1])} color={StrCast(Doc.UserDoc().userColor)} type={Type.TERT} />
                             </div>
                         </div>
                     ))}
                 </div>
+                {!this.loading && (
+                    <>
+                        <IconButton tooltip="Generate Again" onClick={this.generateImage} icon={<FontAwesomeIcon icon="redo-alt" size="lg" />} color={StrCast(Doc.UserDoc().userVariantColor)} />
+                    </>
+                )}
             </div>
         );
     };
@@ -227,43 +269,6 @@ export class GPTPopup extends React.Component<GPTPopupProps> {
         </>
     );
 
-    editBox = () => {
-        const hr = this.highlightRange;
-        return (
-            <>
-                <div>
-                    {this.heading('TEXT EDIT SUGGESTIONS')}
-                    <div className="content-wrapper">
-                        {hr && (
-                            <div>
-                                {this.text.slice(0, hr[0])} <span className="highlighted-text">{this.text.slice(hr[0], hr[1])}</span> {this.text.slice(hr[1])}
-                            </div>
-                        )}
-                    </div>
-                </div>
-                {hr && !this.loading && (
-                    <>
-                        <div className="btns-wrapper">
-                            <>
-                                <button className="icon-btn" onPointerDown={this.callEditApi}>
-                                    <FontAwesomeIcon icon="redo-alt" size="lg" />
-                                </button>
-                                <button
-                                    className="text-btn"
-                                    onClick={e => {
-                                        this.replaceText(this.text);
-                                    }}>
-                                    Replace Text
-                                </button>
-                            </>
-                        </div>
-                        {this.aiWarning()}
-                    </>
-                )}
-            </>
-        );
-    };
-
     aiWarning = () =>
         this.done ? (
             <div className="ai-warning">
@@ -277,14 +282,14 @@ export class GPTPopup extends React.Component<GPTPopupProps> {
     heading = (headingText: string) => (
         <div className="summary-heading">
             <label className="summary-text">{headingText}</label>
-            {this.loading ? <ReactLoading type="spin" color="#bcbcbc" width={14} height={14} /> : <IconButton color={StrCast(Doc.UserDoc().userColor)} tooltip="close" icon={<CgClose size="16px" />} onClick={() => this.setVisible(false)} />}
+            {this.loading ? <ReactLoading type="spin" color="#bcbcbc" width={14} height={14} /> : <IconButton color={StrCast(Doc.UserDoc().userVariantColor)} tooltip="close" icon={<CgClose size="16px" />} onClick={() => this.setVisible(false)} />}
         </div>
     );
 
     render() {
         return (
             <div className="summary-box" style={{ display: this.visible ? 'flex' : 'none' }}>
-                {this.mode === GPTPopupMode.SUMMARY ? this.summaryBox() : this.mode === GPTPopupMode.IMAGE ? this.imageBox() : this.editBox()}
+                {this.mode === GPTPopupMode.SUMMARY ? this.summaryBox() : this.mode === GPTPopupMode.IMAGE ? this.imageBox() : <></>}
             </div>
         );
     }
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index c9fee4813..1319a236d 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -424,10 +424,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
 
         // Changing which document to add the annotation to (the currently selected PDF)
         GPTPopup.Instance.setSidebarId('data_sidebar');
-        const anchor = this._getAnchor(undefined, false);
-        if (anchor) {
-            GPTPopup.Instance.setTargetAnchor(anchor);
-        }
         GPTPopup.Instance.addDoc = this.props.sidebarAddDoc;
     };
 
-- 
cgit v1.2.3-70-g09d2


From 63c2c903d4d92aaeb0d024f02d8142d7c8ad7a5f Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Tue, 22 Aug 2023 15:32:06 -0400
Subject: tweaks

---
 .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx     | 2 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx                      | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 91a78c2af..f5cc1eb53 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1600,7 +1600,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                     () => this.rootDoc.fitContentOnce,
                     fitContentOnce => {
                         if (fitContentOnce) this.fitContentOnce();
-                        this.rootDoc.fitContentOnce = false;
+                        this.rootDoc.fitContentOnce = undefined;
                     },
                     { fireImmediately: true, name: 'fitContent' }
                 );
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 0e230e19b..a2cf3bc25 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -426,7 +426,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             case ButtonType.DropdownButton:     return this.dropdownButton;
             case ButtonType.MultiToggleButton:  return this.multiToggleButton;
             case ButtonType.ToggleButton:       return this.toggleButton;
-            case ButtonType.IconClickButton: return this.iconClickButton;
+            case ButtonType.IconClickButton:    return this.iconClickButton;
             case ButtonType.ClickButton:
             case ButtonType.ToolButton: return <IconButton {...btnProps} size={Size.LARGE} color={color} />;
             case ButtonType.TextButton: return <Button     {...btnProps} text={StrCast(this.rootDoc.buttonText)}/>;
-- 
cgit v1.2.3-70-g09d2

