diff options
Diffstat (limited to 'src/client/views/DocumentDecorations.tsx')
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 106 |
1 files changed, 48 insertions, 58 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 2fb9f0fc1..2a44a9739 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -10,7 +10,6 @@ import { DateField } from '../../fields/DateField'; import { Doc, DocListCast, Field, HierarchyMapping, ReverseHierarchyMap } from '../../fields/Doc'; import { AclAdmin, AclAugment, AclEdit, DocData } from '../../fields/DocSymbols'; import { InkField } from '../../fields/InkField'; -import { RichTextField } from '../../fields/RichTextField'; import { ScriptField } from '../../fields/ScriptField'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; import { GetEffectiveAcl } from '../../fields/util'; @@ -33,7 +32,9 @@ import { CollectionFreeFormView } from './collections/collectionFreeForm'; import { Colors } from './global/globalEnums'; import { DocumentView, OpenWhereMod } from './nodes/DocumentView'; import { ImageBox } from './nodes/ImageBox'; +import { KeyValueBox } from './nodes/KeyValueBox'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; +import { identity } from 'lodash'; interface DocumentDecorationsProps { PanelWidth: number; @@ -57,7 +58,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora @observable _showNothing = true; @observable private _accumulatedTitle = ''; - @observable private _titleControlString: string = '#title'; + @observable private _titleControlString: string = '$title'; @observable private _editingTitle = false; @observable private _hidden = false; @observable private _isRotating: boolean = false; @@ -73,11 +74,18 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora DocumentDecorations.Instance = this; document.addEventListener('pointermove', // show decorations whenever pointer moves outside of selection bounds. action(e => { + let inputting = false; + if (this._titleControlString.startsWith('$')) { + const titleFieldKey = this._titleControlString.substring(1); + if (SelectionManager.Views[0]?.Document[titleFieldKey] !== this._accumulatedTitle) { + inputting = true; + } + } const center = {x: (this.Bounds.x+this.Bounds.r)/2, y: (this.Bounds.y+this.Bounds.b)/2}; const {x,y} = Utils.rotPt(e.clientX - center.x, e.clientY - center.y, NumCast(SelectionManager.Views.lastElement()?.screenToViewTransform().Rotate)); - (this._showNothing = !DocumentButtonBar.Instance?._tooltipOpen && !(this.Bounds.x !== Number.MAX_VALUE && // + (this._showNothing = !inputting && !DocumentButtonBar.Instance?._tooltipOpen && !(this.Bounds.x !== Number.MAX_VALUE && // (this.Bounds.x > center.x+x || this.Bounds.r < center.x+x || this.Bounds.y > center.y+y || this.Bounds.b < center.y+y ))); })); // prettier-ignore @@ -111,9 +119,9 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora @action titleBlur = () => { - if (this._accumulatedTitle.startsWith('#') || this._accumulatedTitle.startsWith('=')) { + if (this._accumulatedTitle.startsWith('$')) { this._titleControlString = this._accumulatedTitle; - } else if (this._titleControlString.startsWith('#')) { + } else if (this._titleControlString.startsWith('$')) { if (this._accumulatedTitle.startsWith('-->#')) { SelectionManager.Docs.forEach(doc => (doc[DocData].onViewMounted = ScriptField.MakeScript(`updateTagsCollection(this)`))); } @@ -124,33 +132,8 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora SelectionManager.Views.forEach(d => { if (titleFieldKey === 'title') { d.dataDoc.title_custom = !this._accumulatedTitle.startsWith('-'); - if (StrCast(d.Document.title).startsWith('@') && !this._accumulatedTitle.startsWith('@')) { - Doc.RemFromMyPublished(d.Document); - } - if (!StrCast(d.Document.title).startsWith('@') && this._accumulatedTitle.startsWith('@')) { - Doc.AddToMyPublished(d.Document); - } - } - //@ts-ignore - const titleField = +this._accumulatedTitle == this._accumulatedTitle ? +this._accumulatedTitle : this._accumulatedTitle; - - if (titleField.toString().startsWith('<this>')) { - const title = titleField.toString().replace(/<this>\.?/, ''); - const curKey = Doc.LayoutFieldKey(d.Document); - if (curKey !== title) { - if (title) { - if (d.dataDoc[title] === undefined || d.dataDoc[title] instanceof RichTextField || typeof d.dataDoc[title] === 'string') { - d.Document.layout_fieldKey = `layout_${title}`; - d.Document[`layout_${title}`] = FormattedTextBox.LayoutString(title); - d.Document[`${title}_nativeWidth`] = d.Document[`${title}_nativeHeight`] = 0; - } - } else { - d.Document.layout_fieldKey = undefined; - } - } - } else { - Doc.SetInPlace(d.Document, titleFieldKey, titleField, true); } + KeyValueBox.SetField(d.Document, titleFieldKey, this._accumulatedTitle); }), 'edit title' ); @@ -181,7 +164,8 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora e => this.onBackgroundMove(true, e), emptyFunction, action(e => { - !this._editingTitle && (this._accumulatedTitle = this._titleControlString.startsWith('#') ? this.selectionTitle : this._titleControlString); + const selected = SelectionManager.Views.length === 1 ? SelectionManager.Docs[0] : undefined; + !this._editingTitle && (this._accumulatedTitle = this._titleControlString.startsWith('$') ? (selected && Field.toKeyValueString(selected, this._titleControlString.substring(1))) || '-unset-' : this._titleControlString); this._editingTitle = true; this._keyinput.current && setTimeout(this._keyinput.current.focus); }) @@ -354,8 +338,8 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora const newloccentern = seldocview.screenToContentsTransform().transformPoint(rotCenter[0], rotCenter[1]); const newlocenter = [newloccentern[0] - NumCast(seldocview.layoutDoc._width) / 2, newloccentern[1] - NumCast(seldocview.layoutDoc._height) / 2]; const final = Utils.rotPt(newlocenter[0], newlocenter[1], -(NumCast(seldocview.Document._rotation) / 180) * Math.PI); - seldocview.Document.rotation_centerX = final.x / NumCast(seldocview.layoutDoc._width); - seldocview.Document.rotation_centerY = final.y / NumCast(seldocview.layoutDoc._height); + seldocview.Document._rotation_centerX = final.x / NumCast(seldocview.layoutDoc._width); + seldocview.Document._rotation_centerY = final.y / NumCast(seldocview.layoutDoc._height); }; @action @@ -368,8 +352,10 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora (e: PointerEvent, down: number[], delta: number[]) => // return false to keep getting events this.setRotateCenter(seldocview, [this.rotCenter[0] + delta[0], this.rotCenter[1] + delta[1]]) as any as boolean, action(e => (this._isRotating = false)), // upEvent - action(e => (seldocview.Document.rotation_centerX = seldocview.Document.rotation_centerY = 0)) + action(e => (seldocview.Document._rotation_centerX = seldocview.Document._rotation_centerY = 0)), + true ); // prettier-ignore + e.stopPropagation(); }; @action @@ -441,9 +427,13 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora SnappingManager.SetIsResizing(SelectionManager.Docs.lastElement()); // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction); e.stopPropagation(); - this._resizeHdlId = e.currentTarget.className; + const id = (this._resizeHdlId = e.currentTarget.className); + const pad = id.includes('Left') || id.includes('Right') ? Number(getComputedStyle(e.target as any).width.replace('px', '')) / 2 : 0; const bounds = e.currentTarget.getBoundingClientRect(); - this._offset = { x: this._resizeHdlId.toLowerCase().includes('left') ? bounds.right - e.clientX : bounds.left - e.clientX, y: this._resizeHdlId.toLowerCase().includes('top') ? bounds.bottom - e.clientY : bounds.top - e.clientY }; + this._offset = { + x: id.toLowerCase().includes('left') ? bounds.right - e.clientX - pad : bounds.left - e.clientX + pad, // + y: id.toLowerCase().includes('top') ? bounds.bottom - e.clientY - pad : bounds.top - e.clientY + pad, + }; this._resizeUndo = UndoManager.StartBatch('drag resizing'); this._snapPt = { x: e.pageX, y: e.pageY }; SelectionManager.Views.forEach(docView => docView.CollectionFreeFormView?.dragStarting(false, false)); @@ -622,11 +612,8 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora get selectionTitle(): string { if (SelectionManager.Views.length === 1) { const selected = SelectionManager.Views[0]; - if (this._titleControlString.startsWith('=')) { - return ScriptField.MakeFunction(this._titleControlString.substring(1), { doc: Doc.name })?.script.run({ self: selected.Document, this: selected.layoutDoc }, console.log).result?.toString() || ''; - } - if (this._titleControlString.startsWith('#')) { - return Field.toString(selected.Document[this._titleControlString.substring(1)] as Field) || '-unset-'; + if (this._titleControlString.startsWith('$')) { + return Field.toJavascriptString(selected.Document[this._titleControlString.substring(1)] as Field) || '-unset-'; } return this._accumulatedTitle; } @@ -638,7 +625,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora if (lastView) { const invXf = lastView.screenToContentsTransform().inverse(); const seldoc = lastView.layoutDoc; - const loccenter = Utils.rotPt(NumCast(seldoc.rotation_centerX) * NumCast(seldoc._width), NumCast(seldoc.rotation_centerY) * NumCast(seldoc._height), invXf.Rotate); + const loccenter = Utils.rotPt(NumCast(seldoc._rotation_centerX) * NumCast(seldoc._width), NumCast(seldoc._rotation_centerY) * NumCast(seldoc._height), invXf.Rotate); return invXf.transformPoint(loccenter.x + NumCast(seldoc._width) / 2, loccenter.y + NumCast(seldoc._height) / 2); } return this._rotCenter; @@ -731,21 +718,24 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora ) : null; const titleArea = this._editingTitle ? ( - <input - ref={this._keyinput} - className="documentDecorations-title" - type="text" - name="dynbox" - autoComplete="on" - value={hideTitle ? '' : this._accumulatedTitle} - onBlur={action((e: React.FocusEvent) => { - this._editingTitle = false; - !hideTitle && this.titleBlur(); - })} - onChange={action(e => !hideTitle && (this._accumulatedTitle = e.target.value))} - onKeyDown={hideTitle ? emptyFunction : this.titleEntered} - onPointerDown={e => e.stopPropagation()} - /> + <> + {r - x < 150 ? null : <span>{this._titleControlString + ':'}</span>} + <input + ref={this._keyinput} + className="documentDecorations-title" + type="text" + name="dynbox" + autoComplete="on" + value={hideTitle ? '' : this._accumulatedTitle} + onBlur={action((e: React.FocusEvent) => { + this._editingTitle = false; + this.titleBlur(); + })} + onChange={action(e => !hideTitle && (this._accumulatedTitle = e.target.value))} + onKeyDown={hideTitle ? emptyFunction : this.titleEntered} + onPointerDown={e => e.stopPropagation()} + /> + </> ) : ( <div className="documentDecorations-title" key="title"> {hideTitle ? null : ( |