diff options
Diffstat (limited to 'src/client/views/DocumentDecorations.tsx')
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 61 |
1 files changed, 42 insertions, 19 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 93c3e3338..34b05da56 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -1,7 +1,8 @@ +import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; import { IconButton } from 'browndash-components'; -import { action, computed, makeObservable, observable, runInAction } from 'mobx'; +import { action, computed, makeObservable, observable, runInAction, trace } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { FaUndo } from 'react-icons/fa'; @@ -34,6 +35,8 @@ import { DocumentView } from './nodes/DocumentView'; import { ImageBox } from './nodes/ImageBox'; import { OpenWhere, OpenWhereMod } from './nodes/OpenWhere'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; +import { TagsView } from './TagsView'; +import { setTime } from 'react-datepicker/dist/date_utils'; interface DocumentDecorationsProps { PanelWidth: number; @@ -57,6 +60,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora private _interactionLock?: boolean; @observable _showNothing = true; + @observable private _forceRender = 0 @observable private _accumulatedTitle = ''; @observable private _titleControlString: string = '$title'; @observable private _editingTitle = false; @@ -88,6 +92,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora (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 } @@ -145,7 +150,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora titleEntered = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { e.stopPropagation(); - (e.target as any).blur(); + (e.target as HTMLElement).blur?.(); } }; @@ -170,7 +175,8 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora !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); - }) + }), + false // can't preventDefault since that will mess up goldenlayout if you drag over the tab bar. so just stop propagation below. ); e.stopPropagation(); } @@ -192,7 +198,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora if (containers.size > 1) return false; const { left, top } = dragDocView.getBounds || { left: 0, top: 0 }; const dragData = new DragManager.DocumentDragData(DocumentView.SelectedDocs(), dragDocView._props.dropAction); - dragData.offset = dragDocView.screenToContentsTransform().transformDirection(e.x - left, e.y - top); + dragData.offset = dragDocView.screenToViewTransform().transformDirection(e.x - left, e.y - top); dragData.moveDocument = dragDocView._props.moveDocument; dragData.removeDocument = dragDocView._props.removeDocument; dragData.isDocDecorationMove = true; @@ -229,7 +235,8 @@ 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 { - iconView._props.removeDocument?.(iconView.Document); + if (iconView.Document.annotationOn && iconView.Document.face) iconView.Document.hidden = true; + else iconView._props.removeDocument?.(iconView.Document); } }); views.forEach(DocumentView.DeselectView); @@ -239,7 +246,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora } }); if (!this._iconifyBatch) { - (document.activeElement as any).blur?.(); + (document.activeElement as HTMLElement).blur?.(); this._iconifyBatch = UndoManager.StartBatch(forceDeleteOrIconify ? 'delete selected docs' : 'iconifying'); } else { // eslint-disable-next-line no-param-reassign @@ -254,7 +261,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora setupMoveUpEvents(this, e, () => DragManager.StartWindowDrag?.(e, [DocumentView.SelectedDocs().lastElement()]) ?? false, emptyFunction, this.onMaximizeClick, false, false); e.stopPropagation(); }; - onMaximizeClick = (e: any): void => { + onMaximizeClick = (e: PointerEvent): void => { const selView = DocumentView.Selected()[0]; if (selView) { if (e.ctrlKey) { @@ -335,7 +342,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora setRotateCenter = (seldocview: DocumentView, rotCenter: number[]) => { const selDoc = seldocview.Document; - const newloccentern = seldocview.screenToContentsTransform().transformPoint(rotCenter[0], rotCenter[1]); + const newloccentern = seldocview.screenToViewTransform().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); selDoc._rotation_centerX = final.x / NumCast(seldocview.layoutDoc._width); @@ -349,8 +356,10 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora setupMoveUpEvents( this, e, - (moveEv: 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, + (moveEv: PointerEvent, down: number[], delta: number[]) => { + this.setRotateCenter(seldocview, [this.rotCenter[0] + delta[0], this.rotCenter[1] + delta[1]]); + return false; + }, action(() => { this._isRotating = false; }), // upEvent action(() => { seldocview.Document._rotation_centerX = seldocview.Document._rotation_centerY = 0; }), true @@ -430,7 +439,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction); e.stopPropagation(); 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 pad = id.includes('Left') || id.includes('Right') ? Number(getComputedStyle(e.target as HTMLElement).width?.replace('px', '')) / 2 : 0; const bounds = e.currentTarget.getBoundingClientRect(); this._offset = { x: id.toLowerCase().includes('left') ? bounds.right - e.clientX - pad : bounds.left - e.clientX + pad, // @@ -478,7 +487,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora const scaleAspect = {x:scale.x === 1 && hasFixedAspect ? scale.y : scale.x, y: scale.x !== 1 && hasFixedAspect ? scale.x : scale.y}; DocumentView.Selected().forEach(docView => this.resizeView(docView, refPt, scaleAspect, { dragHdl, ctrlKey:e.ctrlKey })); // prettier-ignore - await new Promise<any>(res => { setTimeout(() => { res(this._interactionLock = undefined)})}); + await new Promise<void>(res => { setTimeout(() => { res(this._interactionLock = undefined)})}); }); // prettier-ignore return false; @@ -613,8 +622,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora }); }; - @computed - get selectionTitle(): string { + @computed get selectionTitle(): string { if (DocumentView.Selected().length === 1) { const selected = DocumentView.Selected()[0]; if (this._titleControlString.startsWith('$')) { @@ -628,15 +636,16 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora @computed get rotCenter() { const lastView = DocumentView.Selected().lastElement(); if (lastView) { - const invXf = lastView.screenToContentsTransform().inverse(); + const invXf = lastView.screenToViewTransform().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); return invXf.transformPoint(loccenter.x + NumCast(seldoc._width) / 2, loccenter.y + NumCast(seldoc._height) / 2); } return this._rotCenter; } - +; render() { + this._forceRender; const { b, r, x, y } = this.Bounds; const seldocview = DocumentView.Selected().lastElement(); if (SnappingManager.IsDragging || r - x < 1 || x === Number.MAX_VALUE || !seldocview || this._hidden || isNaN(r) || isNaN(b) || isNaN(x) || isNaN(y)) { @@ -649,6 +658,11 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora return null; } + if (seldocview && !seldocview?.ContentDiv?.getBoundingClientRect().width) { + setTimeout(action(() => this._forceRender++)); // if the selected Doc has no width, then assume it's stil being layed out and try to render again later. + return null; + } + // sharing const acl = GetEffectiveAcl(!this._showLayoutAcl ? Doc.GetProto(seldocview.Document) : seldocview.Document); const docShareMode = HierarchyMapping.get(acl)!.name; @@ -681,10 +695,10 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora const collectionAcl = docView.containerViewPath?.()?.lastElement() ? GetEffectiveAcl(docView.containerViewPath?.().lastElement().dataDoc) : AclEdit; return collectionAcl !== AclAdmin && collectionAcl !== AclEdit && GetEffectiveAcl(docView.Document) !== AclAdmin; }); - const topBtn = (key: string, icon: string, pointerDown: undefined | ((e: React.PointerEvent) => void), click: undefined | ((e: any) => void), title: string) => ( + const topBtn = (key: string, icon: IconProp, pointerDown: undefined | ((e: React.PointerEvent) => void), click: undefined | ((e: PointerEvent) => void), title: string) => ( <Tooltip key={key} title={<div className="dash-tooltip">{title}</div>} placement="top"> - <div className={`documentDecorations-${key}Button`} onContextMenu={e => e.preventDefault()} onPointerDown={pointerDown ?? (e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, clickEv => click!(clickEv)))}> - <FontAwesomeIcon icon={icon as any} /> + <div className={`documentDecorations-${key}Button`} onContextMenu={e => e.preventDefault()} onPointerDown={pointerDown ?? (e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, clickEv => click?.(clickEv)))}> + <FontAwesomeIcon icon={icon} /> </div> </Tooltip> ); @@ -830,11 +844,20 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora <div className="link-button-container" style={{ + top: DocumentView.Selected().length > 1 ? 0 : `${seldocview.showTags ? 4 + seldocview.TagPanelHeight : 4}px`, transform: `translate(${-this._resizeBorderWidth / 2 + 10}px, ${this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `, }}> <DocumentButtonBar views={() => DocumentView.Selected()} /> </div> )} + <div + className="documentDecorations-tagsView" + style={{ + top: `${seldocview.showTags ? 4 + seldocview.TagPanelHeight : 4}px`, + transform: `translate(${-this._resizeBorderWidth / 2 + 10}px, ${this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `, + }}> + {DocumentView.Selected().length > 1 ? <TagsView Views={DocumentView.Selected()} /> : null} + </div> </div> {useRotation && ( |