diff options
author | bobzel <zzzman@gmail.com> | 2023-12-12 14:39:09 -0500 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2023-12-12 14:39:09 -0500 |
commit | 85c09a9e5df77ad00f3e00a2fb1e0f2e3449f97d (patch) | |
tree | 61aa82a95bdd923af1a48c6968aa8a6135f4cf85 /src | |
parent | 77234b8f1dd2cad90cdf94eaefab55de691305c3 (diff) |
cleaned up SelectionManager. fixed schema view
Diffstat (limited to 'src')
33 files changed, 308 insertions, 318 deletions
diff --git a/src/client/util/CaptureManager.tsx b/src/client/util/CaptureManager.tsx index 8a4f37121..271cf7495 100644 --- a/src/client/util/CaptureManager.tsx +++ b/src/client/util/CaptureManager.tsx @@ -81,7 +81,7 @@ export class CaptureManager extends React.Component<{}> { <div className="cancel" onClick={() => { - const selected = SelectionManager.Views().slice(); + const selected = SelectionManager.Views.slice(); SelectionManager.DeselectAll(); selected.map(dv => dv.props.removeDocument?.(dv.props.Document)); this.close(); diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index 0fd7e840c..039bb360e 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -236,7 +236,7 @@ export namespace DictationManager { export const execute = async (phrase: string) => { return UndoManager.RunInBatch(async () => { console.log('PHRASE: ' + phrase); - const targets = SelectionManager.Views(); + const targets = SelectionManager.Views; if (!targets || !targets.length) { return; } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index e96bbcaaf..c711db31a 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -618,7 +618,7 @@ export namespace DragManager { ScriptingGlobals.add(function toggleRaiseOnDrag(readOnly?: boolean) { if (readOnly) { - return SelectionManager.Views().some(dv => dv.Document.keepZWhenDragged); + return SelectionManager.Views.some(dv => dv.Document.keepZWhenDragged); } - SelectionManager.Views().map(dv => (dv.Document.keepZWhenDragged = !dv.Document.keepZWhenDragged)); + SelectionManager.Views.map(dv => (dv.Document.keepZWhenDragged = !dv.Document.keepZWhenDragged)); }); diff --git a/src/client/util/HypothesisUtils.ts b/src/client/util/HypothesisUtils.ts index 151f18d6f..990798ed3 100644 --- a/src/client/util/HypothesisUtils.ts +++ b/src/client/util/HypothesisUtils.ts @@ -27,7 +27,7 @@ export namespace Hypothesis { * Search for a WebDocument whose url field matches the given uri, return undefined if not found */ export const findWebDoc = async (uri: string) => { - const currentDoc = SelectionManager.Docs().lastElement(); + const currentDoc = SelectionManager.Docs.lastElement(); if (currentDoc && Cast(currentDoc.data, WebField)?.url.href === uri) return currentDoc; // always check first whether the currently selected doc is the annotation's source, only use Search otherwise const results: Doc[] = []; diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index b837cdd08..64cced3f1 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -10,90 +10,72 @@ import { LinkManager } from './LinkManager'; import { ScriptingGlobals } from './ScriptingGlobals'; import { UndoManager } from './UndoManager'; -export namespace SelectionManager { - class Manager { - @observable.shallow SelectedViews: DocumentView[] = []; - @observable IsDragging: boolean = false; - @observable SelectedSchemaDocument: Doc | undefined = undefined; - - constructor() { - makeObservable(this); - } - - @action - SelectSchemaViewDoc(doc: Opt<Doc>) { - manager.SelectedSchemaDocument = doc; - } - @action - SelectView(docView: DocumentView, extendSelection: boolean): void { - if (!docView.SELECTED) { - if (!extendSelection) this.DeselectAll(); - manager.SelectedViews.push(docView); - docView.SELECTED = true; - docView._props.whenChildContentsActiveChanged(true); - } - } - @action - DeselectView(docView?: DocumentView): void { - if (docView && manager.SelectedViews.includes(docView)) { - docView.SELECTED = false; - manager.SelectedViews.splice(manager.SelectedViews.indexOf(docView), 1); - docView._props.whenChildContentsActiveChanged(false); - } - } - @action - DeselectAll(): void { - LinkManager.currentLink = undefined; - LinkManager.currentLinkAnchor = undefined; - manager.SelectedSchemaDocument = undefined; - manager.SelectedViews.forEach(dv => { - dv.SELECTED = false; - dv._props.whenChildContentsActiveChanged(false); - }); - manager.SelectedViews.length = 0; - } +export class SelectionManager { + private static _manager: SelectionManager; + private static get Instance() { + return SelectionManager._manager ?? new SelectionManager(); } - const manager = new Manager(); + @observable.shallow SelectedViews: DocumentView[] = []; + @observable IsDragging: boolean = false; + @observable SelectedSchemaDocument: Doc | undefined = undefined; - export function DeselectView(docView?: DocumentView): void { - manager.DeselectView(docView); - } - export function SelectView(docView: DocumentView | undefined, ctrlPressed: boolean): void { - if (!docView) DeselectAll(); - else manager.SelectView(docView, ctrlPressed); - } - export function SelectSchemaViewDoc(document: Opt<Doc>, deselectAllFirst?: boolean): void { - if (deselectAllFirst) manager.DeselectAll(); - manager.SelectSchemaViewDoc(document); + private constructor() { + SelectionManager._manager = this; + makeObservable(this); } - export function IsSelected(doc?: Doc): boolean { - return Array.from(doc?.[DocViews] ?? []).some(dv => dv?.SELECTED); + @action + public static SelectSchemaViewDoc(doc: Opt<Doc>, deselectAllFirst?: boolean) { + if (deselectAllFirst) this.DeselectAll(); + else this.Instance.SelectedSchemaDocument = doc; } - export function DeselectAll(except?: Doc): void { - const found = manager.SelectedViews.find(dv => dv.Document === except); - manager.DeselectAll(); - if (found) manager.SelectView(found, false); + @action + public static SelectView(docView: DocumentView, extendSelection: boolean): void { + if (!docView) this.DeselectAll(); + else if (!docView.SELECTED) { + if (!extendSelection) this.DeselectAll(); + this.Instance.SelectedViews.push(docView); + docView.SELECTED = true; + docView._props.whenChildContentsActiveChanged(true); + } } - export function Views(): Array<DocumentView> { - return manager.SelectedViews; - } - export function SelectedSchemaDoc(): Doc | undefined { - return manager.SelectedSchemaDocument; + @action + public static DeselectView(docView?: DocumentView): void { + if (docView && this.Instance.SelectedViews.includes(docView)) { + docView.SELECTED = false; + this.Instance.SelectedViews.splice(this.Instance.SelectedViews.indexOf(docView), 1); + docView._props.whenChildContentsActiveChanged(false); + } } - export function Docs(): Doc[] { - return manager.SelectedViews.map(dv => dv.Document).filter(doc => doc?._type_collection !== CollectionViewType.Docking); + @action + public static DeselectAll(except?: Doc): void { + const found = this.Instance.SelectedViews.find(dv => dv.Document === except); + LinkManager.currentLink = undefined; + LinkManager.currentLinkAnchor = undefined; + this.Instance.SelectedSchemaDocument = undefined; + this.Instance.SelectedViews.forEach(dv => { + dv.SELECTED = false; + dv._props.whenChildContentsActiveChanged(false); + }); + this.Instance.SelectedViews.length = 0; + if (found) this.SelectView(found, false); } + + public static IsSelected = (doc?: Doc) => Array.from(doc?.[DocViews] ?? []).some(dv => dv?.SELECTED); + public static get Views() { return this.Instance.SelectedViews; } // prettier-ignore + public static get SelectedSchemaDoc() { return this.Instance.SelectedSchemaDocument; } // prettier-ignore + public static get Docs() { return this.Instance.SelectedViews.map(dv => dv.Document).filter(doc => doc?._type_collection !== CollectionViewType.Docking); } // prettier-ignore } + ScriptingGlobals.add(function SelectionManager_selectedDocType(type: string, expertMode: boolean, checkContext?: boolean) { if (Doc.noviceMode && expertMode) return false; if (type === 'tab') { - return SelectionManager.Views().lastElement()?._props.renderDepth === 0; + return SelectionManager.Views.lastElement()?._props.renderDepth === 0; } - let selected = (sel => (checkContext ? DocCast(sel?.embedContainer) : sel))(SelectionManager.SelectedSchemaDoc() ?? SelectionManager.Docs().lastElement()); + let selected = (sel => (checkContext ? DocCast(sel?.embedContainer) : sel))(SelectionManager.SelectedSchemaDoc ?? SelectionManager.Docs.lastElement()); return selected?.type === type || selected?.type_collection === type || !type; }); ScriptingGlobals.add(function deselectAll() { @@ -118,8 +100,8 @@ ScriptingGlobals.add(function redo() { return UndoManager.Redo(); }); ScriptingGlobals.add(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) { - const docs = SelectionManager.Views() - .map(dv => dv.Document) - .filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.KVP && (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null))); + const docs = SelectionManager.Views.map(dv => dv.Document).filter( + d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.KVP && (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null)) + ); return docs.length ? new List(docs) : prevValue; }); diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index a46c6363e..7176b568e 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -162,7 +162,7 @@ export class SharingManager extends React.Component<{}> { const { user, sharingDoc } = recipient; const target = targetDoc || this.targetDoc!; const acl = `acl-${normalizeEmail(user.email)}`; - const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.Document); + const docs = SelectionManager.Views.length < 2 ? [target] : SelectionManager.Views.map(docView => docView.Document); docs.map(doc => (this.layoutDocAcls || doc.dockingConfig ? doc : Doc.GetProto(doc))).forEach(doc => { distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.upgradeNested ? true : undefined); if (permission !== SharingPermissions.None) { @@ -180,7 +180,7 @@ export class SharingManager extends React.Component<{}> { const target = targetDoc || this.targetDoc!; const acl = `acl-${normalizeEmail(StrCast(group.title))}`; - const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.Document); + const docs = SelectionManager.Views.length < 2 ? [target] : SelectionManager.Views.map(docView => docView.Document); docs.map(doc => (this.layoutDocAcls || doc.dockingConfig ? doc : Doc.GetProto(doc))).forEach(doc => { distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.upgradeNested ? true : undefined); @@ -317,7 +317,7 @@ export class SharingManager extends React.Component<{}> { private focusOn = (contents: string) => { const title = this.targetDoc ? StrCast(this.targetDoc.title) : ''; - const docs = SelectionManager.Views().length > 1 ? SelectionManager.Views().map(docView => docView.props.Document) : [this.targetDoc]; + const docs = SelectionManager.Views.length > 1 ? SelectionManager.Views.map(docView => docView.props.Document) : [this.targetDoc]; return ( <span className="focus-span" @@ -444,7 +444,7 @@ export class SharingManager extends React.Component<{}> { const users = this.individualSort === 'ascending' ? this.users.slice().sort(this.sortUsers) : this.individualSort === 'descending' ? this.users.slice().sort(this.sortUsers).reverse() : this.users; const groups = this.groupSort === 'ascending' ? groupList.slice().sort(this.sortGroups) : this.groupSort === 'descending' ? groupList.slice().sort(this.sortGroups).reverse() : groupList; - let docs = SelectionManager.Views().length < 2 ? [this.targetDoc] : SelectionManager.Views().map(docView => docView.Document); + let docs = SelectionManager.Views.length < 2 ? [this.targetDoc] : SelectionManager.Views.map(docView => docView.Document); if (this.myDocAcls) { const newDocs: Doc[] = []; diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts index 44c6aad52..48ec61f85 100644 --- a/src/client/util/SnappingManager.ts +++ b/src/client/util/SnappingManager.ts @@ -2,7 +2,7 @@ import { observable, action, runInAction, reaction, makeObservable } from 'mobx' import { Doc } from '../../fields/Doc'; export class SnappingManager { - static _manager: SnappingManager; + private static _manager: SnappingManager; private static get Instance() { return SnappingManager._manager ?? new SnappingManager(); } @@ -15,7 +15,7 @@ export class SnappingManager { @observable _horizSnapLines: number[] = []; @observable _vertSnapLines: number[] = []; - constructor() { + private constructor() { SnappingManager._manager = this; makeObservable(this); } @@ -26,16 +26,16 @@ export class SnappingManager { this.Instance._vertSnapLines.push(...vertLines); }; - public static get HorizSnapLines() { return SnappingManager.Instance._horizSnapLines; } // prettier-ignore - public static get VertSnapLines() { return SnappingManager.Instance._vertSnapLines; } // prettier-ignore - public static get ShiftKey() { return SnappingManager.Instance._shiftKey; } // prettier-ignore - public static get CtrlKey() { return SnappingManager.Instance._ctrlKey; } // prettier-ignore - public static get IsDragging() { return SnappingManager.Instance._isDragging; } // prettier-ignore - public static get IsResizing() { return SnappingManager.Instance._isResizing; } // prettier-ignore - public static get CanEmbed() { return SnappingManager.Instance._canEmbed; } // prettier-ignore - public static SetShiftKey = (down: boolean) => runInAction(() => (SnappingManager.Instance._shiftKey = down)); - public static SetCtrlKey = (down: boolean) => runInAction(() => (SnappingManager.Instance._ctrlKey = down)); - public static SetIsDragging = (dragging: boolean) => runInAction(() => (SnappingManager.Instance._isDragging = dragging)); - public static SetIsResizing = (doc: Doc | undefined) => runInAction(() => (SnappingManager.Instance._isResizing = doc)); - public static SetCanEmbed = (canEmbed: boolean) => runInAction(() => (SnappingManager.Instance._canEmbed = canEmbed)); + public static get HorizSnapLines() { return this.Instance._horizSnapLines; } // prettier-ignore + public static get VertSnapLines() { return this.Instance._vertSnapLines; } // prettier-ignore + public static get ShiftKey() { return this.Instance._shiftKey; } // prettier-ignore + public static get CtrlKey() { return this.Instance._ctrlKey; } // prettier-ignore + public static get IsDragging() { return this.Instance._isDragging; } // prettier-ignore + public static get IsResizing() { return this.Instance._isResizing; } // prettier-ignore + public static get CanEmbed() { return this.Instance._canEmbed; } // prettier-ignore + public static SetShiftKey = (down: boolean) => runInAction(() => (this.Instance._shiftKey = down)); + public static SetCtrlKey = (down: boolean) => runInAction(() => (this.Instance._ctrlKey = down)); + public static SetIsDragging = (dragging: boolean) => runInAction(() => (this.Instance._isDragging = dragging)); + public static SetIsResizing = (doc: Doc | undefined) => runInAction(() => (this.Instance._isResizing = doc)); + public static SetCanEmbed = (canEmbed: boolean) => runInAction(() => (this.Instance._canEmbed = canEmbed)); } diff --git a/src/client/views/ComponentDecorations.tsx b/src/client/views/ComponentDecorations.tsx index 0a34b283b..ca4e5f2bc 100644 --- a/src/client/views/ComponentDecorations.tsx +++ b/src/client/views/ComponentDecorations.tsx @@ -8,7 +8,7 @@ export class ComponentDecorations extends React.Component<{ boundsTop: number; b static Instance: ComponentDecorations; render() { - const seldoc = SelectionManager.Views().lastElement(); + const seldoc = SelectionManager.Views.lastElement(); return seldoc?.ComponentView?.componentUI?.(this.props.boundsLeft, this.props.boundsTop) ?? null; } } diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 47ec0f1b4..a8ad4150e 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -375,7 +375,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV ); }; return !targetDoc ? null : ( - <Tooltip title={<div className="dash-tooltip">{`Pin Document ${SelectionManager.Views().length > 1 ? 'multiple documents' : ''} to Trail`}</div>}> + <Tooltip title={<div className="dash-tooltip">{`Pin Document ${SelectionManager.Views.length > 1 ? 'multiple documents' : ''} to Trail`}</div>}> <div className="documentButtonBar-icon documentButtonBar-pin" onClick={e => { @@ -526,7 +526,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV } openContextMenu = (e: PointerEvent) => { - let child = SelectionManager.Views()[0].ContentDiv!.children[0]; + let child = SelectionManager.Views[0].ContentDiv!.children[0]; while (child.children.length) { const next = Array.from(child.children).find(c => c.className?.toString().includes('SVGAnimatedString') || typeof c.className === 'string'); if (next?.className?.toString().includes(DocumentView.ROOT_DIV)) break; @@ -606,7 +606,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV Doc.noviceMode ? null : <div className="documentButtonBar-button">{this.templateButton}</div> /*<div className="documentButtonBar-button"> {this.metadataButton} </div> */ } - {!SelectionManager.Views()?.some(v => v.allLinks.length) ? null : <div className="documentButtonBar-button">{this.followLinkButton}</div>} + {!SelectionManager.Views?.some(v => v.allLinks.length) ? null : <div className="documentButtonBar-button">{this.followLinkButton}</div>} <div className="documentButtonBar-button">{this.pinButton}</div> <div className="documentButtonBar-button">{this.recordButton}</div> {!Doc.UserDoc()['documentLinksButton-fullMenu'] ? null : <div className="documentButtonBar-button">{this.shareButton}</div>} diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index b93df36eb..8bcc1cb56 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -77,7 +77,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp 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()?.screenToLocalTransform().Rotate)); + NumCast(SelectionManager.Views.lastElement()?.screenToLocalTransform().Rotate)); (this._showNothing = !(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 ))); @@ -99,7 +99,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp @computed get Bounds() { return (LinkFollower.IsFollowing || DocumentView.ExploreMode) ? { x: 0, y: 0, r: 0, b: 0 } - : SelectionManager.Views() + : SelectionManager.Views .filter(dv => dv._props.renderDepth > 0) .map(dv => dv.getBounds()) .reduce((bounds, rect) => !rect ? bounds @@ -107,7 +107,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp y: Math.min(rect.top, bounds.y), r: Math.max(rect.right, bounds.r), b: Math.max(rect.bottom, bounds.b), - c: SelectionManager.Views().length === 1 ? rect.center : undefined }, + c: SelectionManager.Views.length === 1 ? rect.center : undefined }, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE, c: undefined as { X: number; Y: number } | undefined }); // prettier-ignore } @@ -121,7 +121,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp UndoManager.RunInBatch( () => titleFieldKey && - SelectionManager.Views().forEach(d => { + SelectionManager.Views.forEach(d => { if (titleFieldKey === 'title') { d.dataDoc.title_custom = !this._accumulatedTitle.startsWith('-'); if (StrCast(d.Document.title).startsWith('@') && !this._accumulatedTitle.startsWith('@')) { @@ -165,7 +165,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp }; onContainerDown = (e: React.PointerEvent) => { - const effectiveLayoutAcl = GetEffectiveAcl(SelectionManager.Views()[0].Document); + const effectiveLayoutAcl = GetEffectiveAcl(SelectionManager.Views[0].Document); if (effectiveLayoutAcl == AclAdmin || effectiveLayoutAcl == AclEdit || effectiveLayoutAcl == AclAugment) { setupMoveUpEvents(this, e, e => this.onBackgroundMove(true, e), emptyFunction, emptyFunction); e.stopPropagation(); @@ -173,7 +173,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp }; onTitleDown = (e: React.PointerEvent) => { - const effectiveLayoutAcl = GetEffectiveAcl(SelectionManager.Views()[0].Document); + const effectiveLayoutAcl = GetEffectiveAcl(SelectionManager.Views[0].Document); if (effectiveLayoutAcl == AclAdmin || effectiveLayoutAcl == AclEdit || effectiveLayoutAcl == AclAugment) { setupMoveUpEvents( this, @@ -196,17 +196,17 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp }; @action onBackgroundMove = (dragTitle: boolean, e: PointerEvent): boolean => { - const dragDocView = SelectionManager.Views()[0]; + const dragDocView = SelectionManager.Views[0]; const effectiveLayoutAcl = GetEffectiveAcl(dragDocView.Document); if (effectiveLayoutAcl != AclAdmin && effectiveLayoutAcl != AclEdit && effectiveLayoutAcl != AclAugment) { return false; } const containers = new Set<Doc | undefined>(); - SelectionManager.Views().forEach(v => containers.add(DocCast(v.Document.embedContainer))); + SelectionManager.Views.forEach(v => containers.add(DocCast(v.Document.embedContainer))); if (containers.size > 1) return false; const { left, top } = dragDocView.getBounds() || { left: 0, top: 0 }; const dragData = new DragManager.DocumentDragData( - SelectionManager.Views().map(dv => dv.Document), + SelectionManager.Views.map(dv => dv.Document), dragDocView._props.dropAction ); dragData.offset = dragDocView._props.ScreenToLocalTransform().transformDirection(e.x - left, e.y - top); @@ -216,7 +216,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp dragData.canEmbed = dragTitle; this._hidden = true; DragManager.StartDocumentDrag( - SelectionManager.Views().map(dv => dv.ContentDiv!), + SelectionManager.Views.map(dv => dv.ContentDiv!), dragData, e.x, e.y, @@ -231,7 +231,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp _deleteAfterIconify = false; _iconifyBatch: UndoManager.Batch | undefined; onCloseClick = (forceDeleteOrIconify: boolean | undefined) => { - const views = SelectionManager.Views().filter(v => v && v._props.renderDepth > 0); + const views = SelectionManager.Views.filter(v => v && v._props.renderDepth > 0); if (forceDeleteOrIconify === false && this._iconifyBatch) return; this._deleteAfterIconify = forceDeleteOrIconify || this._iconifyBatch ? true : false; var iconifyingCount = views.length; @@ -264,11 +264,11 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp }; onMaximizeDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, () => DragManager.StartWindowDrag?.(e, [SelectionManager.Views().lastElement().Document]) ?? false, emptyFunction, this.onMaximizeClick, false, false); + setupMoveUpEvents(this, e, () => DragManager.StartWindowDrag?.(e, [SelectionManager.Views.lastElement().Document]) ?? false, emptyFunction, this.onMaximizeClick, false, false); e.stopPropagation(); }; onMaximizeClick = (e: any): void => { - const selectedDocs = SelectionManager.Views(); + const selectedDocs = SelectionManager.Views; if (selectedDocs.length) { if (e.ctrlKey) { // open an embedding in a new tab with Ctrl Key @@ -300,11 +300,11 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp }; onIconifyClick = (): void => { - SelectionManager.Views().forEach(dv => dv?.iconify()); + SelectionManager.Views.forEach(dv => dv?.iconify()); SelectionManager.DeselectAll(); }; - onSelectContainerDocClick = () => SelectionManager.Views()?.[0]?._props.docViewPath?.().lastElement()?.select(false); + onSelectContainerDocClick = () => SelectionManager.Views?.[0]?._props.docViewPath?.().lastElement()?.select(false); /** * sets up events when user clicks on the border radius editor */ @@ -319,7 +319,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp const [x, y] = [this.Bounds.x + 3, this.Bounds.y + 3]; const maxDist = Math.min((this.Bounds.r - this.Bounds.x) / 2, (this.Bounds.b - this.Bounds.y) / 2); const dist = e.clientX < x && e.clientY < y ? 0 : Math.sqrt((e.clientX - x) * (e.clientX - x) + (e.clientY - y) * (e.clientY - y)); - SelectionManager.Docs().map(doc => { + SelectionManager.Docs.map(doc => { const docMax = Math.min(NumCast(doc.width) / 2, NumCast(doc.height) / 2); const radius = Math.min(1, dist / maxDist) * docMax; // set radius based on ratio of drag distance to half diagonal distance of bounding box doc.layout_borderRounding = `${radius}px`; @@ -344,7 +344,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp returnFalse, // don't care about move or up event, emptyFunction, // just care about whether we get a click event e => UndoManager.RunInBatch( - () => SelectionManager.Docs().forEach(doc => + () => SelectionManager.Docs.forEach(doc => doc._pointerEvents = (doc._lockedPosition = !doc._lockedPosition)? 'none' : undefined ), 'toggleBackground' ) // prettier-ignore ); @@ -362,7 +362,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp @action onRotateCenterDown = (e: React.PointerEvent): void => { this._isRotating = true; - const seldocview = SelectionManager.Views()[0]; + const seldocview = SelectionManager.Views[0]; setupMoveUpEvents( this, e, @@ -378,11 +378,11 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp this._isRotating = true; const rcScreen = { X: this.rotCenter[0], Y: this.rotCenter[1] }; const rotateUndo = UndoManager.StartBatch('drag rotation'); - const selectedInk = SelectionManager.Views().filter(i => i.ComponentView instanceof InkingStroke); + const selectedInk = SelectionManager.Views.filter(i => i.ComponentView instanceof InkingStroke); const centerPoint = this.rotCenter.slice(); const infos = new Map<Doc, { unrotatedDocPos: { x: number; y: number }; startRotCtr: { x: number; y: number }; accumRot: number }>(); - const seldocview = SelectionManager.Views()[0]; - SelectionManager.Views().forEach(dv => { + const seldocview = SelectionManager.Views[0]; + SelectionManager.Views.forEach(dv => { const accumRot = (NumCast(dv.Document._rotation) / 180) * Math.PI; const localRotCtr = dv._props.ScreenToLocalTransform().transformPoint(rcScreen.X, rcScreen.Y); const localRotCtrOffset = [localRotCtr[0] - NumCast(dv.Document.width) / 2, localRotCtr[1] - NumCast(dv.Document.height) / 2]; @@ -391,7 +391,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp infos.set(dv.Document, { unrotatedDocPos, startRotCtr, accumRot }); }); const infoRot = (angle: number, isAbs = false) => { - SelectionManager.Views().forEach( + SelectionManager.Views.forEach( action(dv => { const { unrotatedDocPos, startRotCtr, accumRot } = infos.get(dv.Document)!; const endRotCtr = Utils.rotPt(startRotCtr.x, startRotCtr.y, isAbs ? angle : accumRot + angle); @@ -439,7 +439,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp @action onPointerDown = (e: React.PointerEvent): void => { - SnappingManager.SetIsResizing(SelectionManager.Docs().lastElement()); + SnappingManager.SetIsResizing(SelectionManager.Docs.lastElement()); setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction); e.stopPropagation(); DocumentView.Interacting = true; // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them @@ -448,7 +448,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp 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._resizeUndo = UndoManager.StartBatch('drag resizing'); this._snapPt = { x: e.pageX, y: e.pageY }; - SelectionManager.Views().forEach(docView => docView.CollectionFreeFormView?.dragStarting(false, false)); + SelectionManager.Views.forEach(docView => docView.CollectionFreeFormView?.dragStarting(false, false)); }; projectDragToAspect = (e: PointerEvent, docView: DocumentView, fixedAspect: number) => { @@ -466,7 +466,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp return project([e.clientX + this._offset.x, e.clientY + this._offset.y], tl, [tl[0] + fixedAspect, tl[1] + 1]); }; onPointerMove = (e: PointerEvent, down: number[], move: number[]): boolean => { - const first = SelectionManager.Views()[0]; + const first = SelectionManager.Views[0]; const effectiveAcl = GetEffectiveAcl(first.Document); if (!(effectiveAcl == AclAdmin || effectiveAcl == AclEdit || effectiveAcl == AclAugment)) return false; if (!first) return false; @@ -483,10 +483,10 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp !this._interactionLock && runInAction(async () => { // resize selected docs if we're not in the middle of a resize (ie, throttle input events to frame rate) this._interactionLock = true; this._snapPt = thisPt; - e.ctrlKey && (SelectionManager.Views().forEach(docView => !Doc.NativeHeight(docView.Document) && docView.toggleNativeDimensions())); - const fixedAspect = SelectionManager.Docs().some(this.hasFixedAspect); + e.ctrlKey && (SelectionManager.Views.forEach(docView => !Doc.NativeHeight(docView.Document) && docView.toggleNativeDimensions())); + const fixedAspect = SelectionManager.Docs.some(this.hasFixedAspect); const scaleAspect = {x:scale.x === 1 && fixedAspect ? scale.y : scale.x, y: scale.x !== 1 && fixedAspect ? scale.x : scale.y}; - SelectionManager.Views().forEach(docView => + SelectionManager.Views.forEach(docView => this.resizeView(docView, refPt, scaleAspect, { dragHdl, ctrlKey:e.ctrlKey })); // prettier-ignore await new Promise<any>(res => setTimeout(() => res(this._interactionLock = undefined))); }); // prettier-ignore @@ -600,7 +600,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp this._resizeUndo?.end(); // detect layout_autoHeight gesture and apply - SelectionManager.Docs().forEach(doc => NumCast(doc._height) < 20 && (doc._layout_autoHeight = true)); + SelectionManager.Docs.forEach(doc => NumCast(doc._height) < 20 && (doc._layout_autoHeight = true)); //need to change points for resize, or else rotation/control points will fail. this._inkDragDocs .map(oldbds => ({ oldbds, inkPts: Cast(oldbds.doc.data, InkField)?.inkData || [] })) @@ -617,8 +617,8 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp @computed get selectionTitle(): string { - if (SelectionManager.Views().length === 1) { - const selected = SelectionManager.Views()[0]; + 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() || ''; } @@ -627,11 +627,11 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp } return this._accumulatedTitle; } - return SelectionManager.Views().length > 1 ? '-multiple-' : '-unset-'; + return SelectionManager.Views.length > 1 ? '-multiple-' : '-unset-'; } @computed get rotCenter() { - const lastView = SelectionManager.Views().lastElement(); + const lastView = SelectionManager.Views.lastElement(); if (lastView) { const invXf = lastView._props.ScreenToLocalTransform().inverse(); const seldoc = lastView.layoutDoc; @@ -643,7 +643,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp render() { const { b, r, x, y } = this.Bounds; - const seldocview = SelectionManager.Views().lastElement(); + const seldocview = SelectionManager.Views.lastElement(); if (SnappingManager.IsDragging || r - x < 1 || x === Number.MAX_VALUE || !seldocview || this._hidden || isNaN(r) || isNaN(b) || isNaN(x) || isNaN(y)) { setTimeout(action(() => (this._showNothing = true))); return null; @@ -667,7 +667,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp hideDecorations || seldocview._props.hideOpenButton || seldocview.Document.layout_hideOpenButton || - SelectionManager.Views().some(docView => docView.Document._dragOnlyWithinContainer || docView.Document.isGroup || docView.Document.layout_hideOpenButton) || + SelectionManager.Views.some(docView => docView.Document._dragOnlyWithinContainer || docView.Document.isGroup || docView.Document.layout_hideOpenButton) || this._isRounding || this._isRotating; const hideDeleteButton = @@ -677,7 +677,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp this._isRotating || seldocview._props.hideDeleteButton || seldocview.Document.hideDeleteButton || - SelectionManager.Views().some(docView => { + SelectionManager.Views.some(docView => { const collectionAcl = docView._props.docViewPath()?.lastElement() ? GetEffectiveAcl(docView._props.docViewPath().lastElement().dataDoc) : AclEdit; return collectionAcl !== AclAdmin && collectionAcl !== AclEdit && GetEffectiveAcl(docView.Document) !== AclAdmin; }); @@ -692,7 +692,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp const bounds = this.ClippedBounds; const useLock = bounds.r - bounds.x > 135 && seldocview.CollectionFreeFormDocumentView; const useRotation = !hideResizers && seldocview.Document.type !== DocumentType.EQUATION && seldocview.CollectionFreeFormDocumentView; // when do we want an object to not rotate? - const rotation = SelectionManager.Views().length == 1 ? seldocview.screenToLocalTransform().inverse().RotateDeg : 0; + const rotation = SelectionManager.Views.length == 1 ? seldocview.screenToLocalTransform().inverse().RotateDeg : 0; // Radius constants const useRounding = seldocview.ComponentView instanceof ImageBox || seldocview.ComponentView instanceof FormattedTextBox || seldocview.ComponentView instanceof CollectionFreeFormView; @@ -754,7 +754,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp ); const centery = hideTitle ? 0 : this._titleHeight; const transformOrigin = `${50}% calc(50% + ${centery / 2}px)`; - const freeformDoc = SelectionManager.Views().some(v => v.CollectionFreeFormDocumentView); + const freeformDoc = SelectionManager.Views.some(v => v.CollectionFreeFormDocumentView); return ( <div className="documentDecorations" style={{ display: this._showNothing && !freeformDoc ? 'none' : undefined }}> <div @@ -767,7 +767,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp transformOrigin, background: SnappingManager.ShiftKey ? undefined : 'yellow', pointerEvents: SnappingManager.ShiftKey || DocumentView.Interacting ? 'none' : 'all', - display: SelectionManager.Views().length <= 1 || hideDecorations ? 'none' : undefined, + display: SelectionManager.Views.length <= 1 || hideDecorations ? 'none' : undefined, transform: `rotate(${rotation}deg)`, }} onPointerDown={this.onBackgroundDown} @@ -824,7 +824,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp style={{ transform: `translate(${-this._resizeBorderWidth / 2 + 10}px, ${this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `, }}> - <DocumentButtonBar views={SelectionManager.Views} /> + <DocumentButtonBar views={() => SelectionManager.Views} /> </div> )} </div> diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 174f7951d..4015fb321 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -90,8 +90,8 @@ export class KeyManager { }); nudge = (x: number, y: number, label: string) => { - const nudgeable = SelectionManager.Views().some(dv => dv.CollectionFreeFormDocumentView?.nudge); - nudgeable && UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.CollectionFreeFormDocumentView?.nudge(x, y)), label); + const nudgeable = SelectionManager.Views.some(dv => dv.CollectionFreeFormDocumentView?.nudge); + nudgeable && UndoManager.RunInBatch(() => SelectionManager.Views.map(dv => dv.CollectionFreeFormDocumentView?.nudge(x, y)), label); return { stopPropagation: nudgeable, preventDefault: nudgeable }; }; @@ -99,18 +99,18 @@ export class KeyManager { switch (keyname) { case 'u': if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') { - const ungroupings = SelectionManager.Views(); + const ungroupings = SelectionManager.Views; UndoManager.RunInBatch(() => ungroupings.map(dv => (dv.layoutDoc.group = undefined)), 'ungroup'); SelectionManager.DeselectAll(); } break; case 'g': if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') { - const selected = SelectionManager.Views(); + const selected = SelectionManager.Views; const collectionView = selected.reduce((col, dv) => (col === null || dv.CollectionFreeFormView === col ? dv.CollectionFreeFormView : undefined), null as null | undefined | CollectionFreeFormView); if (collectionView) { UndoManager.RunInBatch(() => - collectionView._marqueeViewRef.current?.collection(e, true, SelectionManager.Docs()) + collectionView._marqueeViewRef.current?.collection(e, true, SelectionManager.Docs) , 'grouping'); break; } @@ -182,14 +182,14 @@ export class KeyManager { case 'arrowdown': return this.nudge(0, 10, 'nudge down'); case 'u' : if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') { - UndoManager.RunInBatch(() => SelectionManager.Docs().forEach(doc => (doc.group = undefined)), 'unggroup'); + UndoManager.RunInBatch(() => SelectionManager.Docs.forEach(doc => (doc.group = undefined)), 'unggroup'); SelectionManager.DeselectAll(); } break; case 'g': if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') { const randomGroup = random(0, 1000); - UndoManager.RunInBatch(() => SelectionManager.Docs().forEach(doc => (doc.group = randomGroup)), 'group'); + UndoManager.RunInBatch(() => SelectionManager.Docs.forEach(doc => (doc.group = randomGroup)), 'group'); SelectionManager.DeselectAll(); } break; @@ -208,7 +208,7 @@ export class KeyManager { switch (keyname) { case 'Æ’': case 'f': - const dv = SelectionManager.Views()?.[0]; + const dv = SelectionManager.Views?.[0]; UndoManager.RunInBatch(() => dv.CollectionFreeFormDocumentView?.float(), 'float'); } @@ -256,8 +256,8 @@ export class KeyManager { } break; case 'f': - if (SelectionManager.Views().length === 1 && SelectionManager.Views()[0].ComponentView?.search) { - SelectionManager.Views()[0].ComponentView?.search?.('', false, false); + if (SelectionManager.Views.length === 1 && SelectionManager.Views[0].ComponentView?.search) { + SelectionManager.Views[0].ComponentView?.search?.('', false, false); } else { const searchBtn = DocListCast(Doc.MyLeftSidebarMenu.data).find(d => d.target === Doc.MySearcher); if (searchBtn) { @@ -299,17 +299,11 @@ export class KeyManager { preventDefault = false; break; case 'x': - if (SelectionManager.Views().length) { + if (SelectionManager.Views.length) { const bds = DocumentDecorations.Instance.Bounds; - const pt = SelectionManager.Views()[0] - .props.ScreenToLocalTransform() - .transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2); - const text = - `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` + - SelectionManager.Views() - .map(dv => dv.Document[Id]) - .join(':'); - SelectionManager.Views().length && navigator.clipboard.writeText(text); + const pt = SelectionManager.Views[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2); + const text = `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.Views.map(dv => dv.Document[Id]).join(':'); + SelectionManager.Views.length && navigator.clipboard.writeText(text); DocumentDecorations.Instance.onCloseClick(true); stopPropagation = false; preventDefault = false; @@ -318,15 +312,9 @@ export class KeyManager { case 'c': if ((document.activeElement as any)?.type !== 'text' && !AnchorMenu.Instance.Active && DocumentDecorations.Instance.Bounds.r - DocumentDecorations.Instance.Bounds.x > 2) { const bds = DocumentDecorations.Instance.Bounds; - const pt = SelectionManager.Views()[0] - .props.ScreenToLocalTransform() - .transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2); - const text = - `__DashCloneId(${pt?.[0] || 0},${pt?.[1] || 0}):` + - SelectionManager.Views() - .map(dv => dv.Document[Id]) - .join(':'); - SelectionManager.Views().length && navigator.clipboard.writeText(text); + const pt = SelectionManager.Views[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2); + const text = `__DashCloneId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.Views.map(dv => dv.Document[Id]).join(':'); + SelectionManager.Views.length && navigator.clipboard.writeText(text); stopPropagation = false; } preventDefault = false; @@ -344,7 +332,7 @@ export class KeyManager { if (!plain) return; const clone = plain.startsWith('__DashCloneId('); const docids = plain.split(':'); // hack! docids[0] is the top left of the selection rectangle - const addDocument = SelectionManager.Views().lastElement()?.ComponentView?.addDocument; + const addDocument = SelectionManager.Views.lastElement()?.ComponentView?.addDocument; if (addDocument && (plain.startsWith('__DashDocId(') || clone)) { Doc.Paste(docids.slice(1), clone, addDocument); } diff --git a/src/client/views/InkControlPtHandles.tsx b/src/client/views/InkControlPtHandles.tsx index b835a3798..a5c2d99d2 100644 --- a/src/client/views/InkControlPtHandles.tsx +++ b/src/client/views/InkControlPtHandles.tsx @@ -208,8 +208,8 @@ export class InkEndPtHandles extends React.Component<InkEndProps> { const v1n = { X: v1.X / v1len, Y: v1.Y / v1len }; const v2n = { X: v2.X / v2len, Y: v2.Y / v2len }; const angle = Math.acos(v1n.X * v2n.X + v1n.Y * v2n.Y) * Math.sign(v1.X * v2.Y - v2.X * v1.Y); - InkStrokeProperties.Instance.stretchInk(SelectionManager.Views(), scaling, p2, v1n, e.shiftKey); - InkStrokeProperties.Instance.rotateInk(SelectionManager.Views(), angle, pt2()); // bcz: call pt2() func here because pt2 will have changed from previous stretchInk call + InkStrokeProperties.Instance.stretchInk(SelectionManager.Views, scaling, p2, v1n, e.shiftKey); + InkStrokeProperties.Instance.rotateInk(SelectionManager.Views, angle, pt2()); // bcz: call pt2() func here because pt2 will have changed from previous stretchInk call return false; }), action(() => { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 73a6b687a..4f96b9234 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -145,7 +145,7 @@ export class MainView extends React.Component { componentDidMount() { reaction( // when a multi-selection occurs, remove focus from all active elements to allow keyboad input to go only to global key manager to act upon selection - () => SelectionManager.Views().slice(), + () => SelectionManager.Views.slice(), views => views.length > 1 && (document.activeElement as any)?.blur !== undefined && (document.activeElement as any)!.blur() ); const scriptTag = document.createElement('script'); @@ -924,9 +924,7 @@ export class MainView extends React.Component { ); } @computed get snapLines() { - SnappingManager.IsDragging; - SnappingManager.IsResizing; - const dragged = DragManager.docsBeingDragged.lastElement() ?? SelectionManager.Docs().lastElement(); + const dragged = DragManager.docsBeingDragged.lastElement() ?? SelectionManager.Docs.lastElement(); const dragPar = dragged ? DocumentManager.Instance.getDocumentView(dragged)?.CollectionFreeFormView : undefined; return !dragPar?.layoutDoc.freeform_snapLines ? null : ( <div className="mainView-snapLines"> diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 7824ad1c8..8540e81e1 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -40,13 +40,13 @@ export class PropertiesButtons extends React.Component<{}, {}> { @observable public static Instance: PropertiesButtons; @computed get selectedDoc() { - return SelectionManager.SelectedSchemaDoc() || SelectionManager.Views().lastElement()?.Document; + return SelectionManager.SelectedSchemaDoc || SelectionManager.Views.lastElement()?.Document; } @computed get selectedLayoutDoc() { - return SelectionManager.SelectedSchemaDoc() || SelectionManager.Views().lastElement()?.layoutDoc; + return SelectionManager.SelectedSchemaDoc || SelectionManager.Views.lastElement()?.layoutDoc; } @computed get selectedTabView() { - return !SelectionManager.SelectedSchemaDoc() && SelectionManager.Views().lastElement()?.topMost; + return !SelectionManager.SelectedSchemaDoc && SelectionManager.Views.lastElement()?.topMost; } propertyToggleBtn = (label: (on?: any) => string, property: string, tooltip: (on?: any) => string, icon: (on?: any) => any, onClick?: (dv: Opt<DocumentView>, doc: Doc, property: string) => void, useUserDoc?: boolean) => { @@ -64,8 +64,8 @@ export class PropertiesButtons extends React.Component<{}, {}> { fillWidth={true} toggleType={ToggleType.BUTTON} onClick={undoable(() => { - if (SelectionManager.Views().length > 1) { - SelectionManager.Views().forEach(dv => (onClick ?? onPropToggle)(dv, dv.Document, property)); + if (SelectionManager.Views.length > 1) { + SelectionManager.Views.forEach(dv => (onClick ?? onPropToggle)(dv, dv.Document, property)); } else if (targetDoc) (onClick ?? onPropToggle)(undefined, targetDoc, property); }, property)} /> @@ -82,7 +82,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { on => `${on ? 'Set' : 'Remove'} lightbox flag`, on => 'window-restore', onClick => { - SelectionManager.Views().forEach(dv => { + SelectionManager.Views.forEach(dv => { const containerDoc = dv.Document; //containerDoc.followAllLinks = // containerDoc.noShadow = @@ -200,7 +200,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { // on => `${on ? 'Set' : 'Remove'} lightbox flag`, // on => 'window-restore', // onClick => { - // SelectionManager.Views().forEach(dv => { + // SelectionManager.Views.forEach(dv => { // const containerDoc = dv.Document; // //containerDoc.followAllLinks = // // containerDoc.noShadow = @@ -352,8 +352,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @undoBatch handlePerspectiveChange = (e: any) => { this.selectedDoc && (this.selectedDoc._type_collection = e.target.value); - SelectionManager.Views() - .filter(dv => dv.docView) + SelectionManager.Views.filter(dv => dv.docView) .map(dv => dv.docView!) .forEach(docView => (docView.layoutDoc._type_collection = e.target.value)); }; @@ -416,8 +415,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @undoBatch @action handleOptionChange = (onClick: string) => { - SelectionManager.Views() - .filter(dv => dv.docView) + SelectionManager.Views.filter(dv => dv.docView) .map(dv => dv.docView!) .forEach(docView => { const linkButton = IsFollowLinkScript(docView.props.Document.onClick); @@ -443,7 +441,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @undoBatch editOnClickScript = () => { - if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => DocUtils.makeCustomViewClicked(dv.Document, undefined, 'onClick')); + if (SelectionManager.Views.length) SelectionManager.Views.forEach(dv => DocUtils.makeCustomViewClicked(dv.Document, undefined, 'onClick')); else this.selectedDoc && DocUtils.makeCustomViewClicked(this.selectedDoc, undefined, 'onClick'); }; diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx index b1e99c3f5..58d3b72e8 100644 --- a/src/client/views/PropertiesDocBacklinksSelector.tsx +++ b/src/client/views/PropertiesDocBacklinksSelector.tsx @@ -34,10 +34,10 @@ export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDo }); render() { - return !SelectionManager.Views().length ? null : ( + return !SelectionManager.Views.length ? null : ( <div className="propertiesDocBacklinksSelector" style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}> {this.props.hideTitle ? null : <p key="contexts">Contexts:</p>} - <LinkMenu docView={SelectionManager.Views().lastElement()} clearLinkEditor={undefined} itemHandler={this.getOnClick} style={{ left: 0, top: 0 }} /> + <LinkMenu docView={SelectionManager.Views.lastElement()} clearLinkEditor={undefined} itemHandler={this.getOnClick} style={{ left: 0, top: 0 }} /> </div> ); } diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index b4c591b89..442d09739 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -67,14 +67,14 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } @computed get selectedDoc() { - return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.Document || Doc.ActiveDashboard; + return SelectionManager.SelectedSchemaDoc || this.selectedDocumentView?.Document || Doc.ActiveDashboard; } @computed get selectedLayoutDoc() { - return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.layoutDoc || Doc.ActiveDashboard; + return SelectionManager.SelectedSchemaDoc || this.selectedDocumentView?.layoutDoc || Doc.ActiveDashboard; } @computed get selectedDocumentView() { - if (SelectionManager.Views().length) return SelectionManager.Views()[0]; + if (SelectionManager.Views.length) return SelectionManager.Views[0]; if (PresBox.Instance?.selectedArray.size) return DocumentManager.Instance.getDocumentView(PresBox.Instance.Document); return undefined; } @@ -177,7 +177,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const rows: JSX.Element[] = []; if (this.dataDoc && this.selectedDoc) { const ids = new Set<string>(reqdKeys); - const docs: Doc[] = SelectionManager.Views().length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc)); + const docs: Doc[] = SelectionManager.Views.length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views.map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc)); docs.forEach(doc => Object.keys(doc).forEach(key => doc[key] !== ComputedField.undefined && ids.add(key))); // prettier-ignore @@ -226,7 +226,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { @undoBatch setKeyValue = (value: string) => { - const docs = SelectionManager.Views().length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc!] : SelectionManager.Views().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc)); + const docs = SelectionManager.Views.length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc!] : SelectionManager.Views.map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc)); docs.forEach(doc => { if (value.indexOf(':') !== -1) { const newVal = value[0].toUpperCase() + value.substring(1, value.length); @@ -290,7 +290,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } @computed get layoutPreview() { - if (SelectionManager.Views().length > 1) { + if (SelectionManager.Views.length > 1) { return '-- multiple selected --'; } if (this.selectedDoc) { @@ -339,7 +339,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { */ @undoBatch changePermissions = (e: any, user: string) => { - const docs = SelectionManager.Views().length < 2 ? [this.selectedDoc] : SelectionManager.Views().map(dv => (this.layoutDocAcls ? dv.layoutDoc : dv.dataDoc)); + const docs = SelectionManager.Views.length < 2 ? [this.selectedDoc] : SelectionManager.Views.map(dv => (this.layoutDocAcls ? dv.layoutDoc : dv.dataDoc)); SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, docs, this.layoutDocAcls); }; @@ -457,7 +457,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { */ @computed get sharingTable() { // all selected docs - const docs = SelectionManager.Views().length < 2 && this.selectedDoc ? [this.selectedDoc] : SelectionManager.Views().map(docView => docView.Document); + const docs = SelectionManager.Views.length < 2 && this.selectedDoc ? [this.selectedDoc] : SelectionManager.Views.map(docView => docView.Document); const target = docs[0]; const showAdmin = GetEffectiveAcl(target) == AclAdmin; @@ -573,7 +573,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { @computed get editableTitle() { const titles = new Set<string>(); - SelectionManager.Views().forEach(dv => titles.add(StrCast(dv.Document.title))); + SelectionManager.Views.forEach(dv => titles.add(StrCast(dv.Document.title))); const title = Array.from(titles.keys()).length > 1 ? '--multiple selected--' : StrCast(this.selectedDoc?.title); return ( <div> @@ -628,8 +628,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { @undoBatch setTitle = (value: string | number) => { - if (SelectionManager.Views().length > 1) { - SelectionManager.Views().map(dv => Doc.SetInPlace(dv.Document, 'title', value, true)); + if (SelectionManager.Views.length > 1) { + SelectionManager.Views.map(dv => Doc.SetInPlace(dv.Document, 'title', value, true)); } else if (this.dataDoc) { if (this.selectedDoc) Doc.SetInPlace(this.selectedDoc, 'title', value, true); else KeyValueBox.SetField(this.dataDoc, 'title', value as string, true); diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index f8e80ed87..08fcd544e 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -49,7 +49,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> { componentDidMount() { reaction( - () => SelectionManager.Views().lastElement(), + () => SelectionManager.Views.lastElement(), view => view && this.SetSelection(view) ); } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index a74c6858c..79b15fdb1 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -344,7 +344,7 @@ export function CollectionSubView<X>(moreProps?: X) { } }); } else { - const srcWeb = SelectionManager.Views().lastElement(); + const srcWeb = SelectionManager.Views.lastElement(); const srcUrl = (srcWeb?.Document.data as WebField)?.url?.href?.match(/https?:\/\/[^/]*/)?.[0]; const reg = new RegExp(Utils.prepend(''), 'g'); const modHtml = srcUrl ? html.replace(reg, srcUrl) : html; @@ -353,7 +353,7 @@ export function CollectionSubView<X>(moreProps?: X) { Doc.GetProto(htmlDoc)['data-text'] = Doc.GetProto(htmlDoc).text = text; addDocument(htmlDoc); if (srcWeb) { - const iframe = SelectionManager.Views()[0].ContentDiv?.getElementsByTagName('iframe')?.[0]; + const iframe = SelectionManager.Views[0].ContentDiv?.getElementsByTagName('iframe')?.[0]; const focusNode = iframe?.contentDocument?.getSelection()?.focusNode as any; if (focusNode) { const anchor = srcWeb?.ComponentView?.getAnchor?.(true); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 917241c5f..658d60523 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -168,7 +168,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree const targetDataDoc = this.Document[DocData]; const value = DocListCast(targetDataDoc[this._props.fieldKey]); const result = value.filter(v => !docs.includes(v)); - if ((doc instanceof Doc ? [doc] : doc).some(doc => SelectionManager.Views().some(dv => Doc.AreProtosEqual(dv.Document, doc)))) SelectionManager.DeselectAll(); + if ((doc instanceof Doc ? [doc] : doc).some(doc => SelectionManager.Views.some(dv => Doc.AreProtosEqual(dv.Document, doc)))) SelectionManager.DeselectAll(); if (result.length !== value.length && doc instanceof Doc) { const ind = DocListCast(targetDataDoc[this._props.fieldKey]).indexOf(doc); const prev = ind && DocListCast(targetDataDoc[this._props.fieldKey])[ind - 1]; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index ec31f77b2..aa40fb809 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1961,18 +1961,18 @@ export function CollectionBrowseClick(dv: DocumentView, clientX: number, clientY } ScriptingGlobals.add(CollectionBrowseClick); ScriptingGlobals.add(function nextKeyFrame(readOnly: boolean) { - !readOnly && (SelectionManager.Views()[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame(); + !readOnly && (SelectionManager.Views[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame(); }); ScriptingGlobals.add(function prevKeyFrame(readOnly: boolean) { - !readOnly && (SelectionManager.Views()[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame(true); + !readOnly && (SelectionManager.Views[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame(true); }); ScriptingGlobals.add(function curKeyFrame(readOnly: boolean) { - const selView = SelectionManager.Views(); + const selView = SelectionManager.Views; if (readOnly) return selView[0].ComponentView?.getKeyFrameEditing?.() ? Colors.MEDIUM_BLUE : 'transparent'; runInAction(() => selView[0].ComponentView?.setKeyFrameEditing?.(!selView[0].ComponentView?.getKeyFrameEditing?.())); }); ScriptingGlobals.add(function pinWithView(pinContent: boolean) { - SelectionManager.Views().forEach(view => + SelectionManager.Views.forEach(view => view.props.pinToPres(view.Document, { currentFrame: Cast(view.Document.currentFrame, 'number', null), pinData: { @@ -1984,8 +1984,8 @@ ScriptingGlobals.add(function pinWithView(pinContent: boolean) { ); }); ScriptingGlobals.add(function bringToFront() { - SelectionManager.Views().forEach(view => view.CollectionFreeFormView?.bringToFront(view.Document)); + SelectionManager.Views.forEach(view => view.CollectionFreeFormView?.bringToFront(view.Document)); }); ScriptingGlobals.add(function sendToBack(doc: Doc) { - SelectionManager.Views().forEach(view => view.CollectionFreeFormView?.bringToFront(view.Document, true)); + SelectionManager.Views.forEach(view => view.CollectionFreeFormView?.bringToFront(view.Document, true)); }); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 9f316bef3..10beb120a 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -176,7 +176,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque this.pasteTable(ns, x, y); })(); e.stopPropagation(); - } else if (!e.ctrlKey && !e.metaKey && SelectionManager.Views().length < 2) { + } else if (!e.ctrlKey && !e.metaKey && SelectionManager.Views.length < 2) { 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, this._props.xPadding === 0)); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 9a00595f9..276415d56 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -1,13 +1,13 @@ import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, observable, ObservableMap, observe } from 'mobx'; +import { action, computed, makeObservable, observable, ObservableMap, observe, override } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, DocListCast, Field, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; import { listSpec } from '../../../../fields/Schema'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils'; +import { copyProps, emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils'; import { Docs, DocumentOptions, DocUtils, FInfo } from '../../../documents/Documents'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; @@ -19,7 +19,7 @@ import { Colors } from '../../global/globalEnums'; import { DocFocusOptions, DocumentView, DocumentViewProps } from '../../nodes/DocumentView'; import { KeyValueBox } from '../../nodes/KeyValueBox'; import { DefaultStyleProvider, StyleProp } from '../../StyleProvider'; -import { CollectionSubView } from '../CollectionSubView'; +import { CollectionSubView, SubCollectionViewProps } from '../CollectionSubView'; import './CollectionSchemaView.scss'; import { SchemaColumnHeader } from './SchemaColumnHeader'; import { SchemaRowBox } from './SchemaRowBox'; @@ -79,15 +79,27 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _filterSearchValue: string = ''; @observable _selectedCell: [Doc, number] | undefined = undefined; + _prevProps: SubCollectionViewProps; + @override _props: SubCollectionViewProps; + constructor(props: SubCollectionViewProps) { + super(props); + this._props = this._prevProps = props; + makeObservable(this); + } + + componentDidUpdate() { + copyProps(this); + } + // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { return this._menuTarget.current; } @computed get _selectedDocs() { - const selected = SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.Document)); + const selected = SelectionManager.Docs.filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.Document)); if (!selected.length) { - for (const sel of SelectionManager.Docs()) { + for (const sel of SelectionManager.Docs) { const contextPath = DocumentManager.GetContextPath(sel, true); if (contextPath.includes(this.Document)) { const parentInd = contextPath.indexOf(this.Document); @@ -107,7 +119,7 @@ export class CollectionSchemaView extends CollectionSubView() { } @computed get tableWidth() { - return this.props.PanelWidth() - this.previewWidth - (this.previewWidth === 0 ? 0 : CollectionSchemaView._previewDividerWidth); + return this._props.PanelWidth() - this.previewWidth - (this.previewWidth === 0 ? 0 : CollectionSchemaView._previewDividerWidth); } @computed get columnKeys() { @@ -139,9 +151,8 @@ export class CollectionSchemaView extends CollectionSubView() { return BoolCast(this.layoutDoc.sortDesc); } - @action componentDidMount() { - this.props.setContentView?.(this); + this._props.setContentView?.(this); document.addEventListener('keydown', this.onKeyDown); Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => this.fieldInfos.set(pair[0], pair[1])); @@ -239,7 +250,6 @@ export class CollectionSchemaView extends CollectionSubView() { }; @undoBatch - @action setColumnSort = (field: string | undefined, desc: boolean = false) => { this.layoutDoc.sortField = field; this.layoutDoc.sortDesc = desc; @@ -248,7 +258,6 @@ export class CollectionSchemaView extends CollectionSubView() { addRow = (doc: Doc | Doc[]) => this.addDocument(doc); @undoBatch - @action changeColumnKey = (index: number, newKey: string, defaultVal?: any) => { if (!this.documentKeys.includes(newKey)) { this.addNewKey(newKey, defaultVal); @@ -260,7 +269,6 @@ export class CollectionSchemaView extends CollectionSubView() { }; @undoBatch - @action addColumn = (key: string, defaultVal?: any) => { if (!this.documentKeys.includes(key)) { this.addNewKey(key, defaultVal); @@ -281,7 +289,6 @@ export class CollectionSchemaView extends CollectionSubView() { addNewKey = (key: string, defaultVal: any) => this.childDocs.forEach(doc => (doc[key] = defaultVal)); @undoBatch - @action removeColumn = (index: number) => { if (this.columnKeys.length === 1) return; const currWidths = this.storedColumnWidths.slice(); @@ -320,8 +327,8 @@ export class CollectionSchemaView extends CollectionSubView() { change = this._displayColumnWidths[shrinking] - CollectionSchemaView._minColWidth; } - this._displayColumnWidths[shrinking] -= change * this.props.ScreenToLocalTransform().Scale; - this._displayColumnWidths[growing] += change * this.props.ScreenToLocalTransform().Scale; + this._displayColumnWidths[shrinking] -= change * this._props.ScreenToLocalTransform().Scale; + this._displayColumnWidths[growing] += change * this._props.ScreenToLocalTransform().Scale; return false; } @@ -335,7 +342,6 @@ export class CollectionSchemaView extends CollectionSubView() { }; @undoBatch - @action moveColumn = (fromIndex: number, toIndex: number) => { let currKeys = this.columnKeys.slice(); currKeys.splice(toIndex, 0, currKeys.splice(fromIndex, 1)[0]); @@ -379,7 +385,7 @@ export class CollectionSchemaView extends CollectionSubView() { @action highlightDropColumn = (e: PointerEvent) => { e.stopPropagation(); - const mouseX = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0]; + const mouseX = this._props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0]; const index = this.findDropIndex(mouseX); this._colEles.forEach((colRef, i) => { let leftStyle = ''; @@ -439,7 +445,7 @@ export class CollectionSchemaView extends CollectionSubView() { onInternalDrop = (e: Event, de: DragManager.DropEvent) => { if (de.complete.columnDragData) { - const mouseX = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y)[0]; + const mouseX = this._props.ScreenToLocalTransform().transformPoint(de.x, de.y)[0]; const index = this.findDropIndex(mouseX); this.moveColumn(de.complete.columnDragData.colIndex, index ?? de.complete.columnDragData.colIndex); @@ -483,7 +489,7 @@ export class CollectionSchemaView extends CollectionSubView() { const nativeWidth = this._previewRef!.getBoundingClientRect(); const minWidth = 40; const maxWidth = 1000; - const movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]; + const movedWidth = this._props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]; const width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth; this.layoutDoc.schema_previewWidth = width; return false; @@ -507,8 +513,8 @@ export class CollectionSchemaView extends CollectionSubView() { const found = this._tableContentRef && Array.from(this._tableContentRef.getElementsByClassName('documentView-node')).find((node: any) => node.id === doc[Id]); if (found) { const rect = found.getBoundingClientRect(); - const localRect = this.props.ScreenToLocalTransform().transformBounds(rect.left, rect.top, rect.width, rect.height); - if (localRect.y < this.rowHeightFunc() || localRect.y + localRect.height > this.props.PanelHeight()) { + const localRect = this._props.ScreenToLocalTransform().transformBounds(rect.left, rect.top, rect.width, rect.height); + if (localRect.y < this.rowHeightFunc() || localRect.y + localRect.height > this._props.PanelHeight()) { let focusSpeed = options.zoomTime ?? 50; smoothScroll(focusSpeed, this._tableContentRef!, localRect.y + this._tableContentRef!.scrollTop - this.rowHeightFunc(), options.easeFunc); return focusSpeed; @@ -755,7 +761,7 @@ export class CollectionSchemaView extends CollectionSubView() { @computed get renderFilterOptions() { const keyOptions: string[] = []; const columnKey = this.columnKeys[this._filterColumnIndex!]; - const allDocs = DocListCast(this.dataDoc[this.props.fieldKey]); + const allDocs = DocListCast(this.dataDoc[this._props.fieldKey]); allDocs.forEach(doc => { const value = StrCast(doc[columnKey]); if (!keyOptions.includes(value) && value !== '' && (this._filterSearchValue === '' || value.includes(this._filterSearchValue))) { @@ -779,9 +785,9 @@ export class CollectionSchemaView extends CollectionSubView() { onClick={e => e.stopPropagation()} onChange={action(e => { if (e.target.checked) { - Doc.setDocFilter(this.props.Document, columnKey, key, 'check'); + Doc.setDocFilter(this.Document, columnKey, key, 'check'); } else { - Doc.setDocFilter(this.props.Document, columnKey, key, 'remove'); + Doc.setDocFilter(this.Document, columnKey, key, 'remove'); } })} checked={bool} @@ -828,8 +834,8 @@ export class CollectionSchemaView extends CollectionSubView() { } rowHeightFunc = () => (BoolCast(this.layoutDoc._schema_singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight); sortedDocsFunc = () => this.sortedDocs; - isContentActive = () => this.props.isSelected() || this.props.isContentActive(); - screenToLocal = () => this.props.ScreenToLocalTransform().translate(-this.tableWidth, 0); + isContentActive = () => this._props.isSelected() || this._props.isContentActive(); + screenToLocal = () => this._props.ScreenToLocalTransform().translate(-this.tableWidth, 0); previewWidthFunc = () => this.previewWidth; render() { return ( @@ -838,7 +844,7 @@ export class CollectionSchemaView extends CollectionSubView() { <div className="schema-table" style={{ width: `calc(100% - ${this.previewWidth}px)` }} - onWheel={e => this.props.isContentActive() && e.stopPropagation()} + onWheel={e => this._props.isContentActive() && e.stopPropagation()} ref={r => { // prevent wheel events from passively propagating up through containers r?.addEventListener('wheel', (e: WheelEvent) => {}, { passive: false }); @@ -864,7 +870,7 @@ export class CollectionSchemaView extends CollectionSubView() { openContextMenu={this.openContextMenu} dragColumn={this.dragColumn} setColRef={this.setColRef} - isContentActive={this.props.isContentActive} + isContentActive={this._props.isContentActive} /> ))} </div> @@ -895,10 +901,10 @@ export class CollectionSchemaView extends CollectionSubView() { onClickScriptDisable="always" focus={emptyFunction} defaultDoubleClick={returnIgnore} - renderDepth={this.props.renderDepth + 1} + renderDepth={this._props.renderDepth + 1} rootSelected={this.rootSelected} PanelWidth={this.previewWidthFunc} - PanelHeight={this.props.PanelHeight} + PanelHeight={this._props.PanelHeight} isContentActive={returnTrue} isDocumentActive={returnFalse} ScreenToLocalTransform={this.screenToLocal} @@ -907,12 +913,12 @@ export class CollectionSchemaView extends CollectionSubView() { searchFilterDocs={this.searchFilterDocs} styleProvider={DefaultStyleProvider} docViewPath={returnEmptyDoclist} - moveDocument={this.props.moveDocument} + moveDocument={this._props.moveDocument} addDocument={this.addRow} - removeDocument={this.props.removeDocument} + removeDocument={this._props.removeDocument} whenChildContentsActiveChanged={returnFalse} - addDocTab={this.props.addDocTab} - pinToPres={this.props.pinToPres} + addDocTab={this._props.addDocTab} + pinToPres={this._props.pinToPres} bringToFront={returnFalse} /> )} @@ -936,7 +942,7 @@ class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsP return ( <div className="schema-table-content" ref={this.props.setRef} style={{ height: `calc(100% - ${CollectionSchemaView._newNodeInputHeight + this.props.rowHeight()}px)` }}> {this.props.childDocs().docs.map((doc: Doc, index: number) => ( - <div className="schema-row-wrapper" style={{ height: this.props.rowHeight() }}> + <div key={doc[Id]} className="schema-row-wrapper" style={{ height: this.props.rowHeight() }}> <CollectionSchemaViewDoc doc={doc} schema={this.props.schema} index={index} rowHeight={this.props.rowHeight} /> </div> ))} @@ -954,8 +960,18 @@ interface CollectionSchemaViewDocProps { @observer class CollectionSchemaViewDoc extends React.Component<CollectionSchemaViewDocProps> { - tableWidthFunc = () => this.props.schema.tableWidth; - screenToLocalXf = () => this.props.schema.props.ScreenToLocalTransform().translate(0, -this.props.rowHeight() - this.props.index * this.props.rowHeight()); + _prevProps: CollectionSchemaViewDocProps; + @observable _props; + constructor(props: CollectionSchemaViewDocProps) { + super(props); + this._props = this._prevProps = props; + makeObservable(this); + } + componentDidUpdate() { + copyProps(this); + } + tableWidthFunc = () => this._props.schema.tableWidth; + screenToLocalXf = () => this._props.schema._props.ScreenToLocalTransform().translate(0, -this._props.rowHeight() - this._props.index * this._props.rowHeight()); noOpacityStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string) => { if (property === StyleProp.Opacity) return 1; return DefaultStyleProvider(doc, props, property); @@ -963,30 +979,30 @@ class CollectionSchemaViewDoc extends React.Component<CollectionSchemaViewDocPro render() { return ( <DocumentView - key={this.props.doc[Id]} - {...this.props.schema.props} - LayoutTemplate={this.props.schema.props.childLayoutTemplate} - LayoutTemplateString={SchemaRowBox.LayoutString(this.props.schema.props.fieldKey, this.props.index)} - Document={this.props.doc} - renderDepth={this.props.schema.props.renderDepth + 1} + key={this._props.doc[Id]} + {...this._props.schema._props} + LayoutTemplate={this._props.schema._props.childLayoutTemplate} + LayoutTemplateString={SchemaRowBox.LayoutString(this._props.schema._props.fieldKey, this._props.index)} + Document={this._props.doc} + renderDepth={this._props.schema._props.renderDepth + 1} PanelWidth={this.tableWidthFunc} - PanelHeight={this.props.rowHeight} + PanelHeight={this._props.rowHeight} styleProvider={this.noOpacityStyleProvider} waitForDoubleClickToClick={returnNever} defaultDoubleClick={returnIgnore} dragAction="move" onClickScriptDisable="always" - focus={this.props.schema.focusDocument} - childFilters={this.props.schema.childDocFilters} - childFiltersByRanges={this.props.schema.childDocRangeFilters} - searchFilterDocs={this.props.schema.searchFilterDocs} - rootSelected={this.props.schema.rootSelected} + focus={this._props.schema.focusDocument} + childFilters={this._props.schema.childDocFilters} + childFiltersByRanges={this._props.schema.childDocRangeFilters} + searchFilterDocs={this._props.schema.searchFilterDocs} + rootSelected={this._props.schema.rootSelected} ScreenToLocalTransform={this.screenToLocalXf} bringToFront={emptyFunction} dragWhenActive={true} - isDocumentActive={this.props.schema.props.childDocumentsActive?.() ? this.props.schema.props.isDocumentActive : this.props.schema.isContentActive} + isDocumentActive={this._props.schema._props.childDocumentsActive?.() ? this._props.schema._props.isDocumentActive : this._props.schema.isContentActive} isContentActive={emptyFunction} - whenChildContentsActiveChanged={this.props.schema.props.whenChildContentsActiveChanged} + whenChildContentsActiveChanged={this._props.schema._props.whenChildContentsActiveChanged} hideDecorations={true} hideTitle={true} hideDocumentButtonBar={true} diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 5a2926159..737d7e0f4 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -1,13 +1,13 @@ import * as React from 'react'; import { IconButton, Size } from 'browndash-components'; -import { computed } from 'mobx'; +import { computed, makeObservable, override } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import { CgClose } from 'react-icons/cg'; import { FaExternalLinkAlt } from 'react-icons/fa'; import { Doc } from '../../../../fields/Doc'; import { BoolCast } from '../../../../fields/Types'; -import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils'; +import { copyProps, emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils'; import { DragManager } from '../../../util/DragManager'; import { SnappingManager } from '../../../util/SnappingManager'; import { Transform } from '../../../util/Transform'; @@ -28,17 +28,27 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo public static LayoutString(fieldKey: string, rowIndex: number) { return FieldView.LayoutString(SchemaRowBox, fieldKey).replace('fieldKey', `rowIndex={${rowIndex}} fieldKey`); } - private _ref: HTMLDivElement | null = null; + _prevProps: FieldViewProps & SchemaRowBoxProps; + @override _props: FieldViewProps & SchemaRowBoxProps; + constructor(props: FieldViewProps & SchemaRowBoxProps) { + super(props); + this._props = this._prevProps = props; + makeObservable(this); + } + componentDidUpdate() { + copyProps(this); + } + bounds = () => this._ref?.getBoundingClientRect(); @computed get schemaView() { - return this.props.DocumentView?.()._props.docViewPath().lastElement()?.ComponentView as CollectionSchemaView; + return this._props.DocumentView?.()._props.docViewPath().lastElement()?.ComponentView as CollectionSchemaView; } @computed get schemaDoc() { - return this.props.DocumentView?.()._props.docViewPath().lastElement()?.Document; + return this._props.DocumentView?.()._props.docViewPath().lastElement()?.Document; } @computed get rowIndex() { @@ -46,7 +56,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo } componentDidMount(): void { - this.props.setContentView?.(this); + this._props.setContentView?.(this); } select = (ctrlKey: boolean, shiftKey: boolean) => { @@ -54,12 +64,12 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo const lastSelected = Array.from(this.schemaView._selectedDocs).lastElement(); if (shiftKey && lastSelected) this.schemaView.selectRows(this.Document, lastSelected); else { - this.props.select?.(ctrlKey); + this._props.select?.(ctrlKey); } }; onPointerEnter = (e: any) => { - if (SnappingManager.IsDragging && this.props.isContentActive()) { + if (SnappingManager.IsDragging && this._props.isContentActive()) { document.removeEventListener('pointermove', this.onPointerMove); document.addEventListener('pointermove', this.onPointerMove); } @@ -103,7 +113,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo return ( <div className="schema-row" - style={{ height: this.props.PanelHeight(), backgroundColor: this.props.isSelected() ? Colors.LIGHT_BLUE : undefined }} + style={{ height: this._props.PanelHeight(), backgroundColor: this._props.isSelected() ? Colors.LIGHT_BLUE : undefined }} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave} ref={(row: HTMLDivElement | null) => { @@ -114,7 +124,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo className="row-menu" style={{ width: CollectionSchemaView._rowMenuWidth, - pointerEvents: !this.props.isContentActive() ? 'none' : undefined, + pointerEvents: !this._props.isContentActive() ? 'none' : undefined, }}> <IconButton tooltip="close" @@ -128,7 +138,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo emptyFunction, undoable(e => { e.stopPropagation(); - this.props.removeDocument?.(this.Document); + this._props.removeDocument?.(this.Document); }, 'Delete Row') ) } @@ -145,7 +155,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo emptyFunction, undoable(e => { e.stopPropagation(); - this.props.addDocTab(this.Document, OpenWhere.addRight); + this._props.addDocTab(this.Document, OpenWhere.addRight); }, 'Open schema Doc preview') ) } @@ -161,7 +171,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo allowCRs={false} // to enter text with new lines, must use \n columnWidth={this.columnWidth(index)} rowHeight={this.schemaView.rowHeightFunc} - isRowActive={this.props.isContentActive} + isRowActive={this._props.isContentActive} getFinfo={this.getFinfo} selectCell={this.selectCell} deselectCell={this.deselectCell} @@ -172,7 +182,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo transform={() => { const ind = index === this.schemaView.columnKeys.length - 1 ? this.schemaView.columnKeys.length - 3 : index; const x = this.schemaView?.displayColumnWidths.reduce((p, c, i) => (i <= ind ? p + c : p), 0); - const y = (this.props.rowIndex ?? 0) * this.props.PanelHeight(); + const y = (this._props.rowIndex ?? 0) * this._props.PanelHeight(); return new Transform(x + CollectionSchemaView._rowMenuWidth, y, 1); }} /> diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index dcd3bffac..814003955 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -21,18 +21,18 @@ import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; import { WebBox } from '../nodes/WebBox'; ScriptingGlobals.add(function IsNoneSelected() { - return SelectionManager.Views().length <= 0; + return SelectionManager.Views.length <= 0; }, 'are no document selected'); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setView(view: string) { - const selected = SelectionManager.Docs().lastElement(); + const selected = SelectionManager.Docs.lastElement(); selected ? (selected._type_collection = view) : console.log('[FontIconBox.tsx] changeView failed'); }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) { - const selectedViews = SelectionManager.Views(); + const selectedViews = SelectionManager.Views; if (Doc.ActiveTool !== InkTool.None) { if (checkResult) { return ActiveFillColor(); @@ -60,7 +60,7 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b } }); } else { - const selected = SelectionManager.Docs().length ? SelectionManager.Docs() : LinkManager.currentLink ? [LinkManager.currentLink] : []; + const selected = SelectionManager.Docs.length ? SelectionManager.Docs : LinkManager.currentLink ? [LinkManager.currentLink] : []; if (checkResult) { return selected.lastElement()?._backgroundColor ?? 'transparent'; } @@ -72,10 +72,10 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b // toggle: Set overlay status of selected document ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boolean) { if (checkResult) { - return SelectionManager.Views().length ? StrCast(SelectionManager.Docs().lastElement().layout_headingColor) : Doc.SharingDoc().headingColor; + return SelectionManager.Views.length ? StrCast(SelectionManager.Docs.lastElement().layout_headingColor) : Doc.SharingDoc().headingColor; } - if (SelectionManager.Views().length) { - SelectionManager.Docs().forEach(doc => { + if (SelectionManager.Views.length) { + SelectionManager.Docs.forEach(doc => { Doc.GetProto(doc).layout_headingColor = color; doc.layout_showTitle = color === 'transparent' ? undefined : StrCast(doc.layout_showTitle, 'title'); }); @@ -88,7 +88,7 @@ ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boole // toggle: Set overlay status of selected document ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; + const selected = SelectionManager.Views.length ? SelectionManager.Views[0] : undefined; if (checkResult) { if (NumCast(selected?.Document.z) >= 1) return true; return false; @@ -97,7 +97,7 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { }); ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce', checkResult?: boolean) { - const selected = SelectionManager.Docs().lastElement(); + const selected = SelectionManager.Docs.lastElement(); // prettier-ignore const map: Map<'flashcards' | 'center' |'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll' | 'fitOnce', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc, dv:DocumentView) => void;}> = new Map([ ['grid', { @@ -140,13 +140,13 @@ ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid return map.get(attr)?.checkResult(selected); } const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; - SelectionManager.Views().map(dv => map.get(attr)?.setDoc(dv.layoutDoc, dv)); + SelectionManager.Views.map(dv => map.get(attr)?.setDoc(dv.layoutDoc, dv)); setTimeout(() => batch.end(), 100); }); ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highlight' | 'fontSize' | 'alignment', value: any, checkResult?: boolean) { const editorView = RichTextMenu.Instance?.TextView?.EditorView; - const selected = SelectionManager.Docs().lastElement(); + const selected = SelectionManager.Docs.lastElement(); // prettier-ignore const map: Map<'font'|'fontColor'|'highlight'|'fontSize'|'alignment', { checkResult: () => any; setDoc: () => void;}> = new Map([ ['font', { @@ -338,7 +338,7 @@ ScriptingGlobals.add(setActiveTool, 'sets the active ink tool mode'); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'fillColor' | 'strokeWidth' | 'strokeColor', value: any, checkResult?: boolean) { - const selected = SelectionManager.Docs().lastElement() ?? Doc.UserDoc(); + const selected = SelectionManager.Docs.lastElement() ?? Doc.UserDoc(); // prettier-ignore const map: Map<'inkMask' | 'fillColor' | 'strokeWidth' | 'strokeColor', { checkResult: () => any; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([ ['inkMask', { @@ -367,16 +367,14 @@ ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'fillColor' | ' return map.get(option)?.checkResult(); } map.get(option)?.setMode(); - SelectionManager.Docs() - .filter(doc => doc.type === DocumentType.INK) - .map(doc => map.get(option)?.setInk(doc)); + SelectionManager.Docs.filter(doc => doc.type === DocumentType.INK).map(doc => map.get(option)?.setInk(doc)); }); /** WEB * webSetURL **/ ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) { - const selected = SelectionManager.Views().lastElement(); + const selected = SelectionManager.Views.lastElement(); if (selected?.Document.type === DocumentType.WEB) { if (checkResult) { return StrCast(selected.Document.data, Cast(selected.Document.data, WebField, null)?.url?.href); @@ -386,14 +384,14 @@ ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) { } }); ScriptingGlobals.add(function webForward(checkResult?: boolean) { - const selected = SelectionManager.Views().lastElement()?.ComponentView as WebBox; + const selected = SelectionManager.Views.lastElement()?.ComponentView as WebBox; if (checkResult) { return selected?.forward(checkResult) ? undefined : 'lightGray'; } selected?.forward(); }); ScriptingGlobals.add(function webBack(checkResult?: boolean) { - const selected = SelectionManager.Views().lastElement()?.ComponentView as WebBox; + const selected = SelectionManager.Views.lastElement()?.ComponentView as WebBox; if (checkResult) { return selected?.back(checkResult) ? undefined : 'lightGray'; } @@ -404,7 +402,7 @@ ScriptingGlobals.add(function webBack(checkResult?: boolean) { * toggleSchemaPreview **/ ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) { - const selected = SelectionManager.Docs().lastElement(); + const selected = SelectionManager.Docs.lastElement(); if (checkResult && selected) { const result: boolean = NumCast(selected.schema_previewWidth) > 0; if (result) return Colors.MEDIUM_BLUE; @@ -418,7 +416,7 @@ ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) { } }); ScriptingGlobals.add(function toggleSingleLineSchema(checkResult?: boolean) { - const selected = SelectionManager.Docs().lastElement(); + const selected = SelectionManager.Docs.lastElement(); if (checkResult && selected) { return NumCast(selected._schema_singleLine) > 0 ? Colors.MEDIUM_BLUE : 'transparent'; } @@ -431,7 +429,7 @@ ScriptingGlobals.add(function toggleSingleLineSchema(checkResult?: boolean) { * groupBy */ ScriptingGlobals.add(function setGroupBy(key: string, checkResult?: boolean) { - SelectionManager.Docs().map(doc => (doc._text_fontFamily = key)); + SelectionManager.Docs.map(doc => (doc._text_fontFamily = key)); const editorView = RichTextMenu.Instance.TextView?.EditorView; if (checkResult) { return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index cca2ed3ba..08ee708f7 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -400,7 +400,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps startDragging(x: number, y: number, dropAction: dropActionType, hideSource = false) { if (this._mainCont.current) { - const views = SelectionManager.Views().filter(dv => dv.docView?._mainCont.current); + const views = SelectionManager.Views.filter(dv => dv.docView?._mainCont.current); const selected = views.length > 1 && views.some(dv => dv.Document === this.Document) ? views : [this._props.DocumentView()]; const dragData = new DragManager.DocumentDragData(selected.map(dv => dv.Document)); const [left, top] = this._props.ScreenToLocalTransform().scale(this.NativeDimScaling).inverse().transformPoint(0, 0); @@ -760,8 +760,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps if (this._props.bringToFront !== emptyFunction) { const zorders = cm.findByDescription('ZOrder...'); const zorderItems: ContextMenuProps[] = zorders && 'subitems' in zorders ? zorders.subitems : []; - zorderItems.push({ description: 'Bring to Front', event: () => SelectionManager.Views().forEach(dv => dv._props.bringToFront(dv.Document, false)), icon: 'arrow-up' }); - zorderItems.push({ description: 'Send to Back', event: () => SelectionManager.Views().forEach(dv => dv._props.bringToFront(dv.Document, true)), icon: 'arrow-down' }); + zorderItems.push({ description: 'Bring to Front', event: () => SelectionManager.Views.forEach(dv => dv._props.bringToFront(dv.Document, false)), icon: 'arrow-up' }); + zorderItems.push({ description: 'Send to Back', event: () => SelectionManager.Views.forEach(dv => dv._props.bringToFront(dv.Document, true)), icon: 'arrow-down' }); zorderItems.push({ description: !this.layoutDoc._keepZDragged ? 'Keep ZIndex when dragged' : 'Allow ZIndex to change when dragged', event: undoBatch(action(() => (this.layoutDoc._keepZWhenDragged = !this.layoutDoc._keepZWhenDragged))), @@ -1588,7 +1588,7 @@ export class DocumentView extends React.Component<DocumentViewProps> { docViewPathFunc = () => this.docViewPath; isSelected = () => this.SELECTED; select = (extendSelection: boolean, focusSelection?: boolean) => { - if (this.SELECTED && SelectionManager.Views().length > 1) SelectionManager.DeselectView(this); + if (this.SELECTED && SelectionManager.Views.length > 1) SelectionManager.DeselectView(this); else { SelectionManager.SelectView(this, extendSelection); if (focusSelection) { diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index 22339907f..d8b1f125c 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -187,7 +187,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() { let icon: IconProp = 'caret-down'; const isViewDropdown = script?.script.originalScript.startsWith('setView'); if (isViewDropdown) { - const selected = SelectionManager.Docs(); + const selected = SelectionManager.Docs; if (selected.lastElement()) { if (StrCast(selected.lastElement().type) === DocumentType.COL) { text = StrCast(selected.lastElement()._type_collection); diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index 31aa15588..a7e905fca 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -83,9 +83,9 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() { const anchor = this.fieldKey === 'link_anchor_1' ? 'link_anchor_2' : 'link_anchor_1'; const anchorScale = !this.dataDoc[this.fieldKey + '_useSmallAnchor'] && (x === 0 || x === 100 || y === 0 || y === 100) ? 1 : 0.25; const targetTitle = StrCast((this.dataDoc[anchor] as Doc)?.title); - const selView = SelectionManager.Views().lastElement()?._props.LayoutTemplateString?.includes('link_anchor_1') + const selView = SelectionManager.Views.lastElement()?._props.LayoutTemplateString?.includes('link_anchor_1') ? 'link_anchor_1' - : SelectionManager.Views().lastElement()?._props.LayoutTemplateString?.includes('link_anchor_2') + : SelectionManager.Views.lastElement()?._props.LayoutTemplateString?.includes('link_anchor_2') ? 'link_anchor_2' : ''; return ( diff --git a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx index e6c1db0af..ee1ea3ceb 100644 --- a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx +++ b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx @@ -47,7 +47,7 @@ export class MapAnchorMenu extends AntimodeMenu<AntimodeMenuProps> { componentDidMount() { this._disposer = reaction( - () => SelectionManager.Views().slice(), + () => SelectionManager.Views.slice(), sel => MapAnchorMenu.Instance.fadeOut(true) ); } diff --git a/src/client/views/nodes/MapBox/MapBox2.tsx b/src/client/views/nodes/MapBox/MapBox2.tsx index 2c4c992d1..fdd8285d5 100644 --- a/src/client/views/nodes/MapBox/MapBox2.tsx +++ b/src/client/views/nodes/MapBox/MapBox2.tsx @@ -510,8 +510,8 @@ // // TODO: auto center on select a document in the sidebar // private handleMapCenter = (map: google.maps.Map) => { // // console.log("print the selected views in selectionManager:") -// // if (SelectionManager.Views().lastElement()) { -// // console.log(SelectionManager.Views().lastElement()); +// // if (SelectionManager.Views.lastElement()) { +// // console.log(SelectionManager.Views.lastElement()); // // } // }; diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index d7e799161..7de1eb717 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -116,7 +116,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { } componentDidMount() { this._disposer = reaction( - () => SelectionManager.Views().slice(), + () => SelectionManager.Views.slice(), views => this.updateMenu(undefined, undefined, undefined, undefined) ); } @@ -245,8 +245,8 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { m.type === state.schema.marks.pFontSize && activeSizes.add(m.attrs.fontSize); m.type === state.schema.marks.marker && activeHighlights.add(String(m.attrs.highlight)); }); - } else if (SelectionManager.Views().some(dv => dv.ComponentView instanceof EquationBox)) { - SelectionManager.Views().forEach(dv => StrCast(dv.Document._text_fontSize) && activeSizes.add(StrCast(dv.Document._text_fontSize))); + } else if (SelectionManager.Views.some(dv => dv.ComponentView instanceof EquationBox)) { + SelectionManager.Views.forEach(dv => StrCast(dv.Document._text_fontSize) && activeSizes.add(StrCast(dv.Document._text_fontSize))); } return { activeFamilies: Array.from(activeFamilies), activeSizes: Array.from(activeSizes), activeColors: Array.from(activeColors), activeHighlights: Array.from(activeHighlights) }; } @@ -365,8 +365,8 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { this.setMark(fmark, this.view.state, (tx: any) => this.view!.dispatch(tx.addStoredMark(fmark)), true); this.view.focus(); } - } else if (SelectionManager.Views().some(dv => dv.ComponentView instanceof EquationBox)) { - SelectionManager.Views().forEach(dv => (dv.Document._text_fontSize = fontSize)); + } else if (SelectionManager.Views.some(dv => dv.ComponentView instanceof EquationBox)) { + SelectionManager.Views.forEach(dv => (dv.Document._text_fontSize = fontSize)); } else Doc.UserDoc().fontSize = fontSize; this.updateMenu(this.view, undefined, this._props, this.layoutDoc); }; @@ -649,7 +649,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { if (linkDoc instanceof Doc) { const link_anchor_1 = await Cast(linkDoc.link_anchor_1, Doc); const link_anchor_2 = await Cast(linkDoc.link_anchor_2, Doc); - const currentDoc = SelectionManager.Docs().lastElement(); + const currentDoc = SelectionManager.Docs.lastElement(); if (currentDoc && link_anchor_1 && link_anchor_2) { if (Doc.AreProtosEqual(currentDoc, link_anchor_1)) { return StrCast(link_anchor_2.title); @@ -781,11 +781,11 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { // <div className="collectionMenu-divider" key="divider 3" /> // {[this.createMarksDropdown(this.activeFontSize, this.fontSizeOptions, "font size", action((val: string) => { // this.activeFontSize = val; - // SelectionManager.Views().map(dv => dv.props.Document._text_fontSize = val); + // SelectionManager.Views.map(dv => dv.props.Document._text_fontSize = val); // })), // this.createMarksDropdown(this.activeFontFamily, this.fontFamilyOptions, "font family", action((val: string) => { // this.activeFontFamily = val; - // SelectionManager.Views().map(dv => dv.props.Document._text_fontFamily = val); + // SelectionManager.Views.map(dv => dv.props.Document._text_fontFamily = val); // })), // <div className="collectionMenu-divider" key="divider 4" />, // this.createNodesDropdown(this.activeListType, this.listTypeOptions, "list type", () => ({})), diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index a224ec7fa..4ff816812 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -139,7 +139,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { return false; } @computed get selectedDocumentView() { - if (SelectionManager.Views().length) return SelectionManager.Views()[0]; + if (SelectionManager.Views.length) return SelectionManager.Views[0]; if (this.selectedArray.size) return DocumentManager.Instance.getDocumentView(this.Document); } @computed get isPres() { @@ -187,7 +187,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { this._unmounting = false; this.turnOffEdit(true); this._disposers.selection = reaction( - () => SelectionManager.Views().slice(), + () => SelectionManager.Views.slice(), views => (!PresBox.Instance || views.some(view => view.Document === this.Document)) && this.updateCurrentPresentation(), { fireImmediately: true } ); diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index 3c26c307f..0627876fa 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -69,7 +69,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { componentDidMount() { this._disposer = reaction( - () => SelectionManager.Views().slice(), + () => SelectionManager.Views.slice(), sel => AnchorMenu.Instance.fadeOut(true) ); } @@ -158,7 +158,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { * all selected text available to summarize but its only supported for pdf and web ATM. * @returns Whether the GPT icon for summarization should appear */ - canSummarize = () => SelectionManager.Docs().some(doc => [DocumentType.PDF, DocumentType.WEB].includes(doc.type as any)); + canSummarize = () => SelectionManager.Docs.some(doc => [DocumentType.PDF, DocumentType.WEB].includes(doc.type as any)); render() { const buttons = diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 349f15c96..a581e9df6 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -119,7 +119,7 @@ export class PDFViewer extends React.Component<IViewerProps> { this._disposers.selected = reaction( () => this._props.isSelected(), - selected => SelectionManager.Views().length === 1 && this.setupPdfJsViewer(), + selected => SelectionManager.Views.length === 1 && this.setupPdfJsViewer(), { fireImmediately: true } ); this._disposers.curPage = reaction( |