From 95c076b64a816c6bd503089f90234f8ce078eae8 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 29 Mar 2023 11:51:51 -0400 Subject: fixed sizing of link count button. moved border paths and audio to style provider --- src/client/views/nodes/DocumentLinksButton.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/client/views/nodes/DocumentLinksButton.tsx') diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index a40599d85..d6679b46d 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -71,11 +71,7 @@ export class DocumentLinksButton extends React.Component { - if (doubleTap) { - DocumentView.showBackLinks(this.props.View.rootDoc); - } - }), + action((e, doubleTap) => doubleTap && DocumentView.showBackLinks(this.props.View.rootDoc)), undefined, undefined, action(() => (DocumentLinksButton.LinkEditorDocView = this.props.View)) -- cgit v1.2.3-70-g09d2 From e4b76f6c1dee63c49408c48d7b2bc98e62dc813a Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 5 Apr 2023 12:19:01 -0400 Subject: adjusted general context menu items to always appear last. cleaned up makeLink api, --- src/client/documents/Documents.ts | 32 +++++----- src/client/util/DragManager.ts | 1 - src/client/util/LinkFollower.ts | 2 - src/client/views/ContextMenu.tsx | 12 ++-- src/client/views/DocumentButtonBar.tsx | 4 +- src/client/views/MainView.tsx | 1 + src/client/views/SidebarAnnos.tsx | 2 +- .../views/collections/CollectionNoteTakingView.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 28 ++++----- src/client/views/collections/CollectionSubView.tsx | 2 +- src/client/views/collections/TreeView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 26 ++------ .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- src/client/views/nodes/DocumentLinksButton.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 70 +++++++++++++++------- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/PDFBox.tsx | 31 +++++----- src/client/views/nodes/VideoBox.tsx | 6 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 4 +- .../views/nodes/formattedText/RichTextRules.ts | 2 +- src/client/views/search/SearchBox.tsx | 2 +- 21 files changed, 117 insertions(+), 118 deletions(-) (limited to 'src/client/views/nodes/DocumentLinksButton.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 9cb480c4a..5623ca218 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -470,7 +470,7 @@ export namespace Docs { DocumentType.AUDIO, { layout: { view: AudioBox, dataField: defaultDataKey }, - options: { _height: 100, forceReflow: true, nativeDimModifiable: true }, + options: { _height: 100, fitWidth: true, forceReflow: true, nativeDimModifiable: true }, }, ], [ @@ -934,13 +934,13 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.RTF), field, options, undefined, fieldKey); } - export function LinkDocument(source: { doc: Doc; ctx?: Doc }, target: { doc: Doc; ctx?: Doc }, options: DocumentOptions = {}, id?: string) { + export function LinkDocument(source: Doc, target: Doc, options: DocumentOptions = {}, id?: string) { const linkDoc = InstanceFromProto( Prototypes.get(DocumentType.LINK), undefined, { - anchor1: source.doc, - anchor2: target.doc, + anchor1: source, + anchor2: target, ...options, }, id @@ -1294,16 +1294,14 @@ export namespace DocUtils { broadcastEvent && runInAction(() => (DocumentManager.Instance.RecordingEvent = DocumentManager.Instance.RecordingEvent + 1)); return DocUtils.ActiveRecordings.map(audio => { const sourceDoc = getSourceDoc(); - const link = sourceDoc && DocUtils.MakeLink({ doc: sourceDoc }, { doc: audio.getAnchor(true) || audio.props.Document }, 'recording annotation:linked recording', 'recording timeline'); - link && (link.followLinkLocation = OpenWhere.addRight); - return link; + return sourceDoc && DocUtils.MakeLink(sourceDoc, audio.getAnchor(true) || audio.props.Document, { linkDisplay: false, linkRelationship: 'recording annotation:linked recording', description: 'recording timeline' }); }); } - export function MakeLink(source: { doc: Doc }, target: { doc: Doc }, linkRelationship: string = '', description: string = '', id?: string, allowParCollectionLink?: boolean, showPopup?: number[]) { - if (!linkRelationship) linkRelationship = target.doc.type === DocumentType.RTF ? 'Commentary:Comments On' : 'link'; - const sv = DocumentManager.Instance.getDocumentView(source.doc); - if (!allowParCollectionLink && sv?.props.ContainingCollectionDoc === target.doc) return; + export function MakeLink(source: Doc, target: Doc, linkSettings: { linkRelationship?: string; description?: string; linkDisplay?: boolean }, id?: string, allowParCollectionLink?: boolean, showPopup?: number[]) { + if (!linkSettings.linkRelationship) linkSettings.linkRelationship = target.type === DocumentType.RTF ? 'Commentary:Comments On' : 'link'; + const sv = DocumentManager.Instance.getDocumentView(source); + if (!allowParCollectionLink && sv?.props.ContainingCollectionDoc === target) return; if (target.doc === Doc.UserDoc()) return undefined; const makeLink = action((linkDoc: Doc, showPopup?: number[]) => { @@ -1343,16 +1341,16 @@ export namespace DocUtils { target, { title: ComputedField.MakeFunction('generateLinkTitle(self)') as any, - 'anchor1-useLinkSmallAnchor': source.doc.useLinkSmallAnchor ? true : undefined, - 'anchor2-useLinkSmallAnchor': target.doc.useLinkSmallAnchor ? true : undefined, + 'anchor1-useLinkSmallAnchor': source.useLinkSmallAnchor ? true : undefined, + 'anchor2-useLinkSmallAnchor': target.useLinkSmallAnchor ? true : undefined, 'acl-Public': SharingPermissions.Augment, '_acl-Public': SharingPermissions.Augment, - linkDisplay: true, + linkDisplay: linkSettings.linkDisplay, _linkAutoMove: true, - linkRelationship, + linkRelationship: linkSettings.linkRelationship, _showCaption: 'description', _showTitle: 'linkRelationship', - description, + description: linkSettings.description, }, id ), @@ -1700,7 +1698,7 @@ export namespace DocUtils { _timecodeToShow: Cast(doc._timecodeToShow, 'number', null), }); Doc.AddDocToList(context, annotationField, pushpin); - const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, 'pushpin', ''); + const pushpinLink = DocUtils.MakeLink(pushpin, doc, { linkRelationship: 'pushpin' }, ''); doc._timecodeToShow = undefined; return pushpin; } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index cc116fb46..7d2aa813f 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -168,7 +168,6 @@ export namespace DragManager { this.dropDocCreator = dropDocCreator; this.offset = [0, 0]; } - linkSourceDoc?: Doc; dropDocCreator: (annotationOn: Doc | undefined) => Doc; dropDocument?: Doc; offset: number[]; diff --git a/src/client/util/LinkFollower.ts b/src/client/util/LinkFollower.ts index 785018990..df61ecece 100644 --- a/src/client/util/LinkFollower.ts +++ b/src/client/util/LinkFollower.ts @@ -9,8 +9,6 @@ import { DocumentManager } from './DocumentManager'; import { LinkManager } from './LinkManager'; import { SelectionManager } from './SelectionManager'; import { UndoManager } from './UndoManager'; - -type CreateViewFunc = (doc: Doc, followLinkLocation: string, finished?: () => void) => void; /* * link doc: * - anchor1: doc diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 6a530e3ae..e4c3e864b 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -102,13 +102,11 @@ export class ContextMenu extends React.Component { } } @action - moveAfter(item: ContextMenuProps, after: ContextMenuProps) { - if (after && this.findByDescription(after.description)) { - const curInd = this._items.findIndex(i => i.description === item.description); - this._items.splice(curInd, 1); - const afterInd = this._items.findIndex(i => i.description === after.description); - this._items.splice(afterInd + 1, 0, item); - } + moveAfter(item: ContextMenuProps, after?: ContextMenuProps) { + const curInd = this._items.findIndex(i => i.description === item.description); + this._items.splice(curInd, 1); + const afterInd = after && this.findByDescription(after.description) ? this._items.findIndex(i => i.description === after.description) : this._items.length; + this._items.splice(afterInd, 0, item); } @action setDefaultItem(prefix: string, item: (name: string) => void) { diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 9389fed01..3e1a0f265 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -416,7 +416,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV const targetDoc = this.view0?.props.Document; return !targetDoc ? null : ( {`Open Context Menu`}}> -
this.openContextMenu(e)}> +
@@ -569,7 +569,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV const anchor = rootView.ComponentView?.getAnchor?.(false) ?? rootDoc; const trail = DocCast(anchor.presTrail) ?? Doc.MakeCopy(DocCast(Doc.UserDoc().emptyTrail), true); if (trail !== anchor.presTrail) { - DocUtils.MakeLink({ doc: anchor }, { doc: trail }, 'link trail'); + DocUtils.MakeLink(anchor, trail, { linkRelationship: 'link trail' }); anchor.presTrail = trail; } Doc.ActivePresentation = trail; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index befb0200d..b0888df68 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -270,6 +270,7 @@ export class MainView extends React.Component { fa.faLaptopCode, fa.faMale, fa.faCopy, + fa.faHome, fa.faHandPointLeft, fa.faHandPointRight, fa.faCompass, diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index 48c0150e6..2d2b0f83e 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -74,7 +74,7 @@ export class SidebarAnnos extends React.Component { }); FormattedTextBox.SelectOnLoad = target[Id]; FormattedTextBox.DontSelectInitialText = true; - const link = DocUtils.MakeLink({ doc: anchor }, { doc: target }, 'inline comment:comment on'); + const link = DocUtils.MakeLink(anchor, target, { linkRelationship: 'inline comment:comment on' }); link && (link.linkDisplay = false); const taggedContent = this.docFilters() diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index 121260680..cb5be990d 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -441,7 +441,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { } else if (de.complete.linkDragData?.dragDocument.context === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) { const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, _fitWidth: true, title: 'dropped annotation' }); this.props.addDocument?.(source); - de.complete.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: de.complete.linkDragData.linkSourceGetAnchor() }, 'doc annotation', ''); // TODODO this is where in text links get passed + de.complete.linkDocument = DocUtils.MakeLink(source, de.complete.linkDragData.linkSourceGetAnchor(), { linkRelationship: 'doc annotation' }); // TODODO this is where in text links get passed e.stopPropagation(); } else if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de.complete.annoDragData); return false; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 64ec419ec..1e02fc9d4 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -3,14 +3,14 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { CursorProperty } from 'csstype'; import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; -import { DataSym, Doc, DocListCast, HeightSym, Opt, WidthSym } from '../../../fields/Doc'; +import { DataSym, Doc, HeightSym, Opt, WidthSym } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; -import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; +import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { CollectionViewType } from '../../documents/DocumentTypes'; import { DragManager, dropActionType } from '../../util/DragManager'; @@ -460,7 +460,7 @@ export class CollectionStackingView extends CollectionSubView { // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout if (!e.isPropagationStopped()) { - const subItems: ContextMenuProps[] = []; - subItems.push({ description: `${this.layoutDoc._columnsFill ? 'Variable Size' : 'Autosize'} Column`, event: () => (this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill), icon: 'plus' }); - subItems.push({ description: `${this.layoutDoc._autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight), icon: 'plus' }); - subItems.push({ description: 'Clear All', event: () => (this.dataDoc.data = new List([])), icon: 'times' }); - ContextMenu.Instance.addItem({ description: 'Options...', subitems: subItems, icon: 'eye' }); + const cm = ContextMenu.Instance; + const options = cm.findByDescription('Options...'); + const optionItems: ContextMenuProps[] = options && 'subitems' in options ? options.subitems : []; + optionItems.push({ description: `${this.layoutDoc._columnsFill ? 'Variable Size' : 'Autosize'} Column`, event: () => (this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill), icon: 'plus' }); + optionItems.push({ description: `${this.layoutDoc._autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight), icon: 'plus' }); + optionItems.push({ description: 'Clear All', event: () => (this.dataDoc[this.fieldKey ?? 'data'] = new List([])), icon: 'times' }); + !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'compass' }); } }; @@ -735,14 +737,6 @@ export class CollectionStackingView extends CollectionSubView
)} - {/* {this.chromeHidden || !this.props.isSelected() ? (null) : - } */} diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 5100d8d67..132ed6fb6 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -335,7 +335,7 @@ export function CollectionSubView(moreProps?: X) { const focusNode = iframe?.contentDocument?.getSelection()?.focusNode as any; if (focusNode) { const anchor = srcWeb?.ComponentView?.getAnchor?.(true); - anchor && DocUtils.MakeLink({ doc: htmlDoc }, { doc: anchor }); + anchor && DocUtils.MakeLink(htmlDoc, anchor, {}); } } } diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 99b7549c0..75e76019e 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -359,7 +359,7 @@ export class TreeView extends React.Component { if (de.complete.linkDragData) { const sourceDoc = de.complete.linkDragData.linkSourceGetAnchor(); const destDoc = this.doc; - DocUtils.MakeLink({ doc: sourceDoc }, { doc: destDoc }, 'tree link', ''); + DocUtils.MakeLink(sourceDoc, destDoc, { linkRelationship: 'tree link' }); e.stopPropagation(); } const docDragData = de.complete.docDragData; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d39668a5d..fb0bd2a19 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -397,7 +397,7 @@ export class CollectionFreeFormView extends CollectionSubView (Doc.UserDoc().defaultTextLayout = undefined), icon: 'eye' }); appearanceItems.push({ description: `${this.fitContentsToBox ? 'Make Zoomable' : 'Scale to Window'}`, @@ -1700,7 +1704,7 @@ export class CollectionFreeFormView extends CollectionSubView TabDocView.PinDoc(this.rootDoc, { pinViewport: MarqueeView.CurViewBounds(this.rootDoc, this.props.PanelWidth(), this.props.PanelHeight()) }), icon: 'map-pin' }); - //appearanceItems.push({ description: `update icon`, event: this.updateIcon, icon: "compress-arrows-alt" }); + !Doc.noviceMode && appearanceItems.push({ description: `update icon`, event: this.updateIcon, icon: 'compress-arrows-alt' }); appearanceItems.push({ description: 'Ungroup collection', event: this.promoteCollection, icon: 'table' }); this.props.Document._isGroup && this.Document.transcription && appearanceItems.push({ description: 'Ink to text', event: () => this.transcribeStrokes(false), icon: 'font' }); @@ -1730,27 +1734,9 @@ export class CollectionFreeFormView extends CollectionSubView this.importDocument(e.clientX, e.clientY) }); !mores && ContextMenu.Instance.addItem({ description: 'More...', subitems: moreItems, icon: 'eye' }); }; - importDocument = (x: number, y: number) => { - const input = document.createElement('input'); - input.type = 'file'; - input.accept = '.zip'; - input.onchange = _e => { - input.files && - Doc.importDocument(input.files[0]).then(doc => { - if (doc instanceof Doc) { - const [xx, yy] = this.getTransform().transformPoint(x, y); - (doc.x = xx), (doc.y = yy); - this.props.addDocument?.(doc); - } - }); - }; - input.click(); - }; - @undoBatch @action transcribeStrokes = (math: boolean) => { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 043fe0bcf..0b4f76fa1 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -527,7 +527,7 @@ export class MarqueeView extends React.Component { + drop = (e: Event, de: DragManager.DropEvent) => { if (this.props.dontRegisterView || this.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return; if (this.props.Document === Doc.ActiveDashboard) { alert((e.target as any)?.closest?.('*.lm_content') ? "You can't perform this move most likely because you don't have permission to modify the destination." : 'Linking to document tabs not yet supported. Drop link on document content.'); return; } const linkdrag = de.complete.annoDragData ?? de.complete.linkDragData; - if (linkdrag) linkdrag.linkSourceDoc = linkdrag.linkSourceGetAnchor(); - if (linkdrag?.linkSourceDoc) { - e.stopPropagation(); - if (de.complete.annoDragData && !de.complete.annoDragData.dropDocument) { - de.complete.annoDragData.dropDocument = de.complete.annoDragData.dropDocCreator(undefined); - } - if (de.complete.annoDragData || this.rootDoc !== linkdrag.linkSourceDoc.context) { - const dropDoc = de.complete.annoDragData?.dropDocument ?? this._componentView?.getAnchor?.(true) ?? this.props.Document; - de.complete.linkDocument = DocUtils.MakeLink({ doc: linkdrag.linkSourceDoc }, { doc: dropDoc }, undefined, undefined, undefined, undefined, [de.x, de.y - 50]); + if (linkdrag) { + linkdrag.linkSourceDoc = linkdrag.linkSourceGetAnchor(); + if (linkdrag.linkSourceDoc) { + e.stopPropagation(); + if (de.complete.annoDragData && !de.complete.annoDragData.dropDocument) { + de.complete.annoDragData.dropDocument = de.complete.annoDragData.dropDocCreator(undefined); + } + if (de.complete.annoDragData || this.rootDoc !== linkdrag.linkSourceDoc.context) { + const dropDoc = de.complete.annoDragData?.dropDocument ?? this._componentView?.getAnchor?.(true) ?? this.rootDoc; + de.complete.linkDocument = DocUtils.MakeLink(linkdrag.linkSourceDoc, dropDoc, {}, undefined, undefined, [de.x, de.y - 50]); + } } } }; @@ -643,9 +645,9 @@ export class DocumentViewInternal extends DocComponent d.anchor1 === this.props.Document && d.linkRelationship === 'portal to:portal from'); if (!portalLink) { DocUtils.MakeLink( - { doc: this.props.Document }, - { doc: Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _isLightbox: true, _fitWidth: true, title: StrCast(this.props.Document.title) + ' [Portal]' }) }, - 'portal to:portal from' + this.props.Document, + Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _isLightbox: true, _fitWidth: true, title: StrCast(this.props.Document.title) + ' [Portal]' }), + { linkRelationship: 'portal to:portal from' } ); } this.Document.followLinkLocation = OpenWhere.lightbox; @@ -653,6 +655,24 @@ export class DocumentViewInternal extends DocComponent { + const input = document.createElement('input'); + input.type = 'file'; + input.accept = '.zip'; + input.onchange = _e => { + if (input.files) { + const batch = UndoManager.StartBatch('importing'); + Doc.importDocument(input.files[0]).then(doc => { + if (doc instanceof Doc) { + this.props.addDocTab(doc, OpenWhere.addRight); + batch.end(); + } + }); + } + }; + input.click(); + }; + @action onContextMenu = (e?: React.MouseEvent, pageX?: number, pageY?: number) => { if (e && this.rootDoc._hideContextMenu && Doc.noviceMode) { @@ -704,9 +724,7 @@ export class DocumentViewInternal extends DocComponent this.props.addDocTab(templateDoc, OpenWhere.addRight), icon: 'eye' }); - LinkManager.Links(this.Document).length && - appearanceItems.splice(0, 0, { description: `${this.layoutDoc.hideLinkButton ? 'Show' : 'Hide'} Link Button`, event: action(() => (this.layoutDoc.hideLinkButton = !this.layoutDoc.hideLinkButton)), icon: 'eye' }); - !appearance && cm.addItem({ description: 'UI Controls...', subitems: appearanceItems, icon: 'compass' }); + !appearance && appearanceItems.length && cm.addItem({ description: 'UI Controls...', subitems: appearanceItems, icon: 'compass' }); if (!Doc.IsSystem(this.rootDoc) && this.rootDoc._viewType !== CollectionViewType.Docking && this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Tree) { const existingOnClick = cm.findByDescription('OnClick...'); @@ -774,16 +792,21 @@ export class DocumentViewInternal extends DocComponent Utils.CopyText(Doc.globalServerPath(this.props.Document)), icon: 'fingerprint' }); } - moreItems.push({ description: 'Export collection', icon: 'download', event: async () => Doc.Zip(this.props.Document) }); - - (this.rootDoc._viewType !== CollectionViewType.Docking || !Doc.noviceMode) && moreItems.push({ description: 'Share', event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: 'users' }); } - if (this.props.removeDocument && !Doc.IsSystem(this.rootDoc) && Doc.ActiveDashboard !== this.props.Document) { + !more && moreItems.length && cm.addItem({ description: 'More...', subitems: moreItems, icon: 'compass' }); + } + const constantItems: ContextMenuProps[] = []; + + if (!Doc.IsSystem(this.rootDoc)) { + constantItems.push({ description: 'Export as Zip file', icon: 'download', event: async () => Doc.Zip(this.props.Document) }); + constantItems.push({ description: 'Import Zipped file', icon: 'upload', event: ({ x, y }) => this.importDocument() }); + (this.rootDoc._viewType !== CollectionViewType.Docking || !Doc.noviceMode) && constantItems.push({ description: 'Share', event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: 'users' }); + if (this.props.removeDocument && Doc.ActiveDashboard !== this.props.Document) { // need option to gray out menu items ... preferably with a '?' that explains why they're grayed out (eg., no permissions) - moreItems.push({ description: 'Close', event: this.deleteClicked, icon: 'times' }); + constantItems.push({ description: 'Close', event: this.deleteClicked, icon: 'times' }); } - !more && moreItems.length && cm.addItem({ description: 'More...', subitems: moreItems, icon: 'compass' }); + cm.addItem({ description: 'General...', noexpand: false, subitems: constantItems, icon: 'question' }); } const help = cm.findByDescription('Help...'); const helpItems: ContextMenuProps[] = help && 'subitems' in help ? help.subitems : []; @@ -834,7 +857,8 @@ export class DocumentViewInternal extends DocComponent !isClick && batch.end(), () => { - this.toggleSidebar(); + onButton && this.toggleSidebar(); batch.end(); } ); @@ -440,17 +440,20 @@ export class PDFBox extends ViewBoxAnnotatableComponent (this.rootDoc.sidebarViewType = this.rootDoc.sidebarViewType === CollectionViewType.Freeform ? CollectionViewType.Stacking : CollectionViewType.Freeform); specificContextMenu = (e: React.MouseEvent): void => { - const funcs: ContextMenuProps[] = []; - funcs.push({ - description: 'Toggle Sidebar Type', - event: () => (this.rootDoc.sidebarViewType = this.rootDoc.sidebarViewType === CollectionViewType.Freeform ? CollectionViewType.Stacking : CollectionViewType.Freeform), - icon: 'expand-arrows-alt', - }); - funcs.push({ description: 'Copy path', event: () => this.pdfUrl && Utils.CopyText(Utils.prepend('') + this.pdfUrl.url.pathname), icon: 'expand-arrows-alt' }); - funcs.push({ description: 'update icon', event: () => this.pdfUrl && this.updateIcon(), icon: 'expand-arrows-alt' }); - //funcs.push({ description: "Toggle Sidebar ", event: () => this.toggleSidebar(), icon: "expand-arrows-alt" }); - ContextMenu.Instance.addItem({ description: 'Options...', subitems: funcs, icon: 'asterisk' }); + const cm = ContextMenu.Instance; + const options = cm.findByDescription('Options...'); + const optionItems: ContextMenuProps[] = options && 'subitems' in options ? options.subitems : []; + optionItems.push({ description: 'Toggle Sidebar Type', event: this.toggleSidebarType, icon: 'expand-arrows-alt' }); + !Doc.noviceMode && optionItems.push({ description: 'update icon', event: () => this.pdfUrl && this.updateIcon(), icon: 'expand-arrows-alt' }); + //optionItems.push({ description: "Toggle Sidebar ", event: () => this.toggleSidebar(), icon: "expand-arrows-alt" }); + !options && ContextMenu.Instance.addItem({ description: 'Options...', subitems: optionItems, icon: 'asterisk' }); + const help = cm.findByDescription('Help...'); + const helpItems: ContextMenuProps[] = help && 'subitems' in help ? help.subitems : []; + helpItems.push({ description: 'Copy path', event: () => this.pdfUrl && Utils.CopyText(Utils.prepend('') + this.pdfUrl.url.pathname), icon: 'expand-arrows-alt' }); + !help && ContextMenu.Instance.addItem({ description: 'Help...', noexpand: true, subitems: helpItems, icon: 'asterisk' }); }; @computed get renderTitleBox() { @@ -523,8 +526,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent ) : (
setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.props.DocumentView?.()!, false), true)}> @@ -568,7 +569,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent downX !== undefined && downY !== undefined && DocumentManager.Instance.getFirstDocumentView(imageSnapshot)?.startDragging(downX, downY, 'move', true)); }; @@ -1031,7 +1031,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent Doc.AreProtosEqual(Cast(link.anchor1, Doc, null), this.rootDoc) && Doc.AreProtosEqual(Cast(link.anchor2, Doc, null), target)) || - DocUtils.MakeLink({ doc: this.props.Document }, { doc: target }, LinkManager.AutoKeywords)!); + DocUtils.MakeLink(this.props.Document, target, { linkRelationship: LinkManager.AutoKeywords })!); newAutoLinks.add(alink); const allAnchors = [{ href: Doc.localServerPath(target), title: 'a link', anchorId: this.props.Document[Id] }]; allAnchors.push(...(node.marks.find((m: Mark) => m.type.name === schema.marks.autoLinkAnchor.name)?.attrs.allAnchors ?? [])); @@ -1273,7 +1273,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent() { makeLink = action((linkTo: Doc) => { const linkFrom = this.props.linkCreateAnchor?.(); if (linkFrom) { - const link = DocUtils.MakeLink({ doc: linkFrom }, { doc: linkTo }); + const link = DocUtils.MakeLink(linkFrom, linkTo, {}); link && this.props.linkCreated?.(link); } }); -- cgit v1.2.3-70-g09d2 From 5cd64622f14ede408d3baca4a10d155b60392e46 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 13 Apr 2023 22:22:07 -0400 Subject: lots of changes to get rid of ContainingCollectionDoc and ContainingCollectionView props. --- src/client/documents/Documents.ts | 8 +-- src/client/util/CurrentUserUtils.ts | 2 +- src/client/util/DocumentManager.ts | 83 ++++++++++------------ src/client/util/DragManager.ts | 4 +- .../util/Import & Export/DirectoryImportBox.tsx | 6 +- src/client/util/ReplayMovements.ts | 64 ++++++----------- src/client/util/SelectionManager.ts | 6 +- src/client/util/SharingManager.tsx | 5 +- src/client/util/TrackMovements.ts | 36 +++++----- src/client/views/DashboardView.tsx | 17 ++--- src/client/views/DocComponent.tsx | 1 - src/client/views/DocumentDecorations.tsx | 8 +-- src/client/views/GestureOverlay.tsx | 4 +- src/client/views/InkStrokeProperties.ts | 3 +- src/client/views/LightboxView.tsx | 4 +- src/client/views/MainView.tsx | 20 ++---- src/client/views/OverlayView.tsx | 10 +-- src/client/views/Palette.tsx | 31 ++++---- src/client/views/PropertiesDocContextSelector.tsx | 22 ++++-- src/client/views/PropertiesView.tsx | 2 - src/client/views/StyleProvider.tsx | 11 ++- src/client/views/TemplateMenu.tsx | 2 - .../views/collections/CollectionCarouselView.tsx | 1 - src/client/views/collections/CollectionMenu.tsx | 6 +- .../views/collections/CollectionNoteTakingView.tsx | 4 -- .../views/collections/CollectionPileView.tsx | 2 +- .../collections/CollectionStackedTimeline.tsx | 2 - .../views/collections/CollectionStackingView.tsx | 4 -- .../views/collections/CollectionTreeView.tsx | 10 +-- src/client/views/collections/CollectionView.tsx | 5 +- src/client/views/collections/TabDocView.tsx | 6 +- src/client/views/collections/TreeView.tsx | 54 ++++++-------- .../collectionFreeForm/CollectionFreeFormView.tsx | 31 ++++---- .../collectionLinear/CollectionLinearView.tsx | 5 +- .../CollectionMulticolumnView.tsx | 2 - .../CollectionMultirowView.tsx | 2 - .../collectionSchema/CollectionSchemaView.tsx | 6 +- .../collections/collectionSchema/SchemaRowBox.tsx | 2 +- .../collectionSchema/SchemaTableCell.tsx | 2 - src/client/views/linking/LinkMenuItem.tsx | 21 +----- src/client/views/linking/LinkPopup.tsx | 4 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 7 +- src/client/views/nodes/DocumentContentsView.tsx | 1 - src/client/views/nodes/DocumentLinksButton.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 12 ++-- src/client/views/nodes/FieldView.tsx | 1 + src/client/views/nodes/KeyValuePair.tsx | 2 - src/client/views/nodes/LinkDocPreview.tsx | 4 +- src/client/views/nodes/ScreenshotBox.tsx | 5 +- src/client/views/nodes/button/FontIconBox.tsx | 4 +- .../views/nodes/formattedText/DashDocView.tsx | 7 +- .../views/nodes/formattedText/DashFieldView.tsx | 5 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 20 ++++-- src/client/views/nodes/trails/PresBox.tsx | 1 - src/client/views/nodes/trails/PresElementBox.tsx | 27 ++++--- src/client/views/topbar/TopBar.tsx | 51 ++----------- src/mobile/AudioUpload.tsx | 76 ++++++++++---------- src/mobile/MobileInterface.tsx | 4 +- 58 files changed, 291 insertions(+), 456 deletions(-) (limited to 'src/client/views/nodes/DocumentLinksButton.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 8d97ce5af..09b45a481 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1285,10 +1285,6 @@ export namespace DocUtils { return rangeFilteredDocs; } - export function DefaultFocus(doc: Doc, options: DocFocusOptions) { - return undefined; - } - export let ActiveRecordings: { props: FieldViewProps; getAnchor: (addAsAnnotation: boolean) => Doc }[] = []; export function MakeLinkToActiveAudio(getSourceDoc: () => Doc | undefined, broadcastEvent = true) { @@ -1299,10 +1295,9 @@ export namespace DocUtils { }); } - export function MakeLink(source: Doc, target: Doc, linkSettings: { linkRelationship?: string; description?: string; linkDisplay?: boolean }, id?: string, allowParCollectionLink?: boolean, showPopup?: number[]) { + export function MakeLink(source: Doc, target: Doc, linkSettings: { linkRelationship?: string; description?: string; linkDisplay?: boolean }, id?: string, showPopup?: number[]) { if (!linkSettings.linkRelationship) linkSettings.linkRelationship = target.type === DocumentType.RTF ? 'Commentary:Comments On' : 'link'; const sv = DocumentManager.Instance.getDocumentView(source); - if (!allowParCollectionLink && sv?.props.ContainingCollectionDoc === target) return; if (target.doc === Doc.UserDoc()) return undefined; const makeLink = action((linkDoc: Doc, showPopup?: number[]) => { @@ -1371,7 +1366,6 @@ export namespace DocUtils { value: 'any', _readOnly_: 'boolean', scriptContext: 'any', - thisContainer: Doc.name, documentView: Doc.name, heading: Doc.name, checked: 'boolean', diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 76ea3e3ea..abf7313a4 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -110,7 +110,7 @@ export class CurrentUserUtils { const tempClicks = DocCast(doc[field]); const reqdClickOpts:DocumentOptions = {_width: 300, _height:200, system: true}; const reqdTempOpts:{opts:DocumentOptions, script: string}[] = [ - { opts: { title: "Open In Target", targetScriptKey: "onChildClick"}, script: "docCast(thisContainer.target).then((target) => target && (target.proto.data = new List([self])))"}, + { opts: { title: "Open In Target", targetScriptKey: "onChildClick"}, script: "docCast(documentView?.props.docViewPath().lastElement()?.rootDoc.target).then((target) => target && (target.proto.data = new List([self])))"}, { opts: { title: "Open Detail On Right", targetScriptKey: "onChildDoubleClick"}, script: `openDoc(self.doubleClickView.${OpenWhere.addRight})`}]; const reqdClickList = reqdTempOpts.map(opts => { const allOpts = {...reqdClickOpts, ...opts.opts}; diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index ccf370662..ad89e8653 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,15 +1,11 @@ -import { loadAsync } from 'jszip'; -import { action, observable, ObservableSet, runInAction } from 'mobx'; +import { action, observable, ObservableSet } from 'mobx'; import { AnimationSym, Doc, Opt } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; import { listSpec } from '../../fields/Schema'; import { Cast, DocCast, StrCast } from '../../fields/Types'; import { AudioField } from '../../fields/URLField'; -import { emptyFunction } from '../../Utils'; import { CollectionViewType } from '../documents/DocumentTypes'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; -import { CollectionFreeFormView } from '../views/collections/collectionFreeForm'; -import { CollectionView } from '../views/collections/CollectionView'; import { TabDocView } from '../views/collections/TabDocView'; import { LightboxView } from '../views/LightboxView'; import { MainView } from '../views/MainView'; @@ -39,7 +35,7 @@ export class DocumentManager { private _viewRenderedCbs: { doc: Doc; func: (dv: DocumentView) => any }[] = []; public AddViewRenderedCb = (doc: Opt, func: (dv: DocumentView) => any) => { if (doc) { - const dv = this.getDocumentViewById(doc[Id]); + const dv = this.getDocumentView(doc); this._viewRenderedCbs.push({ doc, func }); if (dv) { this.callAddViewFuncs(dv); @@ -129,42 +125,24 @@ export class DocumentManager { return this.getDocumentViewsById(doc[Id]); } - public getDocumentViewById(id: string, preferredCollection?: CollectionView): DocumentView | undefined { - if (!id) return undefined; - let toReturn: DocumentView | undefined; - const passes = preferredCollection ? [preferredCollection, undefined] : [undefined]; - - for (const pass of passes) { - Array.from(DocumentManager.Instance.DocumentViews).map(view => { - if (view.rootDoc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { - toReturn = view; - return; - } - }); - if (!toReturn) { - Array.from(DocumentManager.Instance.DocumentViews).map(view => { - const doc = view.rootDoc.proto; - if (doc && doc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { - toReturn = view; - } - }); - } else { - break; - } - } - - return toReturn; - } - - public getDocumentView(toFind: Doc, preferredCollection?: CollectionView): DocumentView | undefined { - const found = + public getDocumentView(toFind: Doc | undefined, preferredCollection?: DocumentView): DocumentView | undefined { + const doc = + // bcz: this was temporary code used to match documents by data url instead of by id. intended only for repairing the DB // Array.from(DocumentManager.Instance.DocumentViews).find( // dv => // ((dv.rootDoc.data as any)?.url?.href && (dv.rootDoc.data as any)?.url?.href === (toFind.data as any)?.url?.href) || // ((DocCast(dv.rootDoc.annotationOn)?.data as any)?.url?.href && (DocCast(dv.rootDoc.annotationOn)?.data as any)?.url?.href === (DocCast(toFind.annotationOn)?.data as any)?.url?.href) // )?.rootDoc ?? toFind; - return this.getDocumentViewById(found[Id], preferredCollection); + const docViewArray = Array.from(DocumentManager.Instance.DocumentViews); + const passes = !doc ? [] : preferredCollection ? [preferredCollection, undefined] : [undefined]; + return passes.reduce( + (pass, toReturn) => + toReturn ?? + docViewArray.filter(view => view.rootDoc === doc).find(view => !pass || view.props.docViewPath().lastElement() === preferredCollection) ?? + docViewArray.filter(view => Doc.GetProto(view.rootDoc) === doc).find(view => !pass || view.props.docViewPath().lastElement() === preferredCollection), + undefined as Opt + ); } public getLightboxDocumentView = (toFind: Doc, originatingDoc: Opt = undefined): DocumentView | undefined => { @@ -247,7 +225,8 @@ export class DocumentManager { public showDocumentView = async (targetDocView: DocumentView, options: DocFocusOptions) => { const docViewPath = targetDocView.docViewPath.slice(); let rootContextView = docViewPath.shift(); - return rootContextView && this.focusViewsInPath(rootContextView, options, async () => ({ childDocView: docViewPath.shift(), viewSpec: undefined })); + await (rootContextView && this.focusViewsInPath(rootContextView, options, async () => ({ childDocView: docViewPath.shift(), viewSpec: undefined }))); + if (options.toggleTarget && (!options.didMove || targetDocView.rootDoc.hidden)) targetDocView.rootDoc.hidden = !targetDocView.rootDoc.hidden; }; // shows a document by first: @@ -318,15 +297,25 @@ export class DocumentManager { } } } -export function DocFocusOrOpen(doc: Doc, collectionDoc?: Doc) { - const cv = collectionDoc && DocumentManager.Instance.getDocumentView(collectionDoc); - const dv = DocumentManager.Instance.getDocumentView(doc, (cv?.ComponentView as CollectionFreeFormView)?.props.CollectionView); - if (dv) { - DocumentManager.Instance.showDocumentView(dv, { willZoomCentered: true }); - } else { - const context = doc.context !== Doc.MyFilesystem && Cast(doc.context, Doc, null); - const showDoc = context || doc; - DocumentManager.Instance.showDocument(Doc.BestAlias(showDoc), { openLocation: OpenWhere.addRight }, () => DocumentManager.Instance.showDocument(doc, { willZoomCentered: true })); - } +export function DocFocusOrOpen(doc: Doc, options: DocFocusOptions = { willZoomCentered: true, openLocation: OpenWhere.addRight }, containingDoc?: Doc) { + const func = () => { + const cv = DocumentManager.Instance.getDocumentView(containingDoc); + const dv = DocumentManager.Instance.getDocumentView(doc, cv); + if (dv && (!containingDoc || dv.props.docViewPath().lastElement()?.Document === containingDoc)) { + DocumentManager.Instance.showDocumentView(dv, options).then(() => dv && Doc.linkFollowHighlight(dv.rootDoc)); + } else { + const showDoc = Doc.BestAlias(DocCast((containingDoc ?? doc.context) !== Doc.MyFilesystem ? containingDoc ?? doc.context : undefined, doc)); + DocumentManager.Instance.showDocument(showDoc, { ...options, toggleTarget: undefined }, () => DocumentManager.Instance.showDocument(doc, options)).then(() => { + const cv = DocumentManager.Instance.getDocumentView(containingDoc); + const dv = DocumentManager.Instance.getDocumentView(doc, cv); + dv && Doc.linkFollowHighlight(dv.rootDoc); + }); + } + }; + if (doc.hidden) { + doc.hidden = false; + options.toggleTarget = false; + setTimeout(func); + } else func(); } ScriptingGlobals.add(DocFocusOrOpen); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 7d2aa813f..7e6de5e67 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -3,10 +3,8 @@ import { DateField } from '../../fields/DateField'; import { Doc, Field, Opt, StrListCast } from '../../fields/Doc'; import { List } from '../../fields/List'; import { PrefetchProxy } from '../../fields/Proxy'; -import { listSpec } from '../../fields/Schema'; -import { SchemaHeaderField } from '../../fields/SchemaHeaderField'; import { ScriptField } from '../../fields/ScriptField'; -import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../fields/Types'; +import { BoolCast, ScriptCast, StrCast } from '../../fields/Types'; import { emptyFunction, Utils } from '../../Utils'; import { Docs, DocUtils } from '../documents/Documents'; import * as globalCssVariables from '../views/global/globalCssVariables.scss'; diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index 559958c2b..76b1323c4 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -14,12 +14,14 @@ import { AcceptableMedia, Upload } from '../../../server/SharedMediaTypes'; import { Utils } from '../../../Utils'; import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { Docs, DocumentOptions, DocUtils } from '../../documents/Documents'; +import { DocumentType } from '../../documents/DocumentTypes'; import { Networking } from '../../Network'; import { FieldView, FieldViewProps } from '../../views/nodes/FieldView'; import { DocumentManager } from '../DocumentManager'; import './DirectoryImportBox.scss'; import ImportMetadataEntry, { keyPlaceholder, valuePlaceholder } from './ImportMetadataEntry'; import React = require('react'); +import _ = require('lodash'); const unsupported = ['text/html', 'text/plain']; @@ -155,8 +157,8 @@ export class DirectoryImportBox extends React.Component { x: NumCast(doc.x), y: NumCast(doc.y) + offset, }; - const parent = this.props.ContainingCollectionView; - if (parent) { + const parent = _.nth(this.props.docViewPath(), -2); // last element of path is this box's document view, 2nd to last is any collection or other document that may contain it. + if (parent?.rootDoc.type === DocumentType.COL) { let importContainer: Doc; if (docs.length < 50) { importContainer = Docs.Create.MasonryDocument(docs, options); diff --git a/src/client/util/ReplayMovements.ts b/src/client/util/ReplayMovements.ts index d5bffc5e2..40261985a 100644 --- a/src/client/util/ReplayMovements.ts +++ b/src/client/util/ReplayMovements.ts @@ -7,6 +7,7 @@ import { CollectionDockingView } from '../views/collections/CollectionDockingVie import { DocServer } from '../DocServer'; import { Movement, Presentation } from './TrackMovements'; import { OpenWhereMod } from '../views/nodes/DocumentView'; +import { returnTransparent } from '../../Utils'; export class ReplayMovements { private timers: NodeJS.Timeout[] | null; @@ -60,17 +61,11 @@ export class ReplayMovements { return; } - let docIdtoDoc: Map = new Map(); - try { - docIdtoDoc = await this.loadPresentation(presentation); - } catch { - console.error('[recordingApi.ts] setVideoBox(): error loading presentation - no replay movements'); - throw 'error loading docs from server'; - } + const docIdtoDoc = this.loadPresentation(presentation); this.videoBoxDisposeFunc = reaction( () => ({ playing: videoBox._playing, timeViewed: videoBox.player?.currentTime || 0 }), - ({ playing, timeViewed }) => (playing ? this.playMovements(presentation, docIdtoDoc, timeViewed) : this.pauseMovements()) + ({ playing, timeViewed }) => (playing ? this.playMovements(presentation, timeViewed) : this.pauseMovements()) ); this.videoBox = videoBox; }; @@ -93,45 +88,33 @@ export class ReplayMovements { this.pauseMovements(); }; - loadPresentation = async (presentation: Presentation) => { + loadPresentation = (presentation: Presentation) => { const { movements } = presentation; if (movements === null) { throw '[recordingApi.ts] followMovements() failed: no presentation data'; } // generate a set of all unique docIds - const docIds = new Set(); - for (const { docId } of movements) { - if (!docIds.has(docId)) docIds.add(docId); - } - - const docIdtoDoc = new Map(); - - let refFields = await DocServer.GetRefFields([...docIds.keys()]); - for (const docId in refFields) { - if (!refFields[docId]) { - throw `one field was undefined`; - } - docIdtoDoc.set(docId, refFields[docId] as Doc); + const docs = new Set(); + for (const { doc } of movements) { + if (!docs.has(doc)) docs.add(doc); } - // console.info('loadPresentation refFields', refFields, docIdtoDoc); - return docIdtoDoc; + return docs; }; // returns undefined if the docView isn't open on the screen - getCollectionFFView = (docId: string) => { - const isInView = DocumentManager.Instance.getDocumentViewById(docId); + getCollectionFFView = (doc: Doc) => { + const isInView = DocumentManager.Instance.getDocumentView(doc); if (isInView) { return isInView.ComponentView as CollectionFreeFormView; } }; // will open the doc in a tab then return the CollectionFFView that holds it - openTab = (docId: string, docIdtoDoc: Map) => { - const doc = docIdtoDoc.get(docId); - if (doc == undefined) { - console.error(`docIdtoDoc did not contain docId ${docId}`); + openTab = (doc: Doc) => { + if (doc === undefined) { + console.error(`doc undefined`); return undefined; } // console.log('openTab', docId, doc); @@ -149,13 +132,12 @@ export class ReplayMovements { document.Document._panY = panY; }; - getFirstMovements = (movements: Movement[]): Map => { + getFirstMovements = (movements: Movement[]): Map => { if (movements === null) return new Map(); // generate a set of all unique docIds - const docIdtoFirstMove = new Map(); + const docIdtoFirstMove = new Map(); for (const move of movements) { - const { docId } = move; - if (!docIdtoFirstMove.has(docId)) docIdtoFirstMove.set(docId, move); + if (!docIdtoFirstMove.has(move.doc)) docIdtoFirstMove.set(move.doc, move); } return docIdtoFirstMove; }; @@ -165,7 +147,7 @@ export class ReplayMovements { Doc.UserDoc().presentationMode = 'none'; }; - public playMovements = (presentation: Presentation, docIdtoDoc: Map, timeViewed: number = 0) => { + public playMovements = (presentation: Presentation, timeViewed: number = 0) => { // console.info('playMovements', presentation, timeViewed, docIdtoDoc); if (presentation.movements === null || presentation.movements.length === 0) { @@ -183,13 +165,13 @@ export class ReplayMovements { const handleFirstMovements = () => { // if the first movement is a closed tab, open it const firstMovement = filteredMovements[0]; - const isClosed = this.getCollectionFFView(firstMovement.docId) === undefined; - if (isClosed) this.openTab(firstMovement.docId, docIdtoDoc); + const isClosed = this.getCollectionFFView(firstMovement.doc) === undefined; + if (isClosed) this.openTab(firstMovement.doc); // for the open tabs, set it to the first move const docIdtoFirstMove = this.getFirstMovements(filteredMovements); - for (const [docId, firstMove] of docIdtoFirstMove) { - const colFFView = this.getCollectionFFView(docId); + for (const [doc, firstMove] of docIdtoFirstMove) { + const colFFView = this.getCollectionFFView(doc); if (colFFView) this.zoomAndPan(firstMove, colFFView); } }; @@ -200,12 +182,12 @@ export class ReplayMovements { const timeDiff = movement.time - timeViewed * 1000; return setTimeout(() => { - const collectionFFView = this.getCollectionFFView(movement.docId); + const collectionFFView = this.getCollectionFFView(movement.doc); if (collectionFFView) { this.zoomAndPan(movement, collectionFFView); } else { // tab wasn't open - open it and play the movement - const openedColFFView = this.openTab(movement.docId, docIdtoDoc); + const openedColFFView = this.openTab(movement.doc); console.log('openedColFFView', openedColFFView); openedColFFView && this.zoomAndPan(movement, openedColFFView); } diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 313c255a0..bfad93334 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -1,4 +1,3 @@ -import { ModalManager } from '@material-ui/core'; import { action, observable, ObservableMap } from 'mobx'; import { computedFn } from 'mobx-utils'; import { Doc, Opt } from '../../fields/Doc'; @@ -64,8 +63,9 @@ export namespace SelectionManager { export function DeselectView(docView?: DocumentView): void { manager.DeselectView(docView); } - export function SelectView(docView: DocumentView, ctrlPressed: boolean): void { - manager.SelectView(docView, ctrlPressed); + export function SelectView(docView: DocumentView | undefined, ctrlPressed: boolean): void { + if (!docView) DeselectAll(); + else manager.SelectView(docView, ctrlPressed); } export function SelectSchemaViewDoc(document: Opt, deselectAllFirst?: boolean): void { if (deselectAllFirst) manager.DeselectAll(); diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 3c05af4bb..a73eda04c 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -370,11 +370,10 @@ export class SharingManager extends React.Component<{}> { const docs = SelectionManager.Views().length > 1 ? SelectionManager.Views().map(docView => docView.props.Document) : [this.targetDoc]; return ( { - let context: Opt; - if (this.targetDoc && this.targetDocView && docs.length === 1 && (context = this.targetDocView.props.ContainingCollectionView)) { + if (this.targetDoc && this.targetDocView && docs.length === 1) { DocumentManager.Instance.showDocument(this.targetDoc, { willZoomCentered: true }); } }} diff --git a/src/client/util/TrackMovements.ts b/src/client/util/TrackMovements.ts index 4a2ccd706..2f16307b3 100644 --- a/src/client/util/TrackMovements.ts +++ b/src/client/util/TrackMovements.ts @@ -9,7 +9,7 @@ export type Movement = { panX: number; panY: number; scale: number; - docId: string; + doc: Doc; }; export type Presentation = { @@ -28,7 +28,7 @@ export class TrackMovements { private tracking: boolean; private absoluteStart: number; // instance variable for holding the FFViews and their disposers - private recordingFFViews: Map | null; + private recordingFFViews: Map | null; private tabChangeDisposeFunc: IReactionDisposer | null; // create static instance and getter for global use @@ -55,33 +55,33 @@ export class TrackMovements { return this.currentPresentation.movements === null; } - private addRecordingFFView(doc: Doc, key: string = doc[Id]): void { + private addRecordingFFView(doc: Doc): void { // console.info('adding dispose func : docId', key, 'doc', doc); if (this.recordingFFViews === null) { console.warn('addFFView on null RecordingApi'); return; } - if (this.recordingFFViews.has(key)) { - console.warn('addFFView : key already in map'); + if (this.recordingFFViews.has(doc)) { + console.warn('addFFView : doc already in map'); return; } const disposeFunc = reaction( () => ({ x: NumCast(doc.panX, -1), y: NumCast(doc.panY, -1), scale: NumCast(doc.viewScale, 0) }), - res => res.x !== -1 && res.y !== -1 && this.tracking && this.trackMovement(res.x, res.y, key, res.scale) + res => res.x !== -1 && res.y !== -1 && this.tracking && this.trackMovement(res.x, res.y, doc, res.scale) ); - this.recordingFFViews?.set(key, disposeFunc); + this.recordingFFViews?.set(doc, disposeFunc); } - private removeRecordingFFView = (key: string) => { + private removeRecordingFFView = (doc: Doc) => { // console.info('removing dispose func : docId', key); if (this.recordingFFViews === null) { console.warn('removeFFView on null RecordingApi'); return; } - this.recordingFFViews.get(key)?.(); - this.recordingFFViews.delete(key); + this.recordingFFViews.get(doc)?.(); + this.recordingFFViews.delete(doc); }; // in the case where only one tab was changed (updates not across dashboards), set only one to true @@ -90,15 +90,15 @@ export class TrackMovements { // so that the size comparisons are correct, we must filter to only the FFViews const isFFView = (doc: Doc) => doc && 'viewType' in doc && doc.viewType === 'freeform'; - const tabbedFFViews = new Set(); + const tabbedFFViews = new Set(); for (const DashDoc of tabbedDocs) { - if (isFFView(DashDoc)) tabbedFFViews.add(DashDoc[Id]); + if (isFFView(DashDoc)) tabbedFFViews.add(DashDoc); } // new tab was added - need to add it if (tabbedFFViews.size > this.recordingFFViews.size) { for (const DashDoc of tabbedDocs) { - if (!this.recordingFFViews.has(DashDoc[Id])) { + if (!this.recordingFFViews.has(DashDoc)) { if (isFFView(DashDoc)) { this.addRecordingFFView(DashDoc); @@ -110,9 +110,9 @@ export class TrackMovements { } // tab was removed - need to remove it from recordingFFViews else if (tabbedFFViews.size < this.recordingFFViews.size) { - for (const [key] of this.recordingFFViews) { - if (!tabbedFFViews.has(key)) { - this.removeRecordingFFView(key); + for (const [doc] of this.recordingFFViews) { + if (!tabbedFFViews.has(doc)) { + this.removeRecordingFFView(doc); if (onlyOne) return; } } @@ -214,7 +214,7 @@ export class TrackMovements { } }; - private trackMovement = (panX: number, panY: number, docId: string, scale: number = 0) => { + private trackMovement = (panX: number, panY: number, doc: Doc, scale: number = 0) => { // ensure we are recording to track if (!this.tracking) { console.error('[recordingApi.ts] trackMovements(): tracking is false'); @@ -231,7 +231,7 @@ export class TrackMovements { // get the time const time = new Date().getTime() - this.absoluteStart; // make new movement object - const movement: Movement = { time, panX, panY, scale, docId }; + const movement: Movement = { time, panX, panY, scale, doc }; // add that movement to the current presentation data's movement array this.currentPresentation.movements && this.currentPresentation.movements.push(movement); diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index 2b586b0e2..dee161931 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -109,17 +109,8 @@ export class DashboardView extends React.Component { />
-
); @@ -163,7 +154,7 @@ export class DashboardView extends React.Component {
-
this.selectDashboardGroup(DashboardGroup.MyDashboards)}> My Dashboards @@ -196,7 +187,7 @@ export class DashboardView extends React.Component { e.stopPropagation(); this.onContextMenu(dashboard, e); }}> - } /> +
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 9fc1487a0..a59189fd2 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -52,7 +52,6 @@ export function DocComponent

