aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/collectionFreeForm
diff options
context:
space:
mode:
authorSkitty1238 <157652284+Skitty1238@users.noreply.github.com>2025-06-02 14:18:20 -0400
committerSkitty1238 <157652284+Skitty1238@users.noreply.github.com>2025-06-02 14:18:20 -0400
commit83bfca49c38e12dc575b5037c8fac25f3c21d6c5 (patch)
treed3e66b45d0e95e51d2b6f2672fd367776f19db35 /src/client/views/collections/collectionFreeForm
parente4b5aa5e72cca6dd51e9acf28017cde4233b5cc6 (diff)
parent76a21badf70c82388872ec5485858ab06e303bca (diff)
Merge branch 'master' into task_nodes_aarav
Diffstat (limited to 'src/client/views/collections/collectionFreeForm')
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx109
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx5
2 files changed, 37 insertions, 77 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 2364fd74a..3571dab1a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -176,7 +176,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return renderableEles;
}
@computed get fitContentsToBox() {
- return (this._props.fitContentsToBox?.() || this.Document._freeform_fitContentsToBox) && !this.isAnnotationOverlay;
+ return (this._props.fitContentsToBox?.() || this.Document._freeform_fitContentsToBox || this.Document.freeform_isGroup) && !this.isAnnotationOverlay;
}
@computed get nativeWidth() {
return this._props.NativeWidth?.() || Doc.NativeWidth(this.Document);
@@ -256,8 +256,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
override contentBounds = () => {
const { x, y, r, b } = aggregateBounds(
this._layoutElements.filter(e => e.bounds?.width && !e.bounds.z).map(e => e.bounds!),
- NumCast(this.layoutDoc._xPadding, NumCast(this.layoutDoc._xMargin, this._props.xPadding ?? 0)),
- NumCast(this.layoutDoc._yPadding, NumCast(this.layoutDoc._yMargin, this._props.yPadding ?? 0))
+ NumCast(this.layoutDoc._xMargin, this._props.xMargin ?? 0),
+ NumCast(this.layoutDoc._yMargin, this._props.yMargin ?? 0)
);
const [width, height] = [r - x, b - y];
return {
@@ -342,7 +342,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
*/
focusOnPoint = (options: FocusViewOptions) => {
const { pointFocus, zoomTime, didMove } = options;
- if (!this.Document.isGroup && pointFocus && !didMove) {
+ if (!this.Document.freeform_isGroup && pointFocus && !didMove) {
const dfltScale = this.isAnnotationOverlay ? 1 : 0.25;
if (this.layoutDoc[this.scaleFieldKey] !== dfltScale) {
this.zoomSmoothlyAboutPt(this.screenToFreeformContentsXf.transformPoint(pointFocus.X, pointFocus.Y), dfltScale, zoomTime);
@@ -380,7 +380,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
* @returns
*/
focus = (anchor: Doc, options: FocusViewOptions) => {
- if (anchor.isGroup && !options.docTransform && options.contextPath?.length) {
+ if (Doc.IsFreeformGroup(anchor) && !options.docTransform && options.contextPath?.length) {
// don't focus on group if there's a context path because we're about to focus on a group item
// which will override any group focus. (If we allowed the group to focus, it would mark didMove even if there were no net movement)
return undefined;
@@ -395,7 +395,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}
const xfToCollection = options?.docTransform ?? Transform.Identity();
const savedState = { panX: NumCast(this.Document[this.panXFieldKey]), panY: NumCast(this.Document[this.panYFieldKey]), scale: options?.willZoomCentered ? this.Document[this.scaleFieldKey] : undefined };
- const cantTransform = this.fitContentsToBox || ((this.Document.isGroup || this.layoutDoc._lockedTransform) && !DocumentView.LightboxDoc());
+ const cantTransform = this.fitContentsToBox || ((this.Document.freeform_isGroup || this.layoutDoc._lockedTransform) && !DocumentView.LightboxDoc());
const { panX, panY, scale } = cantTransform || (!options.willPan && !options.willZoomCentered) ? savedState : this.calculatePanIntoView(anchor, xfToCollection, options?.willZoomCentered ? (options?.zoomScale ?? 0.75) : undefined);
// focus on the document in the collection
@@ -514,7 +514,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this._downTime = Date.now();
const scrollMode = e.altKey ? (Doc.UserDoc().freeformScrollMode === freeformScrollMode.Pan ? freeformScrollMode.Zoom : freeformScrollMode.Pan) : Doc.UserDoc().freeformScrollMode;
if (e.button === 0 && (!(e.ctrlKey && !e.metaKey) || scrollMode !== freeformScrollMode.Pan) && this._props.isContentActive()) {
- if (!this.Document.isGroup) {
+ if (!this.Document.freeform_isGroup) {
// group freeforms don't pan when dragged -- instead let the event go through to allow the group itself to drag
// prettier-ignore
const hit = this._clusters.handlePointerDown(this.screenToFreeformContentsXf.transformPoint(e.clientX, e.clientY));
@@ -1259,15 +1259,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
/**
* Adds the created drawing to the freeform canvas and sets the metadata.
*/
- addDrawing = (doc: Doc, opts: DrawingOptions, gptRes: string, x?: number, y?: number) => {
- doc.$title = opts.text;
- doc.$width = opts.size;
- doc.$ai_drawing_input = opts.text;
- doc.$ai_drawing_complexity = opts.complexity;
- doc.$ai_drawing_colored = opts.autoColor;
- doc.$ai_drawing_size = opts.size;
- doc.$ai_drawing_data = gptRes;
- doc.$ai = 'gpt';
+ addDrawing = (doc: Doc, opts: DrawingOptions, x?: number, y?: number) => {
+ doc.$ai_prompt = opts.text;
this._drawingContainer = doc;
if (x !== undefined && y !== undefined) {
[doc.x, doc.y] = this.screenToFreeformContentsXf.transformPoint(x, y);
@@ -1278,7 +1271,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@action
zoom = (pointX: number, pointY: number, deltaY: number): void => {
- if (this.Document.isGroup || this.Document[(this._props.viewField ?? '_') + 'freeform_noZoom']) return;
+ if (this.Document.freeform_isGroup || this.Document[(this._props.viewField ?? '_') + 'freeform_noZoom']) return;
let deltaScale = deltaY > 0 ? 1 / 1.05 : 1.05;
if (deltaScale < 0) deltaScale = -deltaScale;
const [x, y] = this.screenToFreeformContentsXf.transformPoint(pointX, pointY);
@@ -1305,7 +1298,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@action
onPointerWheel = (e: React.WheelEvent): void => {
- if (this.Document.isGroup || !this.isContentActive()) return; // group style collections neither pan nor zoom
+ if (this.Document.freeform_isGroup || !this.isContentActive()) return; // group style collections neither pan nor zoom
SnappingManager.TriggerUserPanned();
if (this.layoutDoc._Transform || this.Document.treeView_OutlineMode === TreeViewType.outline) return;
e.stopPropagation();
@@ -1429,7 +1422,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@action
zoomSmoothlyAboutPt(docpt: number[], scale: number, transitionTime = 500) {
- if (this.Document.isGroup) return;
+ if (this.Document.freeform_isGroup) return;
this.setPanZoomTransition(transitionTime);
const screenXY = this.screenToFreeformContentsXf.inverse().transformPoint(docpt[0], docpt[1]);
this.layoutDoc[this.scaleFieldKey] = scale;
@@ -1512,7 +1505,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
removeDocument = (docs: Doc | Doc[], annotationKey?: string | undefined) => {
const ret = !!this._props.removeDocument?.(docs, annotationKey);
// if this is a group and we have fewer than 2 Docs, then just promote what's left to our parent and get rid of the group.
- if (ret && DocListCast(this.dataDoc[annotationKey ?? this.fieldKey]).length < 2 && this.Document.isGroup) {
+ if (ret && DocListCast(this.dataDoc[annotationKey ?? this.fieldKey]).length < 2 && this.Document.freeform_isGroup) {
this.promoteCollection();
}
return ret;
@@ -1555,7 +1548,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
searchFilterDocs={this.searchFilterDocs}
isDocumentActive={childLayout.pointerEvents === 'none' ? returnFalse : this._props.childDocumentsActive?.() ? this._props.isDocumentActive : this.isContentActive}
isContentActive={this.childContentsActive}
- focus={this.Document.isGroup ? this.groupFocus : this.isAnnotationOverlay ? this._props.focus : this.focus}
+ focus={this.Document.freeform_isGroup ? this.groupFocus : this.isAnnotationOverlay ? this._props.focus : this.focus}
addDocTab={this.addDocTab}
addDocument={this._props.addDocument}
removeDocument={this.removeDocument}
@@ -1740,15 +1733,16 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
});
PinDocView(
anchor,
- { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ? { ...pinProps.pinData, poslayoutview: pinProps.pinData.dataview } : {}), pannable: !this.Document.isGroup, collectionType: true, filters: true } },
+ { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ? { ...pinProps.pinData, poslayoutview: pinProps.pinData.dataview } : {}), pannable: !this.Document.freeform_isGroup, collectionType: true, filters: true } },
this.Document
);
if (addAsAnnotation) {
- if (Cast(this.dataDoc[this._props.fieldKey + '_annotations'], listSpec(Doc), null) !== undefined) {
- Cast(this.dataDoc[this._props.fieldKey + '_annotations'], listSpec(Doc), [])?.push(anchor);
+ const fieldKey = this._props.isAnnotationOverlay ? this._props.fieldKey : this._props.fieldKey + '_annotations';
+ if (Cast(this.dataDoc[fieldKey], listSpec(Doc), null) !== undefined) {
+ Cast(this.dataDoc[fieldKey], listSpec(Doc), [])?.push(anchor);
} else {
- this.dataDoc[this._props.fieldKey + '_annotations'] = new List<Doc>([anchor]);
+ this.dataDoc[fieldKey] = new List<Doc>([anchor]);
}
}
return anchor;
@@ -1773,9 +1767,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this._firstRender = false;
this._disposers.groupBounds = reaction(
() => {
- if (this.Document.isGroup && this.childDocs.length === this.childDocList?.length) {
+ if (this.Document.freeform_isGroup && this.childDocs.length === this.childDocList?.length) {
const clist = this.childDocs.map(cd => ({ x: NumCast(cd.x), y: NumCast(cd.y), width: NumCast(cd._width), height: NumCast(cd._height) }));
- return aggregateBounds(clist, NumCast(this.layoutDoc._xPadding), NumCast(this.layoutDoc._yPadding));
+ return aggregateBounds(clist, NumCast(this.layoutDoc._xMargin), NumCast(this.layoutDoc._yMargin));
}
return undefined;
},
@@ -1935,8 +1929,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const appearance = ContextMenu.Instance.findByDescription('Appearance...');
const appearanceItems = appearance?.subitems ?? [];
- !this.Document.isGroup && appearanceItems.push({ description: 'Reset View', event: this.resetView, icon: 'compress-arrows-alt' });
- !this.Document.isGroup && appearanceItems.push({ description: 'Toggle Auto Reset View', event: this.toggleResetView, icon: 'compress-arrows-alt' });
+ !this.Document.freeform_isGroup && appearanceItems.push({ description: 'Reset View', event: this.resetView, icon: 'compress-arrows-alt' });
+ !this.Document.freeform_isGroup && appearanceItems.push({ description: 'Toggle Auto Reset View', event: this.toggleResetView, icon: 'compress-arrows-alt' });
if (this._props.setContentViewBox === emptyFunction) {
!appearance && ContextMenu.Instance.addItem({ description: 'Appearance...', subitems: appearanceItems, icon: 'eye' });
return;
@@ -1954,7 +1948,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
!Doc.noviceMode && appearanceItems.push({ description: `update icon`, event: () => this.updateIcon(), icon: 'compress-arrows-alt' });
this._props.renderDepth && appearanceItems.push({ description: 'Ungroup collection', event: this.promoteCollection, icon: 'table' });
- this.Document.isGroup && this.Document.transcription && appearanceItems.push({ description: 'Ink to text', event: this.transcribeStrokes, icon: 'font' });
+ this.Document.freeform_isGroup && this.Document.transcription && appearanceItems.push({ description: 'Ink to text', event: this.transcribeStrokes, icon: 'font' });
!Doc.noviceMode ? appearanceItems.push({ description: 'Arrange contents in grid', event: this.layoutDocsInGrid, icon: 'table' }) : null;
!Doc.noviceMode ? appearanceItems.push({ description: (this.Document._freeform_useClusters ? 'Hide' : 'Show') + ' Clusters', event: () => this._clusters.updateClusters(!this.Document._freeform_useClusters), icon: 'braille' }) : null;
@@ -1977,7 +1971,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
event: action(() => {
SmartDrawHandler.Instance.AddDrawing = this.addDrawing;
SmartDrawHandler.Instance.RemoveDrawing = this.removeDrawing;
- !SmartDrawHandler.Instance.ShowRegenerate ? SmartDrawHandler.Instance.displayRegenerate(this._downX, this._downY - 10) : SmartDrawHandler.Instance.hideRegenerate();
+ !SmartDrawHandler.Instance.ShowRegenerate ? SmartDrawHandler.Instance.displayRegenerate(this._downX, this._downY - 10, NumCast(this.layoutDoc[this.scaleFieldKey])) : SmartDrawHandler.Instance.hideRegenerate();
}),
icon: 'pen-to-square',
});
@@ -2013,7 +2007,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
transcribeStrokes = undoable(() => {
- if (this.Document.isGroup && this.Document.transcription) {
+ if (this.Document.freeform_isGroup && this.Document.transcription) {
const text = StrCast(this.Document.transcription);
const lines = text.split('\n');
const height = 30 + 15 * lines.length;
@@ -2031,7 +2025,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
dragStarting = (snapToDraggedDoc: boolean = false, showGroupDragTarget: boolean = true, visited = new Set<Doc>()) => {
if (visited.has(this.Document)) return;
visited.add(this.Document);
- showGroupDragTarget && (this.GroupChildDrag = BoolCast(this.Document.isGroup));
+ showGroupDragTarget && (this.GroupChildDrag = BoolCast(this.Document.freeform_isGroup));
const activeDocs = this.getActiveDocuments();
const size = this.screenToFreeformContentsXf.transformDirection(this._props.PanelWidth(), this._props.PanelHeight());
const selRect = { left: this.panX() - size[0] / 2, top: this.panY() - size[1] / 2, width: size[0], height: size[1] };
@@ -2039,13 +2033,15 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const isDocInView = (doc: Doc, rect: { left: number; top: number; width: number; height: number }) => intersectRect(docDims(doc), rect);
const snappableDocs = activeDocs.filter(doc => doc.z === undefined && isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to
- activeDocs.filter(doc => doc.isGroup && SnappingManager.IsResizing !== doc[Id] && !DragManager.docsBeingDragged.includes(doc)).forEach(doc => DocumentView.getDocumentView(doc)?.ComponentView?.dragStarting?.(snapToDraggedDoc, false, visited));
+ activeDocs
+ .filter(doc => Doc.IsFreeformGroup(doc) && SnappingManager.IsResizing !== doc[Id] && !DragManager.docsBeingDragged.includes(doc))
+ .forEach(doc => DocumentView.getDocumentView(doc)?.ComponentView?.dragStarting?.(snapToDraggedDoc, false, visited));
const horizLines: number[] = [];
const vertLines: number[] = [];
const invXf = this.screenToFreeformContentsXf.inverse();
snappableDocs
- .filter(doc => !doc.isGroup && (snapToDraggedDoc || (SnappingManager.IsResizing !== doc[Id] && !DragManager.docsBeingDragged.includes(doc))))
+ .filter(doc => !Doc.IsFreeformGroup(doc) && (snapToDraggedDoc || (SnappingManager.IsResizing !== doc[Id] && !DragManager.docsBeingDragged.includes(doc))))
.forEach(doc => {
const { left, top, width, height } = docDims(doc);
const topLeftInScreen = invXf.transformPoint(left, top);
@@ -2137,7 +2133,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
{...this._props}
ref={this._marqueeViewRef}
Doc={this.Document}
- ungroup={this.Document.isGroup ? this.promoteCollection : undefined}
+ ungroup={this.Document.freeform_isGroup ? this.promoteCollection : undefined}
nudge={this.isAnnotationOverlay || this._props.renderDepth > 0 ? undefined : this.nudge}
addDocTab={this.addDocTab}
slowLoadDocuments={this.slowLoadDocuments}
@@ -2182,9 +2178,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
placeholder={this._drawingFillInput || StrCast(this.Document.title) || 'Describe image'}
type="text"
value={this._drawingFillInput}
- onChange={action(e => {
- this._drawingFillInput = e.target.value;
- })}
+ onChange={action(e => (this._drawingFillInput = e.target.value))}
/>
<div className="collectionFreeFormView-aiView-strength">
<span className="collectionFreeFormView-aiView-similarity">Similarity</span>
@@ -2213,11 +2207,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
onClick={undoable(
action(() => {
this._drawingFillLoading = true;
- DrawingFillHandler.drawingToImage(this.props.Document, this._fireflyRefStrength, this._drawingFillInput || StrCast(this.Document.title))?.then(
- action(() => {
- this._drawingFillLoading = false;
- })
- );
+ DrawingFillHandler.drawingToImage(this.props.Document, this._fireflyRefStrength, this._drawingFillInput || StrCast(this.Document.title))?.then(action(() => (this._drawingFillLoading = false)));
}),
'create image'
)}
@@ -2225,37 +2215,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
</div>
</div>
</div>
- <div className="collectionfreeformview-aiView-regenerate-container">
- <span className="collectionfreeformview-aiView-subtitle">Regenerate</span>
- <div className="collectionfreeformview-aiView-regenerate">
- <input
- className="collectionfreeformview-aiView-input"
- aria-label="Edit instructions input"
- type="text"
- value={this._regenInput}
- onChange={action(e => {
- this._regenInput = e.target.value;
- })}
- placeholder="..under development.."
- />
- <div className="collectionFreeFormView-aiView-regenBtn">
- <Button
- text="Regenerate"
- type={Type.SEC}
- icon={this._regenLoading ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <AiOutlineSend />}
- iconPlacement="right"
- // onClick={action(async () => {
- // this._regenLoading = true;
- // SmartDrawHandler.Instance.CreateDrawingDoc = this.createDrawingDoc;
- // SmartDrawHandler.Instance.AddDrawing = this.addDrawing;
- // SmartDrawHandler.Instance.RemoveDrawing = this.removeDrawing;
- // await SmartDrawHandler.Instance.regenerate([this.Document], undefined, undefined, this._regenInput, true);
- // this._regenLoading = false;
- // })}
- />
- </div>
- </div>
- </div>
</div>
);
};
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 3cc7c0f2d..c120cddf0 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -190,6 +190,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
FormattedTextBox.SelectOnLoadChar = Doc.UserDoc().defaultTextLayout && !this._props.childLayoutString ? e.key : '';
FormattedTextBox.LiveTextUndo = UndoManager.StartBatch('type new note');
this._props.addLiveTextDocument(DocUtils.GetNewTextDoc('-typed text-', x, y, 200, 100));
+ setTimeout(() => FormattedTextBox.LiveTextUndo?.end(), 100);
e.stopPropagation();
}
};
@@ -372,7 +373,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
? creator(selected, { title: 'nested stack' })
: ((doc: Doc) => {
doc.$data = new List<Doc>(selected);
- doc.$isGroup = makeGroup;
+ doc.$freeform_isGroup = makeGroup;
doc.$title = makeGroup ? 'grouping' : 'nested freeform';
doc._freeform_panX = doc._freeform_panY = 0;
return doc;
@@ -508,7 +509,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
_layout_showSidebar: true,
title: 'overview',
});
- const portal = Docs.Create.FreeformDocument(selected, { title: 'summarized documents', x: this.Bounds.left + 200, y: this.Bounds.top, isGroup: true, backgroundColor: 'transparent' });
+ const portal = Docs.Create.FreeformDocument(selected, { title: 'summarized documents', x: this.Bounds.left + 200, y: this.Bounds.top, freeform_isGroup: true, backgroundColor: 'transparent' });
DocUtils.MakeLink(summary, portal, { link_relationship: 'summary of:summarized by' });
portal.hidden = true;