From 33f416349c00bdec405455340befb0ca85b2fee4 Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Mon, 1 Jul 2024 13:54:07 -0400 Subject: weird error? --- .../collectionFreeForm/CollectionFreeFormView.tsx | 107 +++++--- .../collections/collectionFreeForm/MarqueeView.tsx | 2 + .../collectionFreeForm/SmartDrawHandler.tsx | 295 --------------------- 3 files changed, 72 insertions(+), 332 deletions(-) delete mode 100644 src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx (limited to 'src/client/views/collections/collectionFreeForm') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index b8257ff31..467191735 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -7,7 +7,6 @@ import { action, computed, IReactionDisposer, makeObservable, observable, reacti import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; -import { TbAlpha } from 'react-icons/tb'; import { ClientUtils, DashColor, lightOrDark, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, UpdateIcon } from '../../../../ClientUtils'; import { DateField } from '../../../../fields/DateField'; import { ActiveEraserWidth, ActiveInkWidth, Doc, DocListCast, Field, FieldType, Opt, SetActiveInkColor, SetActiveInkWidth } from '../../../../fields/Doc'; @@ -56,7 +55,7 @@ import { CollectionFreeFormPannableContents } from './CollectionFreeFormPannable import { CollectionFreeFormRemoteCursors } from './CollectionFreeFormRemoteCursors'; import './CollectionFreeFormView.scss'; import { MarqueeView } from './MarqueeView'; -import { SmartDrawHandler } from './SmartDrawHandler'; +import { DrawingOptions, SmartDrawHandler } from '../../smartdraw/SmartDrawHandler'; @observer class CollectionFreeFormOverlayView extends React.Component<{ elements: () => ViewDefResult[] }> { @@ -120,6 +119,7 @@ export class CollectionFreeFormView extends CollectionSubView(); @observable _marqueeViewRef = React.createRef(); @@ -514,7 +514,7 @@ export class CollectionFreeFormView extends CollectionSubView { this._deleteList.lastElement()?._props.removeDocument?.(this._deleteList.map(ink => ink.Document)); @@ -607,12 +608,12 @@ export class CollectionFreeFormView extends CollectionSubView { + e.stopImmediatePropagation(); const currPoint = { X: e.clientX, Y: e.clientY }; this._eraserPts.push([currPoint.X, currPoint.Y]); this._eraserPts = this._eraserPts.slice(Math.max(0, this._eraserPts.length - 5)); if (Doc.ActiveTool === InkTool.RadiusEraser) { const strokeMap: Map = this.getRadiusEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint); - strokeMap.forEach((intersects, stroke) => { if (!this._deleteList.includes(stroke)) { this._deleteList.push(stroke); @@ -682,9 +683,9 @@ export class CollectionFreeFormView extends CollectionSubView { + e.preventDefault(); + e.stopImmediatePropagation(); this.erase(e, [0, 0]); - e.stopPropagation(); - return false; }; /** @@ -696,32 +697,32 @@ export class CollectionFreeFormView extends CollectionSubView { - const currPoint = { X: e.clientX, Y: e.clientY }; - this._eraserPts.push([currPoint.X, currPoint.Y]); - this._eraserPts = this._eraserPts.slice(Math.max(0, this._eraserPts.length - 5)); - const strokeMap: Map = this.getRadiusEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint); - - strokeMap.forEach((intersects, stroke) => { - if (!this._deleteList.includes(stroke)) { - this._deleteList.push(stroke); - SetActiveInkWidth(StrCast(stroke.Document.stroke_width?.toString()) || '1'); - SetActiveInkColor(StrCast(stroke.Document.color?.toString()) || 'black'); - const segments = this.radiusErase(stroke, intersects.sort()); - segments?.forEach(segment => - this.forceStrokeGesture( - e, - Gestures.Stroke, - segment.reduce((data, curve) => [...data, ...curve.points.map(p => stroke.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]) - ) - ); - } - stroke.layoutDoc.opacity = 0; - stroke.layoutDoc.dontIntersect = true; - }); - return false; - }; + // @action + // onRadiusEraserMove = (e: PointerEvent, down: number[], delta: number[]) => { + // const currPoint = { X: e.clientX, Y: e.clientY }; + // this._eraserPts.push([currPoint.X, currPoint.Y]); + // this._eraserPts = this._eraserPts.slice(Math.max(0, this._eraserPts.length - 5)); + // const strokeMap: Map = this.getRadiusEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint); + + // strokeMap.forEach((intersects, stroke) => { + // if (!this._deleteList.includes(stroke)) { + // this._deleteList.push(stroke); + // SetActiveInkWidth(StrCast(stroke.Document.stroke_width?.toString()) || '1'); + // SetActiveInkColor(StrCast(stroke.Document.color?.toString()) || 'black'); + // const segments = this.radiusErase(stroke, intersects.sort()); + // segments?.forEach(segment => + // this.forceStrokeGesture( + // e, + // Gestures.Stroke, + // segment.reduce((data, curve) => [...data, ...curve.points.map(p => stroke.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]) + // ) + // ); + // } + // stroke.layoutDoc.opacity = 0; + // stroke.layoutDoc.dontIntersect = true; + // }); + // return false; + // }; forceStrokeGesture = (e: PointerEvent, gesture: Gestures, points: InkData, text?: any) => { this.onGesture(e, new GestureUtils.GestureEvent(gesture, points, InkField.getBounds(points), text)); @@ -1263,15 +1264,14 @@ export class CollectionFreeFormView extends CollectionSubView { - SmartDrawHandler.Instance.displaySmartDrawHandler(e.pageX, e.pageY, this.createInkStrokes); + showSmartDraw = (e: PointerEvent, doubleTap?: boolean) => { + SmartDrawHandler.Instance.displaySmartDrawHandler(e.pageX, e.pageY, this.createDrawing, this.removeDrawing); }; + _drawing: Doc[] = []; @undoBatch - createInkStrokes = (strokeData: [InkData, string, string][]) => { + createDrawing = (e: React.PointerEvent, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string) => { strokeData.forEach((stroke: [InkData, string, string]) => { - // const points: InkData = FitCurve(inkData, 20) as InkData; - // const allPts = GenerateControlPoints(inkData, alpha); const bounds = InkField.getBounds(stroke[0]); const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; @@ -1288,8 +1288,33 @@ export class CollectionFreeFormView extends CollectionSubView { + this._batch = UndoManager.StartBatch('regenerateDrawing'); + if (doc) { + const docData: Doc = doc[DocData]; + const children = docData.data as unknown as Doc[]; + this._props.removeDocument?.(doc); + this._props.removeDocument?.(children); + } else { + this._props.removeDocument?.(this._drawing); + } + this._drawing = []; }; @action @@ -1995,6 +2020,14 @@ export class CollectionFreeFormView extends CollectionSubView { + this._showDrawingEditor = !this._showDrawingEditor; + this._showDrawingEditor ? SmartDrawHandler.Instance.displayRegenerate(this._downX, this._downY - 10, this.createDrawing, this.removeDrawing) : SmartDrawHandler.Instance.hideRegenerate(); + }), + icon: 'pen-to-square', + }); this._props.renderDepth && optionItems.push({ description: 'Use Background Color as Default', diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index dc15c83c5..23cf487ec 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -36,6 +36,7 @@ import { CollectionFreeFormView } from './CollectionFreeFormView'; import { ImageLabelHandler } from './ImageLabelHandler'; import { MarqueeOptionsMenu } from './MarqueeOptionsMenu'; import './MarqueeView.scss'; +import { collectionOf } from '@turf/turf'; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -426,6 +427,7 @@ export class MarqueeView extends ObservableReactComponent { - static Instance: SmartDrawHandler; - - @observable private _display: boolean = false; - @observable private _pageX: number = 0; - @observable private _pageY: number = 0; - @observable private _yRelativeToTop: boolean = true; - @observable private _isLoading: boolean = false; - @observable private _userInput: string = ''; - @observable private _showOptions: boolean = false; - @observable private _menuIcon: string = 'caret-right'; - @observable private _complexity: number = 5; - @observable private _size: number = 300; - @observable private _autoColor: boolean = true; - @observable private _showRegenerate: boolean = false; - private _addToDocFunc: (strokeList: [InkData, string, string][]) => void = () => {}; - private _lastX: number = 0; - private _lastY: number = 0; - - constructor(props: any) { - super(props); - makeObservable(this); - SmartDrawHandler.Instance = this; - } - - @action - setUserInput = (input: string) => { - this._userInput = input; - }; - - @action - displaySmartDrawHandler = (x: number, y: number, addToDoc: (strokeData: [InkData, string, string][]) => void) => { - this._pageX = x; - this._pageY = y; - this._display = true; - this._addToDocFunc = addToDoc; - }; - - hideSmartDrawHandler = () => { - this._showRegenerate = false; - this._display = false; - this._isLoading = false; - this._showOptions = false; - this._menuIcon = 'caret-right'; - }; - - hideRegenerate = () => { - this._showRegenerate = false; - this._userInput = ''; - this._complexity = 5; - this._size = 300; - this._autoColor = true; - this._isLoading = false; - }; - - toggleMenu = () => { - this._showOptions = !this._showOptions; - this._menuIcon === 'caret-right' ? (this._menuIcon = 'caret-down') : (this._menuIcon = 'caret-right'); - }; - - @action - drawWithGPT = async (e: React.MouseEvent, startPoint: { X: number; Y: number }, input: string, regenerate: boolean = false) => { - if (this._userInput === '') return; - e.stopPropagation(); - this._lastX = startPoint.X; - this._lastY = startPoint.Y; - this._isLoading = true; - this._showOptions = false; - try { - const res = await gptAPICall(`"${input}", "${this._complexity}", "${this._size}"`, GPTCallType.DRAW); - if (!res) { - console.error('GPT call failed'); - return; - } - const svg = res.match(/]*>([\s\S]*?)<\/svg>/g); - if (svg) { - const svgObject = await parse(svg[0]); - const svgStrokes: any = svgObject.children; - const strokeData: [InkData, string, string][] = []; - svgStrokes.forEach((child: any) => { - const convertedBezier: InkData = SVGToBezier(child.name, child.attributes); - strokeData.push([ - convertedBezier.map(point => { - return { X: point.X + startPoint.X - this._size / 1.5, Y: point.Y + startPoint.Y - this._size / 2 }; - }), - this._autoColor ? child.attributes.stroke : undefined, - this._autoColor ? child.attributes.fill : undefined, - ]); - }); - if (regenerate) UndoManager.Undo(); - this._addToDocFunc(strokeData); - } - } catch (err) { - console.error('GPT call failed', err); - } - this.hideSmartDrawHandler(); - this._showRegenerate = true; - }; - - regenerate = (e: React.MouseEvent) => { - this.drawWithGPT(e, { X: this._lastX, Y: this._lastY }, `Regenerate the item "${this._userInput}"`, true); - }; - - render() { - if (this._display) { - return ( -
-
- { - this.hideSmartDrawHandler(); - this.hideRegenerate(); - }} - icon={} - color={SettingsManager.userColor} - style={{ width: '19px' }} - /> - { - this.setUserInput(e.target.value); - }} - placeholder="Enter item to draw" - /> - } - color={SettingsManager.userColor} - style={{ width: '14px' }} - onClick={() => { - this._showOptions = !this._showOptions; - }} - /> -
- {this._showOptions && ( - <> -
-
- Auto color - (this._autoColor = !this._autoColor)} - /> -
-
- Complexity - { - this._complexity = val as number; - }} - valueLabelDisplay="auto" - /> -
-
- Size (in pixels) - { - this._size = val as number; - }} - valueLabelDisplay="auto" - /> -
-
- - )} -
- ); - } else if (this._showRegenerate) { - return ( -
-
- } color={SettingsManager.userColor} style={{ width: '19px' }} /> - : } - color={SettingsManager.userColor} - onClick={e => { - this.regenerate(e); - }} - /> -
-
- ); - } else { - return <>; - } - } -} -- cgit v1.2.3-70-g09d2