diff options
author | eleanor-park <eleanor_park@brown.edu> | 2024-07-24 16:52:50 -0400 |
---|---|---|
committer | eleanor-park <eleanor_park@brown.edu> | 2024-07-24 16:52:50 -0400 |
commit | a763c4e80cec6aef5219a8c9fcfa2ddccbc10b0a (patch) | |
tree | 87bbbe2f9360525b8196f1864abc97e569d1ea97 | |
parent | 9e2f51dc5a1c82e9293e04c71f4430fd67ff3378 (diff) |
bug and render fixes
-rw-r--r-- | package-lock.json | 26 | ||||
-rw-r--r-- | src/client/apis/gpt/GPT.ts | 2 | ||||
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 26 | ||||
-rw-r--r-- | src/client/util/DropConverter.ts | 22 | ||||
-rw-r--r-- | src/client/util/bezierFit.ts | 13 | ||||
-rw-r--r-- | src/client/views/DocumentButtonBar.tsx | 2 | ||||
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 7 | ||||
-rw-r--r-- | src/client/views/LightboxView.tsx | 20 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 1 | ||||
-rw-r--r-- | src/client/views/collections/CollectionCarousel3DView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/CollectionCarouselView.tsx | 11 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 10 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 13 | ||||
-rw-r--r-- | src/client/views/smartdraw/AnnotationPalette.tsx | 203 | ||||
-rw-r--r-- | src/client/views/smartdraw/SmartDrawHandler.tsx | 9 | ||||
-rw-r--r-- | src/fields/Doc.ts | 1 |
16 files changed, 145 insertions, 223 deletions
diff --git a/package-lock.json b/package-lock.json index 663409ddb..70f53156c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13531,19 +13531,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/browndash-components/node_modules/npm/node_modules/node-gyp/node_modules/readable-stream": { - "version": "3.6.2", - "inBundle": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/browndash-components/node_modules/npm/node_modules/node-gyp/node_modules/signal-exit": { "version": "3.0.7", "inBundle": true, @@ -13989,6 +13976,19 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/browndash-components/node_modules/npm/node_modules/readable-stream": { + "version": "3.6.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/browndash-components/node_modules/npm/node_modules/retry": { "version": "0.12.0", "inBundle": true, diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index cbe2f0582..a780596fa 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -58,7 +58,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { model: 'gpt-4o', maxTokens: 1024, temp: 0.5, - prompt: 'Given an item, a level of complexity from 1-10, and a size in pixels, generate a detailed and colored line drawing representation of it. Make sure every element has the stroke field filled out. More complex drawings will have much more detail and strokes. The drawing should be in SVG format with no additional text or comments. For path coordinates, make sure you format with a comma between numbers, like M100,200 C150,250 etc. The only supported commands are line, ellipse, circle, rect, and path with M, Q, C, and L so only use those.', + prompt: 'Given an item, a level of complexity from 1-10, and a size in pixels, generate a detailed and colored line drawing representation of it. Make sure every element has the stroke field filled out. More complex drawings will have much more detail and strokes. The drawing should be in SVG format with no additional text or comments. For path coordinates, make sure you format with a comma between numbers, like M100,200 C150,250 etc. The only supported commands are line, ellipse, circle, rect, polygon, and path with M, Q, C, and L so only use those.', }, }; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 98a54d4d0..6b59828eb 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -165,7 +165,7 @@ export class CurrentUserUtils { static setupAnnoPalette(doc: Doc, field="myAnnos") { const reqdOpts:DocumentOptions = { - title: "Saved Annotations", _xMargin: 0, _layout_showTitle: "title", _chromeHidden: true, hidden: false, + title: "Saved Annotations", _xMargin: 0, _layout_showTitle: "title", hidden: false, _dragOnlyWithinContainer: true, layout_hideContextMenu: true, isSystem: true, _forceActive: true, _layout_autoHeight: true, _width: 500, _height: 300, _layout_fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, }; @@ -174,21 +174,14 @@ export class CurrentUserUtils { return DocUtils.AssignDocField(doc, field, (opts,items) => Docs.Create.MasonryDocument(items??[], opts), reqdOpts, DocListCast(savedAnnos?.data), reqdScripts); } - // static setupNoteTemplates(doc: Doc, field="template_notes") { - // const tempNotes = DocCast(doc[field]); - // const reqdTempOpts:DocumentOptions[] = [ - // { title: "Postit", backgroundColor: "yellow", icon: "sticky-note", _layout_showTitle: "title", layout_borderRounding: "5px"}, - // { title: "Idea", backgroundColor: "pink", icon: "lightbulb" , _layout_showTitle: "title"}, - // { title: "Topic", backgroundColor: "lightblue", icon: "book-open" , _layout_showTitle: "title"}]; - // const reqdNoteList = [...reqdTempOpts.map(opts => { - // const reqdOpts = {...opts, isSystem:true, width:200, layout_autoHeight: true, layout_fitWidth: true}; - // const noteTemp = tempNotes ? DocListCast(tempNotes.data).find(fdoc => fdoc.title === opts.title): undefined; - // return DocUtils.AssignOpts(noteTemp, reqdOpts) ?? MakeTemplate(Docs.Create.TextDocument("",reqdOpts)); - // }), ... DocListCast(tempNotes?.data).filter(note => !reqdTempOpts.find(reqd => reqd.title === note.title))]; - - // const reqdOpts:DocumentOptions = { title: "Note Layouts", _height: 75, isSystem: true }; - // // eslint-disable-next-line no-return-assign - // r + static setupLightboxDrawingPreviews(doc: Doc, field="myLightboxDrawings") { + const reqdOpts:DocumentOptions = { + title: "Preview", _layout_fitWidth: true, childLayoutFitWidth: true, + }; + const reqdScripts = {}; + const drawings = DocCast(doc[field]); + return DocUtils.AssignDocField(doc, field, (opts,items) => Docs.Create.CarouselDocument(items??[], opts), reqdOpts, DocListCast(drawings?.data), reqdScripts); + } // setup templates for different document types when they are iconified from Document Decorations static setupDefaultIconTemplates(doc: Doc, field="template_icons") { @@ -1015,6 +1008,7 @@ pie title Minerals in my tap water this.setupDockedButtons(doc); // the bottom bar of font icons this.setupLeftSidebarMenu(doc); // the left-side column of buttons that open their contents in a flyout panel on the left this.setupAnnoPalette(doc); + this.setupLightboxDrawingPreviews(doc); this.setupDocTemplates(doc); // sets up the template menu of templates // sthis.setupFieldInfos(doc); // sets up the collection of field info descriptions for each possible DocumentOption DocUtils.AssignDocField(doc, "globalScriptDatabase", () => Docs.Prototypes.MainScriptDocument(), {}); diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index 0314af06b..3e26fefad 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -86,6 +86,28 @@ export function makeUserTemplateButton(doc: Doc) { dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory)'); return dbox; } + +export function makeUserTemplateImage(doc: Doc, image: ImageField) { + const layoutDoc = doc; // doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc; + if (layoutDoc.type !== DocumentType.FONTICON) { + !layoutDoc.isTemplateDoc && makeTemplate(layoutDoc); + } + layoutDoc.isTemplateDoc = true; + const dbox = Docs.Create.ImageDocument(image, { + _nativeWidth: 100, + _nativeHeight: 100, + _width: 100, + _height: 100, + title: StrCast(layoutDoc.title), + isSystem: false, + }); + dbox.title = ComputedField.MakeFunction('this.dragFactory.title'); + dbox.dragFactory = layoutDoc; + dbox.dropPropertiesToRemove = doc.dropPropertiesToRemove instanceof ObjectField ? ObjectField.MakeCopy(doc.dropPropertiesToRemove) : undefined; + dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory)'); + return dbox; +} + export function convertDropDataToButtons(data: DragManager.DocumentDragData) { data?.draggedDocuments.forEach((doc, i) => { let dbox = doc; diff --git a/src/client/util/bezierFit.ts b/src/client/util/bezierFit.ts index 98a6feea0..6a4577506 100644 --- a/src/client/util/bezierFit.ts +++ b/src/client/util/bezierFit.ts @@ -694,7 +694,7 @@ export function SVGToBezier(name: SVGType, attributes: any): Point[] { const matches: RegExpMatchArray[] = Array.from( attributes.d.matchAll(/Q(-?\d+\.?\d*),(-?\d+\.?\d*) (-?\d+\.?\d*),(-?\d+\.?\d*)|C(-?\d+\.?\d*),(-?\d+\.?\d*) (-?\d+\.?\d*),(-?\d+\.?\d*) (-?\d+\.?\d*),(-?\d+\.?\d*)|L(-?\d+\.?\d*),(-?\d+\.?\d*)/g) ); - let lastPt: Point; + let lastPt: Point = { X: 0, Y: 0 }; matches.forEach(match => { if (match[0].startsWith('Q')) { coordList.push({ X: parseInt(match[1]), Y: parseInt(match[2]) }); @@ -726,6 +726,17 @@ export function SVGToBezier(name: SVGType, attributes: any): Point[] { } return coordList; case 'polygon': + const coords: RegExpMatchArray[] = Array.from(attributes.points.matchAll(/(-?\d+\.?\d*),(-?\d+\.?\d*)/g)); + let list: Point[] = []; + coords.forEach(coord => { + list.push({ X: parseInt(coord[1]), Y: parseInt(coord[2]) }); + list.push({ X: parseInt(coord[1]), Y: parseInt(coord[2]) }); + list.push({ X: parseInt(coord[1]), Y: parseInt(coord[2]) }); + list.push({ X: parseInt(coord[1]), Y: parseInt(coord[2]) }); + }); + const firstPts = list.splice(0, 2); + list = list.concat(firstPts); + return list; default: return []; } diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index eb0b00472..6950bec14 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -249,7 +249,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => ( saveAnno = action((targetDoc: Doc) => { // targetDoc.savedAsAnno = true; this._annoSaved = true; - AnnotationPalette.Instance.addToPalette(targetDoc); + // AnnotationPalette.addToPalette(targetDoc); }); @computed diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index a229b15db..ae4f5b98b 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -229,6 +229,11 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora if (iconViewDoc.activeFrame) { iconViewDoc.opacity = 0; // bcz: hacky ... allows inkMasks and other documents to be "turned off" without removing them from the animated collection which allows them to function properly in a presenation. } else { + // to mark annotations as no longer saved if they're deleted from the palette + const dragFactory: Doc = DocCast(iconView.Document.dragFactory); + if (dragFactory && DocCast(dragFactory.cloneOf).savedAsAnno) { + DocCast(dragFactory.cloneOf).savedAsAnno = undefined; + } iconView._props.removeDocument?.(iconView.Document); } }); @@ -872,4 +877,4 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora </div> ); } -}
\ No newline at end of file +} diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index 4fcb7ec9c..b0d469674 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -12,7 +12,7 @@ import { emptyFunction } from '../../Utils'; import { CreateLinkToActiveAudio, Doc, DocListCast, FieldResult, Opt } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; import { InkTool } from '../../fields/InkField'; -import { Cast, NumCast, toList } from '../../fields/Types'; +import { Cast, DocCast, NumCast, toList } from '../../fields/Types'; import { SnappingManager } from '../util/SnappingManager'; import { Transform } from '../util/Transform'; import { GestureOverlay } from './GestureOverlay'; @@ -43,13 +43,11 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> { * @returns true if a DocumentView is descendant of the lightbox view */ public static Contains(view?: DocumentView) { - return true; - } - // return ( - // (view && LightboxView.Instance?._docView && (view.containerViewPath?.() ?? []).concat(view).includes(LightboxView.Instance?._docView)) || - // view?.Document === AnnotationPalette.Instance.FreeformCanvas || - // view?.Document.embedContainer === AnnotationPalette.Instance.DrawingCarousel - // ); } // prettier-ignore + return ( + (view && LightboxView.Instance?._docView && (view.containerViewPath?.() ?? []).concat(view).includes(LightboxView.Instance?._docView)) || + (view && LightboxView.Instance?._annoPaletteView?.Contains(view)) + ); + } // prettier-ignore public static LightboxDoc = () => LightboxView.Instance?._doc; // eslint-disable-next-line no-use-before-define static Instance: LightboxView; @@ -69,6 +67,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> { @observable private _docTarget: Opt<Doc> = undefined; @observable private _docView: Opt<DocumentView> = undefined; @observable private _showPalette: boolean = false; + private _annoPaletteView: AnnotationPalette | null = null; @computed get leftBorder() { return Math.min(this._props.PanelWidth / 4, this._props.maxBorder[0]); } // prettier-ignore @computed get topBorder() { return Math.min(this._props.PanelHeight / 4, this._props.maxBorder[1]); } // prettier-ignore @@ -114,7 +113,6 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> { this._history = []; Doc.ActiveTool = InkTool.None; SnappingManager.SetExploreMode(false); - AnnotationPalette.Instance.displayPalette(false); this._showPalette = false; } DocumentView.DeselectAll(); @@ -217,8 +215,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> { }; togglePalette = () => { this._showPalette = !this._showPalette; - AnnotationPalette.Instance.displayPalette(this._showPalette); - if (this._showPalette === false) AnnotationPalette.Instance.resetPalette(true); + // if (this._showPalette === false) AnnotationPalette.Instance.resetPalette(true); }; togglePen = () => { Doc.ActiveTool = Doc.ActiveTool === InkTool.Pen ? InkTool.None : InkTool.Pen; @@ -324,6 +321,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> { </GestureOverlay> </div> + {this._showPalette && <AnnotationPalette ref={r => (this._annoPaletteView = r)} Document={DocCast(Doc.UserDoc().myLightboxDrawings)} />} {this.renderNavBtn(0, undefined, this._props.PanelHeight / 2 - 12.5, 'chevron-left', this._doc && this._history.length, this.previous)} {this.renderNavBtn( this._props.PanelWidth - Math.min(this._props.PanelWidth / 4, this._props.maxBorder[0]), diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index fd1af7547..757fc3fe2 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1119,7 +1119,6 @@ export class MainView extends ObservableReactComponent<{}> { <GPTPopup key="gptpopup" /> <SchemaCSVPopUp key="schemacsvpopup" /> <GenerativeFill imageEditorOpen={ImageEditor.Open} imageEditorSource={ImageEditor.Source} imageRootDoc={ImageEditor.RootDoc} addDoc={ImageEditor.AddDoc} /> - <AnnotationPalette /> </div> ); } diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 27c85533f..241087fd2 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -78,7 +78,7 @@ export class CollectionCarousel3DView extends CollectionSubView() { // suppressSetHeight={true} NativeWidth={returnZero} NativeHeight={returnZero} - fitWidth={undefined} + fitWidth={this._props.childLayoutFitWidth} onDoubleClickScript={this.onChildDoubleClick} renderDepth={this._props.renderDepth + 1} LayoutTemplate={this._props.childLayoutTemplate} diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index 2adad68e0..8b083de15 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -8,7 +8,7 @@ import * as React from 'react'; import { StopEvent, returnFalse, returnOne, returnTrue, returnZero } from '../../../ClientUtils'; import { emptyFunction } from '../../../Utils'; import { Doc, Opt } from '../../../fields/Doc'; -import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; +import { Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { DocumentType } from '../../documents/DocumentTypes'; import { DragManager } from '../../util/DragManager'; import { ContextMenu } from '../ContextMenu'; @@ -144,6 +144,7 @@ export class CollectionCarouselView extends CollectionSubView() { revealItems.push({description: 'Quiz Cards', event: () => {this.layoutDoc.filterOp = cardMode.QUIZ;}, icon: 'pencil',}); // prettier-ignore !revealOptions && cm.addItem({ description: 'Filter Flashcards', addDivider: false, noexpand: true, subitems: revealItems, icon: 'layer-group' }); }; + childFitWidth = (doc: Doc) => Cast(this.Document.childLayoutFitWidth, 'boolean', this._props.childLayoutFitWidth?.(doc) ?? Cast(doc.layout_fitWidth, 'boolean', null)); @computed get content() { const index = NumCast(this.layoutDoc._carousel_index); const curDoc = this.carouselItems?.[index]; @@ -154,10 +155,11 @@ export class CollectionCarouselView extends CollectionSubView() { <div className="collectionCarouselView-image" key="image"> <DocumentView {...this._props} - NativeWidth={returnZero} - NativeHeight={returnZero} - fitWidth={undefined} + // NativeWidth={returnZero} + // NativeHeight={returnZero} + fitWidth={returnTrue} setContentViewBox={undefined} + containerViewPath={this.DocumentView?.().docViewPath} onDoubleClickScript={this.onContentDoubleClick} onClickScript={this.onContentClick} isDocumentActive={this._props.childDocumentsActive?.() ? this._props.isDocumentActive : this._props.isContentActive} @@ -169,6 +171,7 @@ export class CollectionCarouselView extends CollectionSubView() { Document={curDoc.layout} TemplateDataDocument={DocCast(curDoc.layout.resolvedDataDoc)} PanelHeight={this.panelHeight} + PanelWidth={this._props.PanelWidth} /> </div> {!carouselShowsCaptions ? null : ( diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d0f65866b..f2b94fabc 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1312,7 +1312,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection this._drawing.push(inkDoc); this.addDocument(inkDoc); }); - const collection = containerDoc || this._marqueeViewRef.current?.collection(undefined, true, this._drawing); + const collection = this._marqueeViewRef.current?.collection(undefined, true, this._drawing); if (collection) { const docData = collection[DocData]; docData.title = opts.text.match(/^(.*?)~~~.*$/)?.[1] || opts.text; @@ -1329,14 +1329,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection removeDrawing = (doc?: Doc) => { this._batch = UndoManager.StartBatch('regenerateDrawing'); if (doc) { - const docData = DocCast(doc[DocData]); + const docData = doc[DocData]; const children = DocListCast(docData.data); + this._props.removeDocument?.(doc); this._props.removeDocument?.(children); - // this._props.removeDocument?.(doc); } else { - this._props.removeDocument?.(this._drawing); - // if (this._drawingContainer) this._props.removeDocument?.(this._drawingContainer); + if (this._drawingContainer) this._props.removeDocument?.(this._drawingContainer); } + this._drawing = []; }; @action diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 5aff3ed6f..8560323c9 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -363,7 +363,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps this.hideMarquee(); }); - getCollection = action((selected: Doc[], creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, makeGroup: Opt<boolean>) => { + public static getCollection = action((selected: Doc[], creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, makeGroup: Opt<boolean>, bounds: MarqueeViewBounds) => { const newCollection = creator ? creator(selected, { title: 'nested stack' }) : ((doc: Doc) => { @@ -375,14 +375,13 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps return doc; })(Doc.MakeCopy(Doc.UserDoc().emptyCollection as Doc, true)); newCollection.isSystem = undefined; - newCollection._width = this.Bounds.width || 1; // if width/height are unset/0, then groups won't autoexpand to contain their children - newCollection._height = this.Bounds.height || 1; + newCollection._width = bounds.width || 1; // if width/height are unset/0, then groups won't autoexpand to contain their children + newCollection._height = bounds.height || 1; newCollection._dragWhenActive = makeGroup; - newCollection.x = this.Bounds.left; - newCollection.y = this.Bounds.top; + newCollection.x = bounds.left; + newCollection.y = bounds.top; newCollection.layout_fitWidth = true; selected.forEach(d => Doc.SetContainer(d, newCollection)); - this.hideMarquee(); return newCollection; }); @@ -419,7 +418,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps this._props.removeDocument?.(selected); } - const newCollection = this.getCollection(selected, (e as KeyboardEvent)?.key === 't' ? Docs.Create.StackingDocument : undefined, group); + const newCollection = MarqueeView.getCollection(selected, (e as KeyboardEvent)?.key === 't' ? Docs.Create.StackingDocument : undefined, group, this.Bounds); newCollection._freeform_panX = this.Bounds.left + this.Bounds.width / 2; newCollection._freeform_panY = this.Bounds.top + this.Bounds.height / 2; newCollection._currentFrame = activeFrame; diff --git a/src/client/views/smartdraw/AnnotationPalette.tsx b/src/client/views/smartdraw/AnnotationPalette.tsx index c8ce9e653..83f173fcb 100644 --- a/src/client/views/smartdraw/AnnotationPalette.tsx +++ b/src/client/views/smartdraw/AnnotationPalette.tsx @@ -8,13 +8,13 @@ import * as React from 'react'; import { AiOutlineSend } from 'react-icons/ai'; import ReactLoading from 'react-loading'; import { returnAll, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero } from '../../../ClientUtils'; -import { ActiveInkWidth, Doc, DocListCast, StrListCast } from '../../../fields/Doc'; +import { ActiveInkWidth, Doc, DocListCast, Opt, StrListCast } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { InkData, InkField } from '../../../fields/InkField'; import { BoolCast, DocCast, ImageCast, NumCast } from '../../../fields/Types'; import { emptyFunction, unimplementedFunction } from '../../../Utils'; import { Docs } from '../../documents/Documents'; -import { makeUserTemplateButton } from '../../util/DropConverter'; +import { makeUserTemplateButton, makeUserTemplateImage } from '../../util/DropConverter'; import { SettingsManager } from '../../util/SettingsManager'; import { Transform } from '../../util/Transform'; import { undoable, undoBatch } from '../../util/UndoManager'; @@ -28,20 +28,18 @@ import { DrawingOptions, SmartDrawHandler } from './SmartDrawHandler'; import { DocumentType } from '../../documents/DocumentTypes'; import { ImageField } from '../../../fields/URLField'; import { CollectionCarousel3DView } from '../collections/CollectionCarousel3DView'; +import { Copy } from '../../../fields/FieldSymbols'; @observer -export class AnnotationPalette extends ObservableReactComponent<{}> { +export class AnnotationPalette extends ObservableReactComponent<{ Document: Doc }> { static Instance: AnnotationPalette; - @observable private _display: boolean = false; @observable private _paletteMode: 'create' | 'view' = 'view'; @observable private _userInput: string = ''; @observable private _isLoading: boolean = false; @observable private _canInteract: boolean = true; @observable private _showRegenerate: boolean = false; - @observable private _freeFormCanvas = Docs.Create.FreeformDocument([], {}); - @observable private _drawingCarousel = Docs.Create.CarouselDocument([], {}); - @observable private _drawings: Doc[] = []; - private _drawing: Doc[] = []; + @observable private _docView: DocumentView | null = null; + @observable private _docCarouselView: DocumentView | null = null; @observable private _opts: DrawingOptions = { text: '', complexity: 5, size: 200, autoColor: true, x: 0, y: 0 }; private _gptRes: string[] = []; @@ -55,33 +53,16 @@ export class AnnotationPalette extends ObservableReactComponent<{}> { return FieldView.LayoutString(AnnotationPalette, fieldKey); } - public get FreeformCanvas() { - return this._freeFormCanvas; - } - - public get DrawingCarousel() { - return this._drawingCarousel; - } - - // componentDidUpdate(prevProps: Readonly<{}>) { - // const docView = DocumentView.getDocumentView(this._freeFormCanvas); - // const componentView = docView?.ComponentView as CollectionFreeFormView; - // if (componentView) { - // componentView.fitContentOnce(); - // } - // this._freeFormCanvas._freeform_fitContentsToBox = false; - // } + Contains = (view: DocumentView) => { + return (this._docView && (view.containerViewPath?.() ?? []).concat(view).includes(this._docView)) || (this._docCarouselView && (view.containerViewPath?.() ?? []).concat(view).includes(this._docCarouselView)); + }; return170 = () => 170; @action handleKeyPress = async (event: React.KeyboardEvent) => { if (event.key === 'Enter') { - // if (this._showRegenerate) { - // this.regenerate(); - // } else { await this.generateDrawing(); - // } } }; @@ -117,42 +98,34 @@ export class AnnotationPalette extends ObservableReactComponent<{}> { this.setDetail(5); this.setColor(true); this.setSize(200); - this._freeFormCanvas = Docs.Create.FreeformDocument([], {}); - this._drawingCarousel = Docs.Create.CarouselDocument([], {}); this._showRegenerate = false; this._canInteract = true; - this._drawing = []; - this._drawings = []; this._opts = { text: '', complexity: 5, size: 200, autoColor: true, x: 0, y: 0 }; this._gptRes = []; }; - addToPalette = async (doc: Doc) => { - if (!doc.savedAsAnno) { - const clone = await Doc.MakeClone(doc); - clone.clone.title = doc.title; - const image = await this.getIcon(doc); - if (image) { - const imageDoc = Docs.Create.ImageDocument(image); - Doc.AddDocToList(Doc.MyAnnos, 'data', imageDoc); - } - doc.savedAsAnno = true; - // const templateBtn = makeUserTemplateButton(clone.clone); - // Doc.AddDocToList(Doc.MyAnnos, 'data', templateBtn); - // this.resetPalette(true); - } + public static addToPalette = async (doc: Doc) => { + // if (!doc.savedAsAnno) { + // const clone = await Doc.MakeClone(doc); + // clone.clone.title = doc.title; + // const image = (await this.getIcon(doc))?.[Copy](); + // if (image) { + // const imageTemplate = makeUserTemplateImage(clone.clone, image); + // Doc.AddDocToList(Doc.MyAnnos, 'data', imageTemplate); + // doc.savedAsAnno = true; + // } + // this.resetPalette(true); + // } }; - @action - displayPalette = (display: boolean) => { - this._display = display; - }; + // @action + // displayPalette = (display: boolean) => { + // this._display = display; + // }; @undoBatch generateDrawing = action(async () => { this._isLoading = true; - this._drawings = []; - this._drawing = []; for (var i = 0; i < 3; i++) { try { SmartDrawHandler.Instance._addFunc = this.createDrawing; @@ -177,8 +150,8 @@ export class AnnotationPalette extends ObservableReactComponent<{}> { createDrawing = (strokeList: [InkData, string, string][], opts: DrawingOptions, gptRes: string) => { this._opts = opts; this._gptRes.push(gptRes); - this._drawing = []; - // const childDocs = DocListCast(this._drawing1[DocData].data); + const drawing: Doc[] = []; + strokeList.forEach((stroke: [InkData, string, string]) => { const bounds = InkField.getBounds(stroke[0]); const inkWidth = ActiveInkWidth(); @@ -199,51 +172,27 @@ export class AnnotationPalette extends ObservableReactComponent<{}> { ActiveDash(), ActiveIsInkMask() ); - this._drawing.push(inkDoc); - // childDocs.push(inkDoc); + drawing.push(inkDoc); }); - const cv = DocumentView.getDocumentView(this._freeFormCanvas)?.ComponentView as CollectionFreeFormView; - const collection = cv._marqueeViewRef.current?.collection(undefined, true, this._drawing); + const collection = MarqueeView.getCollection(drawing, undefined, true, { left: 1, top: 1, width: 1, height: 1 }); if (collection) { - this._drawings.push(collection); - cv.fitContentOnce(); + Doc.AddDocToList(this._props.Document, 'data', collection); } - this._drawingCarousel = Docs.Create.CarouselDocument(this._drawings, { childLayoutFitWidth: true, _layout_fitWidth: true, _freeform_fitContentsToBox: true }); - this._freeFormCanvas = Docs.Create.FreeformDocument(this._drawing, { _freeform_fitContentsToBox: true }); }; saveDrawing = async () => { - // const cv = DocumentView.getDocumentView(this._freeFormCanvas)?.ComponentView as CollectionFreeFormView; - // if (cv) { - // const collection = cv._marqueeViewRef.current?.collection(undefined, true, this._drawing); - const cIndex: number = this._drawingCarousel.carousel_index as number; - const focusedDrawing = this._drawings[cIndex]; - - const docData = focusedDrawing[DocData]; - docData.title = this._opts.text.match(/^(.*?)~~~.*$/)?.[1] || this._opts.text; - docData.drawingInput = this._opts.text; - docData.drawingComplexity = this._opts.complexity; - docData.drawingColored = this._opts.autoColor; - docData.drawingSize = this._opts.size; - docData.drawingData = this._gptRes[cIndex]; - docData.width = this._opts.size; - // const image = await this.getIcon(collection); - await this.addToPalette(focusedDrawing); - - // if (collection) { - // const docData = collection[DocData]; - // docData.title = this._opts.text.match(/^(.*?)~~~.*$/)?.[1] || this._opts.text; - // docData.drawingInput = this._opts.text; - // docData.drawingComplexity = this._opts.complexity; - // docData.drawingColored = this._opts.autoColor; - // docData.drawingSize = this._opts.size; - // docData.drawingData = this._gptRes; - // docData.width = this._opts.size; - // // const image = await this.getIcon(collection); - // await this.addToPalette(collection); - // } - // } + // const cIndex: number = this._drawingCarousel.carousel_index as number; + // const focusedDrawing = this._drawings[cIndex]; + // const docData = focusedDrawing[DocData]; + // docData.title = this._opts.text.match(/^(.*?)~~~.*$/)?.[1] || this._opts.text; + // docData.drawingInput = this._opts.text; + // docData.drawingComplexity = this._opts.complexity; + // docData.drawingColored = this._opts.autoColor; + // docData.drawingSize = this._opts.size; + // docData.drawingData = this._gptRes[cIndex]; + // docData.width = this._opts.size; + // await AnnotationPalette.addToPalette(focusedDrawing); }; async getIcon(group: Doc) { @@ -255,36 +204,13 @@ export class AnnotationPalette extends ObservableReactComponent<{}> { return undefined; } - @computed get drawingCreator() { - return ( - <DocumentView - Document={this._freeFormCanvas} - addDocument={undefined} - addDocTab={DocumentViewInternal.addDocTabFunc} - pinToPres={DocumentView.PinDoc} - containerViewPath={returnEmptyDoclist} - styleProvider={DefaultStyleProvider} - removeDocument={returnFalse} - ScreenToLocalTransform={Transform.Identity} - PanelWidth={this.return170} - PanelHeight={this.return170} - renderDepth={1} - isContentActive={returnTrue} - focus={emptyFunction} - whenChildContentsActiveChanged={emptyFunction} - childFilters={returnEmptyFilter} - childFiltersByRanges={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - /> - ); - } - render() { - return !this._display ? null : ( + return ( <div className="annotation-palette" style={{ zIndex: 1000 }}> {this._paletteMode === 'view' && ( <> <DocumentView + ref={r => (this._docView = r)} Document={Doc.MyAnnos} addDocument={undefined} addDocTab={DocumentViewInternal.addDocTabFunc} @@ -303,34 +229,19 @@ export class AnnotationPalette extends ObservableReactComponent<{}> { childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} /> - <Button - // style={{ alignSelf: 'center' }} - text="Add" - icon={<FontAwesomeIcon icon="square-plus" />} - // iconPlacement="" - color={SettingsManager.userColor} - onClick={() => this.setPaletteMode('create')} - /> + <Button text="Add" icon={<FontAwesomeIcon icon="square-plus" />} color={SettingsManager.userColor} onClick={() => this.setPaletteMode('create')} /> </> )} {this._paletteMode === 'create' && ( <> <div style={{ display: 'flex', flexDirection: 'row', width: '170px' }}> - {/* <IconButton - tooltip="Advanced Options" - icon={<FontAwesomeIcon icon="caret-right" />} - color={SettingsManager.userColor} - style={{ width: '14px' }} - // onClick={() => { - // this._showOptions = !this._showOptions; - // }} - /> */} <input aria-label="label-input" id="new-label" type="text" style={{ color: 'black', width: '170px' }} value={this._userInput} + onClick={e => e.stopPropagation()} onChange={e => { this.setUserInput(e.target.value); }} @@ -423,29 +334,9 @@ export class AnnotationPalette extends ObservableReactComponent<{}> { /> </div> </div> - <div style={{ display: 'none' }}> - <DocumentView - Document={this._freeFormCanvas} - addDocument={undefined} - addDocTab={DocumentViewInternal.addDocTabFunc} - pinToPres={DocumentView.PinDoc} - containerViewPath={returnEmptyDoclist} - styleProvider={DefaultStyleProvider} - removeDocument={returnFalse} - ScreenToLocalTransform={Transform.Identity} - PanelWidth={this.return170} - PanelHeight={this.return170} - renderDepth={1} - isContentActive={returnTrue} - focus={emptyFunction} - whenChildContentsActiveChanged={emptyFunction} - childFilters={returnEmptyFilter} - childFiltersByRanges={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - /> - </div> <DocumentView - Document={this._drawingCarousel} + ref={r => (this._docCarouselView = r)} + Document={this._props.Document} addDocument={undefined} addDocTab={DocumentViewInternal.addDocTabFunc} pinToPres={DocumentView.PinDoc} diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx index 489f6f92b..ca65ea388 100644 --- a/src/client/views/smartdraw/SmartDrawHandler.tsx +++ b/src/client/views/smartdraw/SmartDrawHandler.tsx @@ -99,7 +99,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { @action displayRegenerate = (x: number, y: number, addFunc: (strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void, deleteFunc: (doc?: Doc) => void) => { - this._selectedDoc = DocumentView.SelectedDocs().lastElement(); + this._selectedDoc = DocumentView.SelectedDocs()?.lastElement(); const docData = this._selectedDoc[DocData]; this._addFunc = addFunc; this._deleteFunc = deleteFunc; @@ -123,7 +123,6 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { this._size = 350; this._autoColor = true; Doc.ActiveTool = InkTool.None; - this._lastInput = { text: '', complexity: 5, size: 350, autoColor: true, x: 0, y: 0 }; }; @action @@ -154,8 +153,6 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { } else { this._showOptions = false; await this.drawWithGPT({ X: this._pageX, Y: this._pageY }, this._userInput, this._complexity, this._size, this._autoColor); - this.hideSmartDrawHandler(); - this._showRegenerate = true; } this._isLoading = false; this._canInteract = true; @@ -176,6 +173,8 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { console.log(res); const strokeData = await this.parseResponse(res, startPt, false, autoColor); this._errorOccurredOnce = false; + this.hideSmartDrawHandler(); + this._showRegenerate = true; return strokeData; } catch (err) { if (this._errorOccurredOnce) { @@ -239,7 +238,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { }); if (regenerate) { if (this._deleteFunc !== unimplementedFunction) this._deleteFunc(this._selectedDoc); - this._addFunc(strokeData, this._lastInput, svg[0], this._selectedDoc); + this._addFunc(strokeData, this._lastInput, svg[0]); } else { this._addFunc(strokeData, this._lastInput, svg[0]); } diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index c86342870..c3e96ab49 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -277,6 +277,7 @@ export class Doc extends RefField { public static get MyDashboards() { return DocCast(Doc.UserDoc().myDashboards); } // prettier-ignore public static get MyTemplates() { return DocCast(Doc.UserDoc().myTemplates); } // prettier-ignore public static get MyAnnos() { return DocCast(Doc.UserDoc().myAnnos); } // prettier-ignore + public static get MyLightboxDrawings() { return DocCast(Doc.UserDoc().myLightboxDrawings); } // prettier-ignore public static get MyImports() { return DocCast(Doc.UserDoc().myImports); } // prettier-ignore public static get MyFilesystem() { return DocCast(Doc.UserDoc().myFilesystem); } // prettier-ignore public static get MyTools() { return DocCast(Doc.UserDoc().myTools); } // prettier-ignore |