() { interface ViewBoxBaseProps { Document: Doc; DataDoc?: Doc; - ContainingCollectionDoc: Opt; DocumentView?: () => DocumentView; fieldKey: string; isSelected: (outsideReaction?: boolean) => boolean; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 9ffbe083f..9a4aaf00e 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -33,6 +33,7 @@ import { ImageBox } from './nodes/ImageBox'; import React = require('react'); import { RichTextField } from '../../fields/RichTextField'; import { LinkFollower } from '../util/LinkFollower'; +import _ = require('lodash'); @observer export class DocumentDecorations extends React.Component<{ PanelWidth: number; PanelHeight: number; boundsLeft: number; boundsTop: number }, { value: string }> { @@ -303,8 +304,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P SelectionManager.DeselectAll(); }; - onSelectorClick = () => SelectionManager.Views()?.[0]?.props.ContainingCollectionView?.props.select(false); - + onSelectorClick = () => SelectionManager.Views()?.[0]?.props.docViewPath?.().lastElement()?.select(false); /** * Handles setting up events when user clicks on the border radius editor * @param e PointerEvent @@ -744,7 +744,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P seldocview.props.hideDeleteButton || seldocview.rootDoc.hideDeleteButton || SelectionManager.Views().some(docView => { - const collectionAcl = docView.props.ContainingCollectionView ? GetEffectiveAcl(docView.props.ContainingCollectionDoc?.[DataSym]) : AclEdit; + const collectionAcl = docView.props.docViewPath()?.lastElement() ? GetEffectiveAcl(docView.props.docViewPath().lastElement().rootDoc[DataSym]) : AclEdit; return docView.rootDoc.stayInCollection || (collectionAcl !== AclAdmin && collectionAcl !== AclEdit && GetEffectiveAcl(docView.rootDoc) !== AclAdmin); }); @@ -865,7 +865,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P

e.preventDefault()} />
e.preventDefault()} /> - {seldocview.props.renderDepth <= 1 || !seldocview.props.ContainingCollectionView ? null : topBtn('selector', 'arrow-alt-circle-up', undefined, this.onSelectorClick, 'tap to select containing document')} + {seldocview.props.renderDepth <= 1 || !seldocview.props.docViewPath().lastElement() ? null : topBtn('selector', 'arrow-alt-circle-up', undefined, this.onSelectorClick, 'tap to select containing document')} )} {useRounding && ( diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 0feccb742..13faae783 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -1010,14 +1010,12 @@ export class GestureOverlay extends Touchable { renderDepth={0} styleProvider={returnEmptyString} docViewPath={returnEmptyDoclist} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} docRangeFilters={returnEmptyFilter} docFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} /> ); }; diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts index e6df0801c..156825f41 100644 --- a/src/client/views/InkStrokeProperties.ts +++ b/src/client/views/InkStrokeProperties.ts @@ -373,10 +373,11 @@ export class InkStrokeProperties { snapToAllCurves = (screenDragPt: { X: number; Y: number }, inkView: DocumentView, snapData: { nearestPt: { X: number; Y: number }; distance: number }, ink: InkData, controlIndex: number) => { const containingCollection = inkView.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView; + const containingDocView = inkView.props.CollectionFreeFormDocumentView?.().props.DocumentView?.(); containingCollection?.childDocs .filter(doc => doc.type === DocumentType.INK) .forEach(doc => { - const testInkView = DocumentManager.Instance.getDocumentView(doc, containingCollection?.props.CollectionView); + const testInkView = DocumentManager.Instance.getDocumentView(doc, containingDocView); const snapped = testInkView?.ComponentView?.snapPt?.(screenDragPt, doc === inkView.rootDoc ? this.excludeSelfSnapSegs(ink, controlIndex) : []); if (snapped && snapped.distance < snapData.distance) { const snappedInkPt = doc === inkView.rootDoc ? snapped.nearestPt : inkView.ComponentView?.ptFromScreen?.(testInkView?.ComponentView?.ptToScreen?.(snapped.nearestPt) ?? { X: 0, Y: 0 }); // convert from snapped ink coordinate system to dragged ink coordinate system by converting to/from screen space diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index 976c8763e..69eec8456 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -266,8 +266,6 @@ export class LightboxView extends React.Component { docFilters={this.docFilters} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} addDocument={undefined} removeDocument={undefined} whenChildContentsActiveChanged={emptyFunction} @@ -275,7 +273,7 @@ export class LightboxView extends React.Component { pinToPres={TabDocView.PinDoc} bringToFront={emptyFunction} onBrowseClick={MainView.Instance.exploreMode} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} />
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 60459cf30..0384d925e 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -595,14 +595,12 @@ export class MainView extends React.Component { PanelWidth={this.headerBarDocWidth} PanelHeight={this.headerBarDocHeight} renderDepth={0} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} />
); @@ -626,14 +624,12 @@ export class MainView extends React.Component { ScreenToLocalTransform={this._hideUI ? this.mainScreenToLocalXf : Transform.Identity} PanelWidth={this.mainDocViewWidth} PanelHeight={this.mainDocViewHeight} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} suppressSetHeight={true} renderDepth={this._hideUI ? 0 : -1} /> @@ -727,14 +723,12 @@ export class MainView extends React.Component { renderDepth={0} isContentActive={returnTrue} scriptContext={CollectionDockingView.Instance?.props.Document} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} /> {this.docButtons} @@ -758,7 +752,7 @@ export class MainView extends React.Component { PanelHeight={this.leftMenuHeight} renderDepth={0} docViewPath={returnEmptyDoclist} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} styleProvider={DefaultStyleProvider} isContentActive={returnTrue} whenChildContentsActiveChanged={emptyFunction} @@ -766,8 +760,6 @@ export class MainView extends React.Component { docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} scriptContext={this} /> @@ -900,13 +892,11 @@ export class MainView extends React.Component { PanelWidth={this.leftMenuFlyoutWidth} PanelHeight={this.leftMenuFlyoutHeight} renderDepth={0} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} /> {['watching', 'recording'].includes(String(this.userDoc?.presentationMode) ?? '') ?
{StrCast(this.userDoc?.presentationMode)}
: <>} diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index ec22128d4..bdc48d03a 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -1,4 +1,4 @@ -import { action, computed, observable, trace } from 'mobx'; +import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; @@ -10,15 +10,13 @@ import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, retu import { DocUtils } from '../documents/Documents'; import { DocumentType } from '../documents/DocumentTypes'; import { DragManager } from '../util/DragManager'; -import { ScriptingGlobals } from '../util/ScriptingGlobals'; import { Transform } from '../util/Transform'; import { CollectionFreeFormLinksView } from './collections/collectionFreeForm/CollectionFreeFormLinksView'; import { LightboxView } from './LightboxView'; import { MainView } from './MainView'; import { DocumentView } from './nodes/DocumentView'; import './OverlayView.scss'; -import { ScriptingRepl } from './ScriptingRepl'; -import { DefaultStyleProvider, testDocProps } from './StyleProvider'; +import { DefaultStyleProvider } from './StyleProvider'; export type OverlayDisposer = () => void; @@ -223,7 +221,7 @@ export class OverlayView extends React.Component { isDocumentActive={returnTrue} isContentActive={returnTrue} whenChildContentsActiveChanged={emptyFunction} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} styleProvider={DefaultStyleProvider} docViewPath={returnEmptyDoclist} addDocTab={d.type === DocumentType.PRES ? MainView.addDocTabFunc : returnFalse} @@ -231,8 +229,6 @@ export class OverlayView extends React.Component { docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} /> ); diff --git a/src/client/views/Palette.tsx b/src/client/views/Palette.tsx index 954529bc9..3ad28c418 100644 --- a/src/client/views/Palette.tsx +++ b/src/client/views/Palette.tsx @@ -1,12 +1,12 @@ -import { IReactionDisposer, observable, reaction } from "mobx"; -import { observer } from "mobx-react"; -import * as React from "react"; -import { Doc } from "../../fields/Doc"; -import { NumCast } from "../../fields/Types"; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, emptyPath } from "../../Utils"; -import { Transform } from "../util/Transform"; -import { DocumentView } from "./nodes/DocumentView"; -import "./Palette.scss"; +import { IReactionDisposer, observable, reaction } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { Doc } from '../../fields/Doc'; +import { NumCast } from '../../fields/Types'; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, emptyPath } from '../../Utils'; +import { Transform } from '../util/Transform'; +import { DocumentView } from './nodes/DocumentView'; +import './Palette.scss'; export interface PaletteProps { x: number; @@ -23,20 +23,20 @@ export default class Palette extends React.Component { componentDidMount = () => { this._selectedDisposer = reaction( () => NumCast(this.props.thumbDoc.selectedIndex), - (i) => this._selectedIndex = i, + i => (this._selectedIndex = i), { fireImmediately: true } ); - } + }; componentWillUnmount = () => { this._selectedDisposer?.(); - } + }; render() { return (
-
+
{ docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} /> + />
); } -} \ No newline at end of file +} diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx index 2c7da5931..93eec61f3 100644 --- a/src/client/views/PropertiesDocContextSelector.tsx +++ b/src/client/views/PropertiesDocContextSelector.tsx @@ -22,9 +22,9 @@ export class PropertiesDocContextSelector extends React.Component alias.context && alias.context instanceof Doc && Cast(alias.context, Doc, null) !== targetContext).reduce((set, alias) => set.add(Cast(alias.context, Doc, null)), new Set()); + const containerProtos = aliases.filter(alias => alias.context && alias.context instanceof Doc).reduce((set, alias) => set.add(Cast(alias.context, Doc, null)), new Set()); const containerSets = Array.from(containerProtos.keys()).map(container => DocListCast(container.aliases)); const containers = containerSets.reduce((p, set) => { set.map(s => p.add(s)); @@ -42,6 +42,7 @@ export class PropertiesDocContextSelector extends React.Component !Doc.AreProtosEqual(doc, CollectionDockingView.Instance?.props.Document)) .filter(doc => !Doc.IsSystem(doc)) + .filter(doc => doc !== targetContext) .map(doc => ({ col: doc, target })); } @@ -53,8 +54,21 @@ export class PropertiesDocContextSelector extends React.Component DocFocusOrOpen(Doc.GetProto(this.props.DocView!.props.Document), col), 100); + //this.props.addDocTab(col, (OpenWhere.toggle + ':' + OpenWhereMod.right) as OpenWhere); + setTimeout( + () => + this.props.DocView && + DocFocusOrOpen( + Doc.GetProto(this.props.DocView.props.Document), + { + // + willZoomCentered: true, + openLocation: (OpenWhere.toggle + ':' + OpenWhereMod.right) as OpenWhere, + }, + col + ), + 100 + ); }; render() { diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index fbc7d7696..6582c3f2a 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -341,8 +341,6 @@ export class PropertiesView extends React.Component { docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionDoc={undefined} - ContainingCollectionView={undefined} addDocument={returnFalse} moveDocument={undefined} removeDocument={returnFalse} diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index b950b4860..739d6d819 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -18,7 +18,7 @@ import { TreeSort } from './collections/TreeView'; import { Colors } from './global/globalEnums'; import { InkingStroke } from './InkingStroke'; import { MainView } from './MainView'; -import { DocumentViewProps } from './nodes/DocumentView'; +import { DocumentViewProps, OpenWhere } from './nodes/DocumentView'; import { FieldViewProps } from './nodes/FieldView'; import { KeyValueBox } from './nodes/KeyValueBox'; import { SliderBox } from './nodes/SliderBox'; @@ -295,7 +295,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt, props: Opt { - if (props?.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform) { + if (props?.docViewPath().lastElement()?.rootDoc?._viewType === CollectionViewType.Freeform) { return doc?.pointerEvents !== 'none' ? null : (
toggleLockedPosition(doc)}> @@ -383,10 +383,7 @@ export function DashboardStyleProvider(doc: Opt, props: Opt {DashboardToggleButton(doc, 'hidden', 'eye-slash', 'eye', () => { - doc.hidden = doc.hidden ? undefined : true; - if (!doc.hidden) { - DocFocusOrOpen(doc, props?.ContainingCollectionDoc); - } + DocFocusOrOpen(doc, { toggleTarget: true, willPan: true, openLocation: OpenWhere.addRight }, props?.docViewPath().lastElement()?.rootDoc); })} ); diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 45db240a9..c5a501aa6 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -114,8 +114,6 @@ export class TemplateMenu extends React.Component { { docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} />
); @@ -642,8 +640,8 @@ export class CollectionViewBaseChrome extends React.Component this.props.docView.props.CollectionFreeFormDocumentView?.().float())}> diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index aec0734b4..80e81bc1c 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -255,8 +255,6 @@ export class CollectionNoteTakingView extends CollectionSubView() { hideTitle={this.props.childHideTitle?.()} docRangeFilters={this.childDocRangeFilters} searchFilterDocs={this.searchFilterDocs} - ContainingCollectionDoc={this.props.CollectionView?.props.Document} - ContainingCollectionView={this.props.CollectionView} addDocument={this.props.addDocument} moveDocument={this.props.moveDocument} removeDocument={this.props.removeDocument} @@ -632,8 +630,6 @@ export class CollectionNoteTakingView extends CollectionSubView() { docFilters={this.props.docFilters} docRangeFilters={this.props.docRangeFilters} searchFilterDocs={this.props.searchFilterDocs} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} />
); diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx index ba90ed8cd..fd9b0c0ce 100644 --- a/src/client/views/collections/CollectionPileView.tsx +++ b/src/client/views/collections/CollectionPileView.tsx @@ -30,7 +30,7 @@ export class CollectionPileView extends CollectionSubView() { // pileups are designed to go away when they are empty. this._disposers.selected = reaction( () => this.childDocs.length, - num => !num && this.props.ContainingCollectionView?.removeDocument(this.props.Document) + num => !num && this.props.CollectionFreeFormDocumentView?.().props.removeDocument?.(this.props.Document) ); } componentWillUnmount() { diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index bbd81d06d..22a575989 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -815,8 +815,6 @@ class StackedTimelineAnchor extends React.Component whenChildContentsActiveChanged={emptyFunction} focus={focusFunc} isContentActive={returnFalse} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} searchFilterDocs={returnEmptyDoclist} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index a85ee0e02..67f5dc9f4 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -346,8 +346,6 @@ export class CollectionStackingView extends CollectionSubView ); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 4a11e8f0b..92932fb61 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -164,7 +164,7 @@ export class CollectionTreeView extends CollectionSubView 0) { FormattedTextBox.SelectOnLoad = prev[Id]; - DocumentManager.Instance.getDocumentView(prev, this.props.CollectionView)?.select(false); + DocumentManager.Instance.getDocumentView(prev, this.props.DocumentView?.())?.select(false); } return true; } @@ -242,8 +242,6 @@ export class CollectionTreeView extends CollectionSubView ); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index bc25ad43a..53fbcc3cc 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -279,7 +279,10 @@ export class CollectionView extends ViewBoxAnnotatableComponent +
{this.showIsTagged()} {this.renderSubView(this.collectionViewType, props)}
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 458712999..ef8f395c5 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -425,8 +425,6 @@ export class TabDocView extends React.Component { hideTitle={this.props.keyValue} Document={this._document} DataDoc={!Doc.AreProtosEqual(this._document[DataSym], this._document) ? this._document[DataSym] : undefined} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} onBrowseClick={MainView.Instance.exploreMode} waitForDoubleClickToClick={MainView.Instance.waitForDoubleClick} isContentActive={returnTrue} @@ -580,8 +578,6 @@ export class TabMinimapView extends React.Component { { ScreenToLocalTransform={Transform.Identity} renderDepth={0} whenChildContentsActiveChanged={emptyFunction} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} styleProvider={TabMinimapView.miniStyleProvider} addDocTab={this.props.addDocTab} pinToPres={TabDocView.PinDoc} diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 75e76019e..8b1dfc767 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -42,7 +42,7 @@ export interface TreeViewProps { prevSibling?: Doc; document: Doc; dataDoc?: Doc; - containerCollection: Doc; + treeViewParent: Doc; renderDepth: number; dropAction: dropActionType; addDocTab: (doc: Doc, where: OpenWhere) => boolean; @@ -143,7 +143,7 @@ export class TreeView extends React.Component { return this.validExpandViewTypes.includes(StrCast(this.doc.treeViewExpandedView)) ? StrCast(this.doc.treeViewExpandedView) : this.defaultExpandedView; } @computed get MAX_EMBED_HEIGHT() { - return NumCast(this.props.containerCollection.maxEmbedHeight, 200); + return NumCast(this.props.treeViewParent.maxEmbedHeight, 200); } @computed get dataDoc() { return this.props.document.treeViewChildrenOnRoot ? this.doc : this.doc[DataSym]; @@ -194,7 +194,7 @@ export class TreeView extends React.Component { const ind = this.dataDoc[key].indexOf(doc); const res = (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true); - res && ind > 0 && DocumentManager.Instance.getDocumentView(this.dataDoc[key][ind - 1], this.props.treeView.props.CollectionView)?.select(false); + res && ind > 0 && DocumentManager.Instance.getDocumentView(this.dataDoc[key][ind - 1], this.props.treeView.props.DocumentView?.())?.select(false); return res; }; @@ -385,7 +385,7 @@ export class TreeView extends React.Component { }; const addDoc = inside ? localAdd : parentAddDoc; const move = (!dropAction || dropAction === 'proto' || dropAction === 'move' || dropAction === 'same') && moveDocument; - const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.containerCollection)?.freezeChildren).includes('add')) || forceAdd; + const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.treeViewParent)?.freezeChildren).includes('add')) || forceAdd; if (canAdd) { this.props.parentTreeView instanceof TreeView && (this.props.parentTreeView.dropping = true); const res = UndoManager.RunInTempBatch(() => droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === 'proto' ? addDoc(d) : false) : addDoc(d)) || added, false)); @@ -406,7 +406,7 @@ export class TreeView extends React.Component { getTransform = () => this.refTransform(this._tref.current); embeddedPanelWidth = () => this.props.panelWidth() / (this.props.treeView.props.NativeDimScaling?.() || 1); embeddedPanelHeight = () => { - const layoutDoc = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document, ''))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc; + const layoutDoc = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc; return Math.min( layoutDoc[HeightSym](), this.MAX_EMBED_HEIGHT, @@ -416,7 +416,7 @@ export class TreeView extends React.Component { return layoutDoc._fitWidth ? !Doc.NativeHeight(layoutDoc) ? NumCast(layoutDoc._height) - : Math.min((this.embeddedPanelWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc))) / (Doc.NativeWidth(layoutDoc) || NumCast(this.props.containerCollection._height))) + : Math.min((this.embeddedPanelWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc))) / (Doc.NativeWidth(layoutDoc) || NumCast(this.props.treeViewParent._height))) : (this.embeddedPanelWidth() * layoutDoc[HeightSym]()) / layoutDoc[WidthSym](); })() ); @@ -452,7 +452,7 @@ export class TreeView extends React.Component { this, doc, undefined, - this.props.containerCollection, + this.props.treeViewParent, this.props.prevSibling, addDoc, remDoc, @@ -596,7 +596,7 @@ export class TreeView extends React.Component { this, this.layoutDoc, this.dataDoc, - this.props.containerCollection, + this.props.treeViewParent, this.props.prevSibling, addDoc, remDoc, @@ -656,7 +656,7 @@ export class TreeView extends React.Component { this.onCheckedClick?.script.run( { this: this.doc.isTemplateForField && this.props.dataDoc ? this.props.dataDoc : this.doc, - heading: this.props.containerCollection.title, + heading: this.props.treeViewParent.title, checked: this.doc.treeViewChecked === 'check' ? 'x' : this.doc.treeViewChecked === 'x' ? 'remove' : 'check', containingTreeView: this.props.treeView.props.Document, }, @@ -724,9 +724,11 @@ export class TreeView extends React.Component { }; @observable headerEleWidth = 0; - @computed get headerElements() { + @computed get titleButtons() { + const customHeaderButtons = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.Decorations); return this.props.treeViewHideHeaderFields() || this.doc.treeViewHideHeaderFields ? null : ( <> + {customHeaderButtons} {/* e.g.,. hide button is set by dashboardStyleProvider */} {this.doc.hideContextMenu ? null : ( { return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label })); }; - onChildClick = () => { - return this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!); - }; + onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!); onChildDoubleClick = () => ScriptCast(this.props.treeView.Document.treeViewChildDoubleClick, !this.props.treeView.outlineMode ? this._openScript?.() : null); @@ -906,7 +906,7 @@ export class TreeView extends React.Component { styleProvider={this.titleStyleProvider} enableDragWhenActive={true} onClickScriptDisable="never" // tree docViews have a script to show fields, etc. - docViewPath={returnEmptyDoclist} + docViewPath={this.props.treeView.props.docViewPath} treeViewDoc={this.props.treeView.props.Document} addDocument={undefined} addDocTab={this.props.addDocTab} @@ -937,12 +937,8 @@ export class TreeView extends React.Component { docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={this.props.treeView.props.CollectionView} - ContainingCollectionDoc={this.props.treeView.props.Document} /> ); - - const buttons = this.props.styleProvider?.(this.doc, { ...this.props.treeView.props, ContainingCollectionDoc: this.props.parentTreeView?.doc }, StyleProp.Decorations + (Doc.IsSystem(this.props.containerCollection) ? ':afterHeader' : '')); return ( <>
{ {view}
r && (this.headerEleWidth = r.getBoundingClientRect().width))}> - {buttons} {/* hide and lock buttons */} - {this.headerElements} + {this.titleButtons}
); @@ -1017,8 +1012,6 @@ export class TreeView extends React.Component { docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionDoc={this.props.containerCollection} - ContainingCollectionView={undefined} addDocument={this.props.addDocument} moveDocument={this.move} removeDocument={this.props.removeDoc} @@ -1131,7 +1124,7 @@ export class TreeView extends React.Component { childDocs: Doc[], treeView: CollectionTreeView, parentTreeView: CollectionTreeView | TreeView | undefined, - containerCollection: Doc, + treeViewParent: Doc, dataDoc: Doc | undefined, parentCollectionDoc: Doc | undefined, containerPrevSibling: Doc | undefined, @@ -1162,19 +1155,19 @@ export class TreeView extends React.Component { hierarchyIndex?: number[], renderCount?: number ) { - const viewSpecScript = Cast(containerCollection.viewSpecScript, ScriptField); + const viewSpecScript = Cast(treeViewParent.viewSpecScript, ScriptField); if (viewSpecScript) { childDocs = childDocs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result); } - const docs = TreeView.sortDocs(childDocs, StrCast(containerCollection.treeViewSortCriterion, TreeSort.None)); + const docs = TreeView.sortDocs(childDocs, StrCast(treeViewParent.treeViewSortCriterion, TreeSort.None)); const rowWidth = () => panelWidth() - treeBulletWidth() * (treeView.props.NativeDimScaling?.() || 1); const treeViewRefs = new Map(); return docs .filter(child => child instanceof Doc) .map((child, i) => { if (renderCount && i > renderCount) return null; - const pair = Doc.GetLayoutDataDocPair(containerCollection, dataDoc, child); + const pair = Doc.GetLayoutDataDocPair(treeViewParent, dataDoc, child); if (!pair.layout || pair.data instanceof Promise) { return null; } @@ -1192,10 +1185,7 @@ export class TreeView extends React.Component { } }; const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeViewRefs.get(docs[i - 1])); - const outdent = - parentCollectionDoc?._viewType !== CollectionViewType.Tree - ? undefined - : (editTitle: boolean) => dentDoc(editTitle, parentCollectionDoc, containerPrevSibling, parentTreeView instanceof TreeView ? parentTreeView.props.parentTreeView : undefined); + const outdent = !parentCollectionDoc ? undefined : (editTitle: boolean) => dentDoc(editTitle, parentCollectionDoc, containerPrevSibling, parentTreeView instanceof TreeView ? parentTreeView.props.parentTreeView : undefined); const addDocument = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => add(doc, relativeTo ?? docs[i], before !== undefined ? before : false); const childLayout = Doc.Layout(pair.layout); const rowHeight = () => { @@ -1208,7 +1198,7 @@ export class TreeView extends React.Component { ref={r => treeViewRefs.set(child, r ? r : undefined)} document={pair.layout} dataDoc={pair.data} - containerCollection={containerCollection} + treeViewParent={treeViewParent} prevSibling={docs[i]} // TODO: [AL] add these hierarchyIndex={hierarchyIndex ? [...hierarchyIndex, i + 1] : undefined} @@ -1220,7 +1210,7 @@ export class TreeView extends React.Component { onCheckedClick={onCheckedClick} onChildClick={onChildClick} renderDepth={renderDepth} - removeDoc={StrCast(containerCollection.freezeChildren).includes('remove') ? undefined : remove} + removeDoc={StrCast(treeViewParent.freezeChildren).includes('remove') ? undefined : remove} addDocument={addDocument} styleProvider={styleProvider} panelWidth={rowWidth} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 7ae7be3c8..a3f5e73fb 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -262,7 +262,7 @@ export class CollectionFreeFormView extends CollectionSubView { SelectionManager.DeselectAll(); - docs.map(doc => DocumentManager.Instance.getDocumentView(doc, this.props.CollectionView)).map(dv => dv && SelectionManager.SelectView(dv, true)); + docs.map(doc => DocumentManager.Instance.getDocumentView(doc, this.props.DocumentView?.())).map(dv => dv && SelectionManager.SelectView(dv, true)); }; addDocument = (newBox: Doc | Doc[]) => { let retVal = false; @@ -319,7 +319,7 @@ export class CollectionFreeFormView extends CollectionSubView 1 ? NumCast(refDoc.y) - (NumCast(sorted[0].layout.y) + (topIndexed ? 0 : NumCast(sorted[0].layout._height))) : 0; const deltax = sorted.length > 1 ? NumCast(refDoc.x) - NumCast(sorted[0].layout.x) : 0; let lastx = NumCast(refDoc.x); let lasty = NumCast(refDoc.y) + (topIndexed ? 0 : NumCast(refDoc._height)); - setTimeout( - action(() => - sorted.slice(1).forEach((pair, i) => { - lastx = pair.layout.x = lastx + deltax; - lasty = (pair.layout.y = lasty + deltay) + (topIndexed ? 0 : NumCast(pair.layout._height)); - }) - ) + runInAction(() => + sorted.slice(1).forEach((pair, i) => { + lastx = pair.layout.x = lastx + deltax; + lasty = (pair.layout.y = lasty + deltay) + (topIndexed ? 0 : NumCast(pair.layout._height)); + }) ); } } @@ -464,7 +462,7 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout).filter(cd => (this.props.Document._useClusters ? NumCast(cd.cluster) : NumCast(cd.group, -1)) === cluster); - const clusterDocs = eles.map(ele => DocumentManager.Instance.getDocumentView(ele, this.props.CollectionView)!); + const clusterDocs = eles.map(ele => DocumentManager.Instance.getDocumentView(ele, this.props.DocumentView?.())!); const { left, top } = clusterDocs[0].getBounds() || { left: 0, top: 0 }; const de = new DragManager.DocumentDragData(eles, e.ctrlKey || e.altKey ? 'alias' : undefined); de.moveDocument = this.props.moveDocument; @@ -872,7 +870,7 @@ export class CollectionFreeFormView extends CollectionSubView DocumentManager.Instance.getDocumentView(doc, this.props.CollectionView)) + .map(doc => DocumentManager.Instance.getDocumentView(doc, this.props.DocumentView?.())) .filter(inkView => inkView?.ComponentView instanceof InkingStroke) .map(inkView => ({ inkViewBounds: inkView!.getBounds(), inkStroke: inkView!.ComponentView as InkingStroke, inkView: inkView! })) .filter( @@ -966,7 +964,7 @@ export class CollectionFreeFormView extends CollectionSubView doc.type === DocumentType.INK && !doc.dontIntersect) .forEach(doc => { - const otherInk = DocumentManager.Instance.getDocumentView(doc, this.props.CollectionView)?.ComponentView as InkingStroke; + const otherInk = DocumentManager.Instance.getDocumentView(doc, this.props.DocumentView?.())?.ComponentView as InkingStroke; const { inkData: otherInkData } = otherInk?.inkScaledData() ?? { inkData: [] }; const otherScreenPts = otherInkData.map(point => otherInk.ptToScreen(point)); const otherCtrlPts = otherScreenPts.map(spt => (ink.ComponentView as InkingStroke).ptFromScreen(spt)); @@ -1121,7 +1119,8 @@ export class CollectionFreeFormView extends CollectionSubView { - if (this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform || this.props.ContainingCollectionDoc._panX !== undefined) { + const collectionDoc = this.props.docViewPath().lastElement().rootDoc; + if (collectionDoc?._viewType !== CollectionViewType.Freeform || collectionDoc._panX !== undefined) { this.setPan( NumCast(this.layoutDoc[this.panXFieldKey]) + ((this.props.PanelWidth() / 2) * x) / this.zoomScaling(), // nudge x,y as a function of panel dimension and scale NumCast(this.layoutDoc[this.panYFieldKey]) + ((this.props.PanelHeight() / 2) * -y) / this.zoomScaling(), @@ -1256,8 +1255,6 @@ export class CollectionFreeFormView extends CollectionSubView @@ -251,8 +249,7 @@ export class CollectionLinearView extends CollectionSubView() { self: this.rootDoc, _readOnly_: false, scriptContext: this.props.scriptContext, - thisContainer: this.props.ContainingCollectionDoc, - documentView: this.props.docViewPath().lastElement(), + documentView: this.props.DocumentView?.(), }); this.layoutDoc.linearViewIsExpanded = this.addMenuToggle.current!.checked; })} diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index b73b1d779..78d3d1b6e 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -262,8 +262,6 @@ export class CollectionMulticolumnView extends CollectionSubView() { docFilters={this.childDocFilters} docRangeFilters={this.childDocRangeFilters} searchFilterDocs={this.searchFilterDocs} - ContainingCollectionDoc={this.props.CollectionView?.props.Document} - ContainingCollectionView={this.props.CollectionView} dontRegisterView={this.props.dontRegisterView} addDocument={this.props.addDocument} moveDocument={this.props.moveDocument} diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index 0cca83803..4d61dc272 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -261,8 +261,6 @@ export class CollectionMultirowView extends CollectionSubView() { docFilters={this.childDocFilters} docRangeFilters={this.childDocRangeFilters} searchFilterDocs={this.searchFilterDocs} - ContainingCollectionDoc={this.props.CollectionView?.props.Document} - ContainingCollectionView={this.props.CollectionView} dontRegisterView={this.props.dontRegisterView} addDocument={this.props.addDocument} moveDocument={this.props.moveDocument} diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index fd9bcf681..6d5a73e55 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -793,7 +793,7 @@ export class CollectionSchemaView extends CollectionSubView() { fitContentsToBox={returnTrue} dontCenter={'y'} onClickScriptDisable="always" - focus={DocUtils.DefaultFocus} + focus={emptyFunction} renderDepth={this.props.renderDepth + 1} rootSelected={this.rootSelected} PanelWidth={this.previewWidthFunc} @@ -806,8 +806,6 @@ export class CollectionSchemaView extends CollectionSubView() { searchFilterDocs={this.searchFilterDocs} styleProvider={DefaultStyleProvider} docViewPath={returnEmptyDoclist} - ContainingCollectionDoc={this.props.CollectionView?.props.Document} - ContainingCollectionView={this.props.CollectionView} moveDocument={this.props.moveDocument} addDocument={this.addRow} removeDocument={this.props.removeDocument} @@ -849,8 +847,6 @@ class CollectionSchemaViewDocs extends React.Component() { } @computed get schemaDoc() { - return this.props.ContainingCollectionDoc!; + return this.props.DocumentView?.().props.docViewPath().lastElement()?.rootDoc; } @computed get rowIndex() { diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 13e45963e..5f8ffe8b0 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -28,8 +28,6 @@ export class SchemaTableCell extends React.Component { searchFilterDocs: returnEmptyDoclist, styleProvider: DefaultStyleProvider, docViewPath: returnEmptyDoclist, - ContainingCollectionView: undefined, - ContainingCollectionDoc: undefined, fieldKey: this.props.fieldKey, rootSelected: returnFalse, isSelected: returnFalse, diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 29e7cd3ad..d703c9595 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -44,25 +44,10 @@ export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: Docume } const dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs); - dragData.moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => { - docView.props.removeDocument?.(doc); - addDocument(doc); - return true; - }; - const containingView = docView.props.ContainingCollectionView; - const finishDrag = (e: DragManager.DragCompleteEvent) => - e.docDragData && - (e.docDragData.droppedDocuments = dragData.draggedDocuments.reduce((droppedDocs, d) => { - const dvs = DocumentManager.Instance.getDocumentViews(d).filter(dv => dv.props.ContainingCollectionView === containingView); - if (dvs.length) { - dvs.forEach(dv => droppedDocs.push(dv.props.Document)); - } else { - droppedDocs.push(Doc.MakeAlias(d)); - } - return droppedDocs; - }, [] as Doc[])); + dragData.canEmbed = true; + dragData.moveDocument = (docView.props.docViewPath().lastElement()?.ComponentView as any)?.props.CollectionView?.moveDocument; // this is equal to docView.props.moveDocument, but moveDocument is not a defined prop of a DocumentView .. but maybe it should be? - DragManager.StartDrag([dragEle], dragData, downX, downY, undefined, finishDrag); + DragManager.StartDocumentDrag([dragEle], dragData, downX, downY, undefined); } } diff --git a/src/client/views/linking/LinkPopup.tsx b/src/client/views/linking/LinkPopup.tsx index 7bdace2b6..5f2d4a7b6 100644 --- a/src/client/views/linking/LinkPopup.tsx +++ b/src/client/views/linking/LinkPopup.tsx @@ -85,15 +85,13 @@ export class LinkPopup extends React.Component { PanelWidth={this.getPWidth} PanelHeight={this.getPHeight} renderDepth={0} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} docViewPath={returnEmptyDoclist} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} /> diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 9bdb2cee7..24b9f3b25 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -160,8 +160,9 @@ export class CollectionFreeFormDocumentView extends DocComponent { - const { Document: topDoc, ContainingCollectionView: container } = this.props; - const screenXf = container?.screenToLocalTransform(); + const topDoc = this.rootDoc; + const containerDocView = this.props.docViewPath().lastElement(); + const screenXf = containerDocView?.screenToLocalTransform(); if (screenXf) { SelectionManager.DeselectAll(); if (topDoc.z) { @@ -178,7 +179,7 @@ export class CollectionFreeFormDocumentView extends DocComponent SelectionManager.SelectView(DocumentManager.Instance.getDocumentView(topDoc, container)!, false), 0); + setTimeout(() => SelectionManager.SelectView(DocumentManager.Instance.getDocumentView(topDoc, containerDocView), false), 0); } }; diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index dbcfe43cf..76a5ce7b3 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -154,7 +154,6 @@ export class DocumentContentsView extends React.Component< // these are the properties in DocumentViewProps that need to be removed to pass on only DocumentSharedViewProps to the FieldViews 'hideResizeHandles', 'hideTitle', - 'treeViewDoc', 'contentPointerEvents', 'radialMenu', 'LayoutTemplateString', diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index df3299eef..47705d53d 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -142,7 +142,7 @@ export class DocumentLinksButton extends React.Component undefined | { x: number; y: number; r: number; b: number }; fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _fitContentsToBox property on a Document - ContainingCollectionView: Opt; - ContainingCollectionDoc: Opt; suppressSetHeight?: boolean; thumbShown?: () => boolean; setContentView?: (view: DocComponentView) => any; @@ -179,6 +177,7 @@ export interface DocumentViewSharedProps { ScreenToLocalTransform: () => Transform; bringToFront: (doc: Doc, sendToBack?: boolean) => void; canEmbedOnDrag?: boolean; + treeViewDoc?: Doc; xPadding?: number; yPadding?: number; dropAction?: dropActionType; @@ -210,7 +209,6 @@ export interface DocumentViewProps extends DocumentViewSharedProps { hideOpenButton?: boolean; hideDeleteButton?: boolean; hideLinkAnchors?: boolean; - treeViewDoc?: Doc; isDocumentActive?: () => boolean | undefined; // whether a document should handle pointer events isContentActive: () => boolean | undefined; // whether document contents should handle pointer events contentPointerEvents?: string; // pointer events allowed for content of a document view. eg. set to "none" in menuSidebar for sharedDocs so that you can select a document, but not interact with its contents @@ -429,7 +427,6 @@ export class DocumentViewInternal extends DocComponent this.props.addDocTab(templateDoc, OpenWhere.addRight), icon: 'eye' }); !appearance && appearanceItems.length && cm.addItem({ description: 'UI Controls...', subitems: appearanceItems, icon: 'compass' }); - if (!Doc.IsSystem(this.rootDoc) && this.rootDoc._viewType !== CollectionViewType.Docking && this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Tree) { + if (!Doc.IsSystem(this.rootDoc) && this.rootDoc._viewType !== CollectionViewType.Docking && this.props.docViewPath().lastElement()?.rootDoc?._viewType !== CollectionViewType.Tree) { const existingOnClick = cm.findByDescription('OnClick...'); const onClicks: ContextMenuProps[] = existingOnClick && 'subitems' in existingOnClick ? existingOnClick.subitems : []; @@ -1446,7 +1442,7 @@ export class DocumentView extends React.Component { scaleToScreenSpace = () => (1 / (this.props.NativeDimScaling?.() || 1)) * this.screenToLocalTransform().Scale; docViewPathFunc = () => this.docViewPath; isSelected = (outsideReaction?: boolean) => SelectionManager.IsSelected(this, outsideReaction); - select = (extendSelection: boolean) => SelectionManager.SelectView(this, !SelectionManager.Views().some(v => v.props.Document === this.props.ContainingCollectionDoc) && extendSelection); + select = (extendSelection: boolean) => SelectionManager.SelectView(this, extendSelection); NativeWidth = () => this.effectiveNativeWidth; NativeHeight = () => this.effectiveNativeHeight; PanelWidth = () => this.panelWidth; diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 8d3534a5c..86779e0dd 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -32,6 +32,7 @@ export interface FieldViewProps extends DocumentViewSharedProps { // See currentUserUtils headerTemplate for examples of creating text boxes from html which set some of these fields // Also, see InkingStroke for examples of creating text boxes from render() methods which set some of these fields backgroundColor?: string; + treeViewDoc?: Doc; color?: string; fontSize?: number; height?: number; diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 94434dce7..7ea6d42ff 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -61,8 +61,6 @@ export class KeyValuePair extends React.Component { searchFilterDocs: returnEmptyDoclist, styleProvider: DefaultStyleProvider, docViewPath: returnEmptyDoclist, - ContainingCollectionView: undefined, - ContainingCollectionDoc: undefined, fieldKey: this.props.keyName, rootSelected: returnFalse, isSelected: returnFalse, diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index fcc5b6975..c58b5dd8c 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -271,14 +271,12 @@ export class LinkDocPreview extends React.Component { docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionDoc={undefined} - ContainingCollectionView={undefined} renderDepth={0} suppressSetHeight={true} PanelWidth={this.width} PanelHeight={this.height} pointerEvents={returnNone} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} whenChildContentsActiveChanged={returnFalse} ignoreAutoHeight={true} // need to ignore autoHeight otherwise autoHeight text boxes will expand beyond the preview panel size. bringToFront={returnFalse} diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index db11a7776..e015024fd 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -305,8 +305,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent + renderDepth={this.props.renderDepth + 1}> <> {this.threed} {this.content} @@ -330,7 +329,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent + /> )} diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index 8eacfbc51..1a75a7e76 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -568,12 +568,12 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b if (selectedViews.length) { if (checkResult) { const selView = selectedViews.lastElement(); - const layoutFrameNumber = Cast(selView.props.ContainingCollectionDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values + const layoutFrameNumber = Cast(selView.props.docViewPath().lastElement()?.rootDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values const contentFrameNumber = Cast(selView.rootDoc?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed return CollectionFreeFormDocumentView.getStringValues(selView?.rootDoc, contentFrameNumber).backgroundColor ?? 'transparent'; } selectedViews.forEach(dv => { - const layoutFrameNumber = Cast(dv.props.ContainingCollectionDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values + const layoutFrameNumber = Cast(dv.props.docViewPath().lastElement()?.rootDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values const contentFrameNumber = Cast(dv.rootDoc?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed if (contentFrameNumber !== undefined) { CollectionFreeFormDocumentView.setStringValues(contentFrameNumber, dv.rootDoc, { backgroundColor: color }); diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx index c00ab6a7e..b31fc01ff 100644 --- a/src/client/views/nodes/formattedText/DashDocView.tsx +++ b/src/client/views/nodes/formattedText/DashDocView.tsx @@ -9,10 +9,9 @@ import { DocServer } from '../../../DocServer'; import { Docs, DocUtils } from '../../../documents/Documents'; import { ColorScheme } from '../../../util/SettingsManager'; import { Transform } from '../../../util/Transform'; -import { DocumentView } from '../DocumentView'; +import { DocFocusOptions, DocumentView } from '../DocumentView'; import { FormattedTextBox } from './FormattedTextBox'; import React = require('react'); -import { SelectionManager } from '../../../util/SelectionManager'; export class DashDocView { dom: HTMLSpanElement; // container for label and value @@ -151,7 +150,7 @@ export class DashDocViewInternal extends React.Component { const { scale, translateX, translateY } = Utils.GetScreenTransform(this._spanRef.current); return new Transform(-translateX, -translateY, 1).scale(1 / scale); }; - outerFocus = (target: Doc) => this._textBox.props.focus(this._textBox.props.Document, {}); // ideally, this would scroll to show the focus target + outerFocus = (target: Doc, options: DocFocusOptions) => this._textBox.focus(target, options); // ideally, this would scroll to show the focus target onKeyDown = (e: any) => { e.stopPropagation(); @@ -212,8 +211,6 @@ export class DashDocViewInternal extends React.Component { docFilters={this.props.tbox?.props.docFilters} docRangeFilters={this.props.tbox?.props.docRangeFilters} searchFilterDocs={this.props.tbox?.props.searchFilterDocs} - ContainingCollectionView={this._textBox.props.ContainingCollectionView} - ContainingCollectionDoc={this._textBox.props.ContainingCollectionDoc} /> ); diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index f23426bb3..c43206629 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -235,10 +235,7 @@ export class DashFieldViewInternal extends React.Component { - let container = this.props.tbox.props.ContainingCollectionView; - while (container?.props.Document.isTemplateForField || container?.props.Document.isTemplateDoc) { - container = container.props.ContainingCollectionView; - } + let container = this.props.tbox.props.DocumentView?.().props.docViewPath().lastElement(); if (container) { const alias = Doc.MakeAlias(container.props.Document); alias._viewType = CollectionViewType.Time; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 677c4662b..bc2a5d797 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -541,7 +541,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { - const tanch = Docs.Create.TextanchorDocument({ title: 'dictation anchor' }); + const tanch = Docs.Create.TextanchorDocument({ title: 'dictation anchor', unrendered: true }); return this.addDocument(tanch) ? tanch : undefined; }; const link = DocUtils.MakeLinkToActiveAudio(textanchorFunc, false).lastElement(); @@ -956,7 +957,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { const examinedNode = findAnchorNode(node, editor); - if (examinedNode?.node && (examinedNode.node.textContent || examinedNode.node.type === this._editorView?.state.schema.nodes.audiotag)) { + if (examinedNode?.node && (examinedNode.node.textContent || examinedNode.node.type === this._editorView?.state.schema.nodes.dashDoc || examinedNode.node.type === this._editorView?.state.schema.nodes.audiotag)) { nodes.push(examinedNode.node); !hadStart && (start = index + examinedNode.start); hadStart = true; @@ -971,9 +972,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent mark.type === editor.state.schema.marks.linkAnchor); @@ -987,7 +994,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent 2 || (content?.length && content[0].type === this._editorView.state.schema.nodes.audiotag)) && ret.start >= 0) { + if ((ret.frag.size || (content?.length && content[0].type === this._editorView.state.schema.nodes.dashDoc) || (content?.length && content[0].type === this._editorView.state.schema.nodes.audiotag)) && ret.start >= 0) { !options.instant && (this._focusSpeed = focusSpeed); let selection = TextSelection.near(editor.state.doc.resolve(ret.start)); // default to near the start if (ret.frag.firstChild) { @@ -998,6 +1005,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent (this._focusSpeed = undefined), this._focusSpeed); setTimeout(() => clearStyleSheetRules(FormattedTextBox._highlightStyleSheet), Math.max(this._focusSpeed || 0, 3000)); + return focusSpeed; + } else { + return this.props.focus(this.rootDoc, options); } } }; diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 3589a9065..807a19771 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -2457,7 +2457,6 @@ export class PresBox extends ViewBoxBaseComponent() { {mode !== CollectionViewType.Invalid ? ( () { // Idea: this boolean will determine whether to automatically show the video when this preselement is selected. // @observable static showVideo: boolean = false; @computed get indexInPres() { - return DocListCast(this.presBox[StrCast(this.presBox.presFieldKey, 'data')]).indexOf(this.rootDoc); + return DocListCast(this.presBox?.[StrCast(this.presBox.presFieldKey, 'data')]).indexOf(this.rootDoc); } // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements) @computed get expandViewHeight() { return 100; @@ -51,11 +51,10 @@ export class PresElementBox extends ViewBoxBaseComponent() { return this.presBoxView?.selectedArray; } @computed get presBoxView() { - const vpath = this.props.docViewPath(); - return vpath.length > 1 ? (vpath[vpath.length - 2].ComponentView as PresBox) : undefined; + return this.props.DocumentView?.()?.props.docViewPath().lastElement()?.ComponentView as PresBox; } @computed get presBox() { - return this.props.ContainingCollectionDoc!; + return this.props.DocumentView?.().props.docViewPath().lastElement()?.rootDoc; } @computed get targetDoc() { return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc; @@ -110,14 +109,12 @@ export class PresElementBox extends ViewBoxBaseComponent() { docFilters={this.props.docFilters} docRangeFilters={this.props.docRangeFilters} searchFilterDocs={this.props.searchFilterDocs} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} rootSelected={returnTrue} addDocument={returnFalse} removeDocument={returnFalse} fitContentsToBox={returnTrue} moveDocument={this.props.moveDocument!} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} whenChildContentsActiveChanged={returnFalse} addDocTab={returnFalse} pinToPres={returnFalse} @@ -195,7 +192,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { const dragData = new DragManager.DocumentDragData(this.presBoxView?.sortArray() ?? []); if (!dragData.draggedDocuments.length) dragData.draggedDocuments.push(this.rootDoc); dragData.dropAction = 'move'; - dragData.treeViewDoc = this.presBox._viewType === CollectionViewType.Tree ? this.props.ContainingCollectionDoc : undefined; // this.props.DocumentView?.()?.props.treeViewDoc; + dragData.treeViewDoc = this.presBox?._viewType === CollectionViewType.Tree ? this.presBox : undefined; // this.props.DocumentView?.()?.props.treeViewDoc; dragData.moveDocument = this.props.moveDocument; const dragItem: HTMLElement[] = []; if (dragArray.length === 1) { @@ -269,7 +266,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { @undoBatch removeItem = action((e: React.MouseEvent) => { e.stopPropagation(); - if (this.indexInPres < (this.presBoxView?.itemIndex || 0)) { + if (this.presBox && this.indexInPres < (this.presBoxView?.itemIndex || 0)) { this.presBox.itemIndex = (this.presBoxView?.itemIndex || 0) - 1; } this.props.removeDocument?.(this.rootDoc); @@ -406,15 +403,15 @@ export class PresElementBox extends ViewBoxBaseComponent() { @computed get toolbarWidth(): number { const presBoxDocView = DocumentManager.Instance.getDocumentView(this.presBox); - let width: number = NumCast(this.presBox._width); + let width: number = NumCast(this.presBox?._width); if (presBoxDocView) width = presBoxDocView.props.PanelWidth(); if (width === 0) width = 300; return width; } @computed get presButtons() { - const presBox: Doc = this.presBox; //presBox - const presBoxColor: string = StrCast(presBox._backgroundColor); + const presBox = this.presBox; //presBox + const presBoxColor: string = StrCast(presBox?._backgroundColor); const presColorBool: boolean = presBoxColor ? presBoxColor !== Colors.WHITE && presBoxColor !== 'transparent' : false; const targetDoc: Doc = this.targetDoc; const activeItem: Doc = this.rootDoc; @@ -494,10 +491,10 @@ export class PresElementBox extends ViewBoxBaseComponent() { @computed get mainItem() { const isSelected: boolean = this.selectedArray?.has(this.rootDoc) ? true : false; - const isCurrent: boolean = this.presBox._itemIndex === this.indexInPres; + const isCurrent: boolean = this.presBox?._itemIndex === this.indexInPres; const miniView: boolean = this.toolbarWidth <= 110; - const presBox: Doc = this.presBox; //presBox - const presBoxColor: string = StrCast(presBox._backgroundColor); + const presBox = this.presBox; //presBox + const presBoxColor: string = StrCast(presBox?._backgroundColor); const presColorBool: boolean = presBoxColor ? presBoxColor !== Colors.WHITE && presBoxColor !== 'transparent' : false; const activeItem: Doc = this.rootDoc; diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index f2e9be61d..d63c25dbe 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -46,7 +46,7 @@ export class TopBar extends React.Component { return (
{Doc.ActiveDashboard ? ( - } isCircle={true} hoverStyle="gray" color={this.textColor} /> + } color={this.textColor} /> ) : (
dash logo @@ -55,18 +55,7 @@ export class TopBar extends React.Component {
)} {Doc.ActiveDashboard && ( -
); @@ -94,13 +83,8 @@ export class TopBar extends React.Component {