diff options
| author | mehekj <mehek.jethani@gmail.com> | 2022-06-20 18:27:29 -0400 |
|---|---|---|
| committer | mehekj <mehek.jethani@gmail.com> | 2022-06-20 18:27:29 -0400 |
| commit | 3415f672292bb349c7d9ec66564933a746ee3b25 (patch) | |
| tree | 69e3c6284211fbaf8fc51f8b661ca855165c701e /src/client/views/collections | |
| parent | 145117365b2708ef6b365c6f0f10c38b85a87307 (diff) | |
Revert "Merge branch 'master' into temporalmedia-mehek"
This reverts commit 145117365b2708ef6b365c6f0f10c38b85a87307, reversing
changes made to 7eedde332010c8896be636f0b5c6a7b2c8043e48.
Diffstat (limited to 'src/client/views/collections')
15 files changed, 383 insertions, 301 deletions
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index d2687df17..de2106e4a 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -26,7 +26,6 @@ import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView"; import { CollectionViewType } from './CollectionView'; import { TabDocView } from './TabDocView'; import React = require("react"); -import { SelectionManager } from '../../util/SelectionManager'; const _global = (window /* browser */ || global /* node */) as any; @observer @@ -51,8 +50,9 @@ export class CollectionDockingView extends CollectionSubView() { public _flush: UndoManager.Batch | undefined; private _ignoreStateChange = ""; public tabMap: Set<any> = new Set(); + public get initialized() { return this._goldenLayout !== null; } public get HasFullScreen() { return this._goldenLayout._maximisedItem !== null; } - private _goldenLayout: any = null; + @observable private _goldenLayout: any = null; constructor(props: SubCollectionViewProps) { super(props); @@ -118,7 +118,6 @@ export class CollectionDockingView extends CollectionSubView() { @undoBatch public static OpenFullScreen(doc: Doc) { - SelectionManager.DeselectAll(); const instance = CollectionDockingView.Instance; if (doc._viewType === CollectionViewType.Docking && doc.layoutKey === "layout") { return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc); @@ -172,6 +171,12 @@ export class CollectionDockingView extends CollectionSubView() { @undoBatch @action public static AddSplit(document: Doc, pullSide: string, stack?: any, panelName?: string) { + if (document.type === DocumentType.PRES) { + const docs = Cast(Cast(Doc.UserDoc().myOverlayDocs, Doc, null).data, listSpec(Doc), []); + if (docs.includes(document)) { + docs.splice(docs.indexOf(document), 1); + } + } if (document._viewType === CollectionViewType.Docking) return CurrentUserUtils.openDashboard(Doc.UserDoc(), document); const tab = Array.from(CollectionDockingView.Instance.tabMap).find(tab => tab.DashDoc === document); @@ -180,7 +185,6 @@ export class CollectionDockingView extends CollectionSubView() { return true; } const instance = CollectionDockingView.Instance; - const glayRoot = instance._goldenLayout.root; if (!instance) return false; const docContentConfig = CollectionDockingView.makeDocumentConfig(document, panelName); @@ -188,75 +192,71 @@ export class CollectionDockingView extends CollectionSubView() { stack.addChild(docContentConfig, undefined); stack.setActiveContentItem(stack.contentItems[stack.contentItems.length - 1]); } else { - const newContentItem = () => { - const newItem = glayRoot.layoutManager.createContentItem({ type: 'stack', content: [docContentConfig] }, instance._goldenLayout); - newItem.callDownwards('_$init'); - return newItem; - } - if (glayRoot.contentItems.length === 0) { // if no rows / columns - glayRoot.addChild(newContentItem()); - } else if (glayRoot.contentItems[0].isStack) { - glayRoot.contentItems[0].addChild(docContentConfig); + const newItemStackConfig = { type: 'stack', content: [docContentConfig] }; + const newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout); + if (instance._goldenLayout.root.contentItems.length === 0) { // if no rows / columns + instance._goldenLayout.root.addChild(newContentItem); + } else if (instance._goldenLayout.root.contentItems[0].isStack) { + instance._goldenLayout.root.contentItems[0].addChild(docContentConfig); } else if ( - glayRoot.contentItems.length === 1 && - glayRoot.contentItems[0].contentItems.length === 1 && - glayRoot.contentItems[0].contentItems[0].contentItems.length === 0) { - glayRoot.contentItems[0].contentItems[0].addChild(docContentConfig); + instance._goldenLayout.root.contentItems.length === 1 && + instance._goldenLayout.root.contentItems[0].contentItems.length === 1 && + instance._goldenLayout.root.contentItems[0].contentItems[0].contentItems.length === 0) { + instance._goldenLayout.root.contentItems[0].contentItems[0].addChild(docContentConfig); } else if (instance._goldenLayout.root.contentItems[0].isRow) { // if row switch (pullSide) { default: - case "right": glayRoot.contentItems[0].addChild(newContentItem()); break; - case "left": glayRoot.contentItems[0].addChild(newContentItem(), 0); break; + case "right": instance._goldenLayout.root.contentItems[0].addChild(newContentItem); break; + case "left": instance._goldenLayout.root.contentItems[0].addChild(newContentItem, 0); break; case "top": case "bottom": // if not going in a row layout, must add already existing content into column - const rowlayout = glayRoot.contentItems[0]; + const rowlayout = instance._goldenLayout.root.contentItems[0]; const newColumn = rowlayout.layoutManager.createContentItem({ type: "column" }, instance._goldenLayout); - const newItem = newContentItem(); - instance._goldenLayout.saveScrollTops(rowlayout.element); + CollectionDockingView.Instance._goldenLayout.saveScrollTops(rowlayout.element); rowlayout.parent.replaceChild(rowlayout, newColumn); if (pullSide === "top") { newColumn.addChild(rowlayout, undefined, true); - newColumn.addChild(newItem, 0, true); + newColumn.addChild(newContentItem, 0, true); } else if (pullSide === "bottom") { - newColumn.addChild(newItem, undefined, true); + newColumn.addChild(newContentItem, undefined, true); newColumn.addChild(rowlayout, 0, true); } - instance._goldenLayout.restoreScrollTops(rowlayout.element); + CollectionDockingView.Instance._goldenLayout.restoreScrollTops(rowlayout.element); rowlayout.config.height = 50; - newItem.config.height = 50; + newContentItem.config.height = 50; } } else {// if (instance._goldenLayout.root.contentItems[0].isColumn) { // if column switch (pullSide) { - case "top": glayRoot.contentItems[0].addChild(newContentItem(), 0); break; - case "bottom": glayRoot.contentItems[0].addChild(newContentItem()); break; + case "top": instance._goldenLayout.root.contentItems[0].addChild(newContentItem, 0); break; + case "bottom": instance._goldenLayout.root.contentItems[0].addChild(newContentItem); break; case "left": case "right": default: // if not going in a row layout, must add already existing content into column - const collayout = glayRoot.contentItems[0]; + const collayout = instance._goldenLayout.root.contentItems[0]; const newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout); - const newItem = newContentItem(); - instance._goldenLayout.saveScrollTops(collayout.element); + CollectionDockingView.Instance._goldenLayout.saveScrollTops(collayout.element); collayout.parent.replaceChild(collayout, newRow); if (pullSide === "left") { newRow.addChild(collayout, undefined, true); - newRow.addChild(newItem, 0, true); + newRow.addChild(newContentItem, 0, true); } else { - newRow.addChild(newItem, undefined, true); + newRow.addChild(newContentItem, undefined, true); newRow.addChild(collayout, 0, true); } - instance._goldenLayout.restoreScrollTops(collayout.element); + CollectionDockingView.Instance._goldenLayout.restoreScrollTops(collayout.element); collayout.config.width = 50; - newItem.config.width = 50; + newContentItem.config.width = 50; } } instance._ignoreStateChange = JSON.stringify(instance._goldenLayout.toConfig()); + newContentItem.callDownwards('_$init'); } return instance.layoutChanged(); @@ -271,7 +271,7 @@ export class CollectionDockingView extends CollectionSubView() { return true; } - setupGoldenLayout = async () => { + async setupGoldenLayout() { const config = StrCast(this.props.Document.dockingConfig); if (config) { const matches = config.match(/\"documentId\":\"[a-z0-9-]+\"/g); @@ -288,19 +288,26 @@ export class CollectionDockingView extends CollectionSubView() { this._goldenLayout.unbind('stackCreated', this.stackCreated); } catch (e) { } } - this.tabMap.clear(); - this._goldenLayout.destroy(); } - const glay = this._goldenLayout = new GoldenLayout(JSON.parse(config)); - glay.on('tabCreated', this.tabCreated); - glay.on('tabDestroyed', this.tabDestroyed); - glay.on('stackCreated', this.stackCreated); - glay.registerComponent('DocumentFrameRenderer', TabDocView); - glay.container = this._containerRef.current; - glay.init(); - glay.root.layoutManager.on('itemDropped', this.tabItemDropped); - glay.root.layoutManager.on('dragStart', this.tabDragStart); - glay.root.layoutManager.on('activeContentItemChanged', this.stateChanged); + this.tabMap.clear(); + this._goldenLayout?.destroy(); + runInAction(() => this._goldenLayout = new GoldenLayout(JSON.parse(config))); + this._goldenLayout.on('tabCreated', this.tabCreated); + this._goldenLayout.on('tabDestroyed', this.tabDestroyed); + this._goldenLayout.on('stackCreated', this.stackCreated); + this._goldenLayout.registerComponent('DocumentFrameRenderer', TabDocView); + this._goldenLayout.container = this._containerRef.current; + if (this._goldenLayout.config.maximisedItemId === '__glMaximised') { + try { + this._goldenLayout.config.root.getItemsById(this._goldenLayout.config.maximisedItemId)[0].toggleMaximise(); + } catch (e) { + this._goldenLayout.config.maximisedItemId = null; + } + } + this._goldenLayout.init(); + this._goldenLayout.root.layoutManager.on('itemDropped', this.tabItemDropped); + this._goldenLayout.root.layoutManager.on('dragStart', this.tabDragStart); + this._goldenLayout.root.layoutManager.on('activeContentItemChanged', this.stateChanged); } } @@ -315,7 +322,7 @@ export class CollectionDockingView extends CollectionSubView() { } this._ignoreStateChange = ""; }); - setTimeout(this.setupGoldenLayout); + setTimeout(() => this.setupGoldenLayout(), 0); //window.addEventListener('resize', this.onResize); // bcz: would rather add this event to the parent node, but resize events only come from Window } } @@ -361,8 +368,7 @@ export class CollectionDockingView extends CollectionSubView() { const htmlTarget = e.target as HTMLElement; window.addEventListener("mouseup", this.onPointerUp); if (!htmlTarget.closest("*.lm_content") && (htmlTarget.closest("*.lm_tab") || htmlTarget.closest("*.lm_stack"))) { - const className = typeof htmlTarget.className === "string" ? htmlTarget.className : ""; - if (!className.includes("lm_close") && !className.includes("lm_maximise")) { + if (htmlTarget.className !== "lm_close_tab") { this._flush = UndoManager.StartBatch("golden layout edit"); } } @@ -407,37 +413,29 @@ export class CollectionDockingView extends CollectionSubView() { const docs = !docids ? [] : docids.map(id => DocServer.GetCachedRefField(id)).filter(f => f).map(f => f as Doc); const changesMade = this.props.Document.dockcingConfig !== json; if (changesMade && !this._flush) { - UndoManager.RunInBatch(() => { - this.props.Document.dockingConfig = json; - this.props.Document.data = new List<Doc>(docs); - }, "state changed"); + this.props.Document.dockingConfig = json; + this.props.Document.data = new List<Doc>(docs); } return changesMade; } tabDestroyed = (tab: any) => { - Doc.AddDocToList(CurrentUserUtils.MyHeaderBarDoc, "data", tab.DashDoc); - Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, "data", tab.DashDoc, undefined, true, true); - const dview = CollectionDockingView.Instance.props.Document; - const fieldKey = CollectionDockingView.Instance.props.fieldKey; - Doc.RemoveDocFromList(dview, fieldKey, tab.DashDoc); this.tabMap.delete(tab); tab._disposers && Object.values(tab._disposers).forEach((disposer: any) => disposer?.()); tab.reactComponents?.forEach((ele: any) => ReactDOM.unmountComponentAtNode(ele)); this.stateChanged(); } tabCreated = (tab: any) => { - this.tabMap.add(tab); tab.contentItem.element[0]?.firstChild?.firstChild?.InitTab?.(tab); // have to explicitly initialize tabs that reuse contents from previous tabs (ie, when dragging a tab around a new tab is created for the old content) } stackCreated = (stack: any) => { stack.header?.element.on('mousedown', (e: any) => { if (e.target === stack.header?.element[0] && e.button === 2) { - const dashboard= CurrentUserUtils.ActiveDashboard; - dashboard["pane-count"] = NumCast(dashboard["pane-count"]) + 1; + const emptyPane = CurrentUserUtils.EmptyPane; + emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1; const docToAdd = Docs.Create.FreeformDocument([], { - _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _backgroundGridShow: true, _fitWidth: true, title: `Untitled Tab ${NumCast(dashboard["pane-count"])}`, + _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _backgroundGridShow: true, _fitWidth: true, title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`, }); this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd); CollectionDockingView.AddSplit(docToAdd, "", stack); @@ -454,17 +452,14 @@ export class CollectionDockingView extends CollectionSubView() { alert('cant delete the last stack'); } })); - - stack.header?.controlsContainer.find('.lm_maximise') //get the close icon - .click(() => setTimeout(this.stateChanged)); stack.header?.controlsContainer.find('.lm_popout') //get the popout icon .off('click') //unbind the current click handler .click(action(() => { // stack.config.fixed = !stack.config.fixed; // force the stack to have a fixed size - const dashboard = CurrentUserUtils.ActiveDashboard; - dashboard["pane-count"] = NumCast(dashboard["pane-count"]) + 1; + const emptyPane = CurrentUserUtils.EmptyPane; + emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1; const docToAdd = Docs.Create.FreeformDocument([], { - _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _fitWidth: true, _backgroundGridShow: true, title: `Untitled Tab ${NumCast(dashboard["pane-count"])}` + _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _fitWidth: true, _backgroundGridShow: true, title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}` }); this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd); CollectionDockingView.AddSplit(docToAdd, "", stack); diff --git a/src/client/views/collections/CollectionDockingViewMenu.scss b/src/client/views/collections/CollectionDockingViewMenu.scss new file mode 100644 index 000000000..4157f0f7e --- /dev/null +++ b/src/client/views/collections/CollectionDockingViewMenu.scss @@ -0,0 +1,34 @@ + +.dockingViewButtonSelector { + div { + overflow: visible !important; + } + + display: inline-block; + width:100%; + height:100%; +} +.dockingViewButtonSelector-flyout { + position: relative; + z-index: 9999; + background-color: #eeeeee; + box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); + color: black; + + padding: 10px; + border-radius: 3px; + display: inline-block; + height: 100%; + width: 100%; + border-radius: 3px; + + hr { + height: 1px; + margin: 0px; + background-color: gray; + border-top: 0px; + border-bottom: 0px; + border-right: 0px; + border-left: 0px; + } +}
\ No newline at end of file diff --git a/src/client/views/collections/CollectionDockingViewMenu.tsx b/src/client/views/collections/CollectionDockingViewMenu.tsx new file mode 100644 index 000000000..1cab293a8 --- /dev/null +++ b/src/client/views/collections/CollectionDockingViewMenu.tsx @@ -0,0 +1,48 @@ +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Tooltip } from "@material-ui/core"; +import { action, computed, observable } from "mobx"; +import { observer } from "mobx-react"; +import * as React from "react"; +import { DocumentButtonBar } from "../DocumentButtonBar"; +import { DocumentView } from "../nodes/DocumentView"; +const higflyout = require("@hig/flyout"); +export const { anchorPoints } = higflyout; +export const Flyout = higflyout.default; + +@observer +export class CollectionDockingViewMenu extends React.Component<{ views: () => DocumentView[], Stack: any }> { + customStylesheet(styles: any) { + return { + ...styles, + panel: { + ...styles.panel, + minWidth: "100px" + }, + }; + } + _ref = React.createRef<HTMLDivElement>(); + + @computed get flyout() { + return ( + <div className="dockingViewButtonSelector-flyout" title=" " ref={this._ref}> + <DocumentButtonBar views={this.props.views} stack={this.props.Stack} /> + </div> + ); + } + + @observable _tooltipOpen: boolean = false; + render() { + return <Tooltip open={this._tooltipOpen} onClose={action(() => this._tooltipOpen = false)} title={<><div className="dash-tooltip">Tap for toolbar, drag to create alias in another pane</div></>} placement="bottom"> + <span className="dockingViewButtonSelector" + onPointerEnter={action(() => !this._ref.current?.getBoundingClientRect().width && (this._tooltipOpen = true))} + onPointerDown={action(e => { + this.props.views()[0]?.select(false); + this._tooltipOpen = false; + })} > + <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={this.flyout} stylesheet={this.customStylesheet}> + <FontAwesomeIcon icon={"arrows-alt"} size={"sm"} /> + </Flyout> + </span> + </Tooltip >; + } +} diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 39f6466d6..23fd4206c 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -252,8 +252,8 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu }; _clusterCommand = { params: ["target"], title: "fit content", - script: "self.target._fitContentsToBox = !self.target._fitContentsToBox;", - immediate: undoBatch((source: Doc[]) => this.target._fitContentsToBox = !this.target._fitContentsToBox), + script: "self.target._fitToBox = !self.target._fitToBox;", + immediate: undoBatch((source: Doc[]) => this.target._fitToBox = !this.target._fitToBox), initialize: emptyFunction }; _fitContentCommand = { @@ -457,7 +457,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu const isPinned = targetDoc && Doc.isDocPinned(targetDoc); return !targetDoc ? (null) : <Tooltip key="pin" title={<div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div>} placement="top"> <button className="antimodeMenu-button" style={{ backgroundColor: isPinned ? "121212" : undefined, borderLeft: "1px solid gray" }} - onClick={e => TabDocView.PinDoc(targetDoc, { /* unpin: isPinned*/ })}> + onClick={e => TabDocView.PinDoc(targetDoc, { unpin: isPinned })}> <FontAwesomeIcon className="colMenu-icon" size="lg" icon="map-pin" /> </button> </Tooltip>; @@ -507,6 +507,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu activeDoc.presPinViewY = y; activeDoc.presPinViewScale = scale; } else if (targetDoc.type === DocumentType.VID) { + activeDoc.presPinTimecode = targetDoc._currentTimecode; activeDoc.presPinView = true; } else if (targetDoc.type === DocumentType.COMPARISON) { const width = targetDoc._clipWidth; diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 372629ddf..8bdcfeea9 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -465,7 +465,6 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack _stayInCollection: true, useLinkSmallAnchor: true, hideLinkButton: true, - _isLinkButton: true, annotationOn: rootDoc, _timelineLabel: true, borderRounding: anchorEndTime === undefined ? "100%" : undefined diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 73572299a..2f002736d 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -30,10 +30,11 @@ width: 90%; margin: 5px; font-size: 11px; + background-color: $light-blue; color: $medium-blue; padding: 10px; - border-radius: 5px; - border: solid .5px $medium-blue; + border-radius: 10px; + border: solid 2px $medium-blue; } } diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index 7573b938a..4f6f45d2f 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -135,7 +135,7 @@ export class CollectionTimeView extends CollectionSubView() { onClick={this.contentsDown}> <CollectionFreeFormView {...this.props} engineProps={{ pivotField: this.pivotField, docFilters: this.childDocFilters, docRangeFilters: this.childDocRangeFilters }} - fitContentsToBox={returnTrue} + fitContentsToDoc={returnTrue} childClickScript={this._childClickedScript} viewDefDivClick={this._viewDefDivClick} childFreezeDimensions={true} diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 022b9fa24..dab3d490d 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -4,15 +4,15 @@ import { Tooltip } from '@material-ui/core'; import 'golden-layout/src/css/goldenlayout-base.css'; import 'golden-layout/src/css/goldenlayout-dark-theme.css'; import { clamp } from 'lodash'; -import { action, computed, IReactionDisposer, observable, reaction } from "mobx"; +import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import * as ReactDOM from 'react-dom'; -import { DataSym, Doc, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; +import { DataSym, Doc, DocListCast, DocListCastAsync, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { FieldId } from "../../../fields/RefField"; import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types"; -import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from "../../../Utils"; +import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, Utils } from "../../../Utils"; import { DocServer } from "../../DocServer"; import { DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; @@ -27,16 +27,14 @@ import { Colors, Shadows } from '../global/globalEnums'; import { LightboxView } from '../LightboxView'; import { MainView } from '../MainView'; import { DocFocusOptions, DocumentView, DocumentViewProps } from "../nodes/DocumentView"; -import { DashFieldView } from '../nodes/formattedText/DashFieldView'; import { PinProps, PresBox, PresMovement } from '../nodes/trails'; import { DefaultStyleProvider, StyleProp } from '../StyleProvider'; import { CollectionDockingView } from './CollectionDockingView'; +import { CollectionDockingViewMenu } from './CollectionDockingViewMenu'; import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; import { CollectionView, CollectionViewType } from './CollectionView'; import "./TabDocView.scss"; import React = require("react"); -import { listSpec } from '../../../fields/Schema'; -import { ScriptField } from '../../../fields/ScriptField'; const _global = (window /* browser */ || global /* node */) as any; interface TabDocViewProps { @@ -84,6 +82,7 @@ export class TabDocView extends React.Component<TabDocViewProps> { const iconWrap = document.createElement("div"); const closeWrap = document.createElement("div"); + titleEle.size = StrCast(doc.title).length + 3; titleEle.value = doc.title; titleEle.onkeydown = (e: KeyboardEvent) => { @@ -94,33 +93,26 @@ export class TabDocView extends React.Component<TabDocViewProps> { Doc.GetProto(doc).title = e.currentTarget.value; })); + const dragBtnDown = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, e => !e.defaultPrevented && DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY), returnFalse, emptyFunction); + }; + + if (tab.element[0].children[1].children.length === 1) { - iconWrap.className = "lm_iconWrap lm_moreInfo"; - const dragBtnDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, e => !e.defaultPrevented && DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY), returnFalse, action(e => { - if (this.view) { - SelectionManager.SelectView(this.view, false); - let child = this.view.ContentDiv!.children[0]; - while (child.children.length) { - const next = Array.from(child.children).find(c => c.className?.toString().includes("SVGAnimatedString") || typeof (c.className) === "string"); - if (next?.className?.toString().includes(DocumentView.ROOT_DIV)) break; - if (next?.className?.toString().includes(DashFieldView.name)) break; - if (next) child = next; - else break; - } - simulateMouseClick(child, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30); - } - else { this._activated = true; - setTimeout(() =>this.view && SelectionManager.SelectView(this.view, false)); - } - })); + iconWrap.className = "lm_iconWrap"; + iconWrap.id = "lm_iconWrap"; + closeWrap.className = "lm_iconWrap"; + closeWrap.id = "lm_closeWrap"; + closeWrap.onclick = (e: MouseEvent) => { + tab.header.parent.contentItem.remove(); + Doc.AddDocToList(CurrentUserUtils.MyHeaderBarDoc, "data", tab.DashDoc); + Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, "data", tab.DashDoc, undefined, true, true); }; - const docIcon = <FontAwesomeIcon onPointerDown={dragBtnDown} icon={iconType} />; - const closeIcon = <FontAwesomeIcon icon={"eye"} />; + const closeIcon = <FontAwesomeIcon icon={"times"} />; ReactDOM.render(docIcon, iconWrap); ReactDOM.render(closeIcon, closeWrap); - tab.reactComponents = [iconWrap, closeWrap]; + // tab.element[0].append(closeWrap); tab.element[0].prepend(iconWrap); tab._disposers.layerDisposer = reaction(() => ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }), ({ layer, color }) => { @@ -131,6 +123,7 @@ export class TabDocView extends React.Component<TabDocViewProps> { titleEle.style.backgroundColor = "transparent"; iconWrap.style.color = textColor; closeWrap.style.color = textColor; + moreInfoDrag.style.backgroundColor = textColor; tab.element[0].style.background = !layer ? color : "dimgrey"; }, { fireImmediately: true }); } @@ -163,6 +156,19 @@ export class TabDocView extends React.Component<TabDocViewProps> { // toggle.style.textTransform = selected ? "uppercase" : ""; })); + //attach the selection doc buttons menu to the drag handle + const stack: HTMLDivElement = tab.contentItem.parent; + const header: HTMLDivElement = tab; + stack.onscroll = action((e: any) => { + console.log('scrolling...'); + }); + const moreInfoDrag = document.createElement("div"); + moreInfoDrag.className = "lm_iconWrap"; + tab._disposers.buttonDisposer = reaction(() => this.view, view => + view && [ReactDOM.render(<span><CollectionDockingViewMenu views={() => [view]} Stack={stack} /></span>, moreInfoDrag), tab._disposers.buttonDisposer?.()], + { fireImmediately: true }); + // tab.reactComponents = [moreInfoDrag]; + // tab.element[0].children[3].before(moreInfoDrag); // highlight the tab when the tab document is brushed in any part of the UI tab._disposers.reactionDisposer = reaction(() => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }), ({ title, degree }) => { @@ -179,21 +185,20 @@ export class TabDocView extends React.Component<TabDocViewProps> { UndoManager.RunInBatch(() => tab.contentItem.remove(), "delete tab"); }); } + CollectionDockingView.Instance.tabMap.add(tab); } /** * Adds a document to the presentation view **/ @action - public static PinDoc(docs: Doc|Doc[], pinProps?: PinProps) { - const docList = ((docs instanceof Doc) ? [docs]: docs); - const batch = UndoManager.StartBatch("pinning doc"); - - // all docs will be added to the ActivePresentation as stored on CurrentUserUtils + public static async PinDoc(doc: Doc, pinProps?: PinProps) { + if (pinProps?.unpin) console.log('TODO: Remove UNPIN from this location'); + //add this new doc to props.Document const curPres = CurrentUserUtils.ActivePresentation; - curPres && docList.forEach(doc => { - // Edge Case 1: Cannot pin document to itself + if (curPres) { if (doc === curPres) { alert("Cannot pin presentation document to itself"); return; } + const batch = UndoManager.StartBatch("pinning doc"); const pinDoc = Doc.MakeAlias(doc); pinDoc.presentationTargetDoc = doc; pinDoc.title = doc.title + " - Slide"; @@ -213,48 +218,6 @@ export class TabDocView extends React.Component<TabDocViewProps> { const size: number = PresBox.Instance?._selectedArray.size; const presSelected: Doc | undefined = presArray && size ? presArray[size - 1] : undefined; const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], null); - // If pinWithView option set then update scale and x / y props of slide - if (pinProps?.pinWithView) { - const viewProps = pinProps.pinWithView; - pinDoc.presPinView = true; - pinDoc.presPinViewX = viewProps.bounds.left + viewProps.bounds.width / 2; - pinDoc.presPinViewY = viewProps.bounds.top + viewProps.bounds.height / 2; - pinDoc.presPinViewScale = viewProps.scale; - pinDoc.contentBounds = new List<number>([viewProps.bounds.left, viewProps.bounds.top, viewProps.bounds.left+viewProps.bounds.width, viewProps.bounds.top+viewProps.bounds.height]); - } - if (pinProps?.pinDocView) { - const scrollable = [DocumentType.PDF, DocumentType.RTF, DocumentType.WEB].includes(pinDoc.type as any) || pinDoc._viewType === CollectionViewType.Stacking; - const pannable: boolean = ((pinDoc.type === DocumentType.COL && doc._viewType === CollectionViewType.Freeform) || doc.type === DocumentType.IMG); - if (scrollable) { - const scroll = doc._scrollTop; - pinDoc.presPinView = true; - pinDoc.presPinViewScroll = scroll; - } else if ([DocumentType.AUDIO, DocumentType.VID].includes(doc.type as any)) { - pinDoc.presPinView = true; - pinDoc.presStartTime = doc._currentTimecode; - pinDoc.presEndTime = NumCast(doc._currentTimecode) + 0.1; - } else if (pannable) { - pinDoc.presPinView = true; - pinDoc.presPinViewX = pinDoc._panX; - pinDoc.presPinViewY = pinDoc._panY; - pinDoc.presPinViewScale = pinDoc._viewScale; - const pw = NumCast(pinProps.panelWidth); - const ph = NumCast(pinProps.panelHeight); - const ps = NumCast(pinDoc._viewScale); - if (pw && ph && ps) { - pinDoc.contentBounds = new List<number>([ - NumCast(pinDoc.panX)-pw/2/ps, - NumCast(pinDoc.panY)-ph/2/ps, - NumCast(pinDoc.panX)+pw/2/ps, - NumCast(pinDoc.panY)+ph/2/ps]); - } - } else if (doc.type === DocumentType.COMPARISON) { - const width = doc._clipWidth; - pinDoc.presPinClipWidth = width; - pinDoc.presPinView = true; - } - } - pinDoc.onClick = ScriptField.MakeFunction("navigateToDoc(self.presentationTargetDoc, self)"); Doc.AddDocToList(curPres, "data", pinDoc, presSelected); if (!pinProps?.audioRange && duration !== undefined) { pinDoc.mediaStart = "manual"; @@ -273,16 +236,20 @@ export class TabDocView extends React.Component<TabDocViewProps> { pinDoc.presMovement = PresMovement.None; } if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true; - PresBox.Instance?._selectedArray.clear(); - pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array - }); - if (!Array.from(CollectionDockingView.Instance.tabMap).map(d => d.DashDoc).includes(curPres)) { - const docs = Cast(Cast(Doc.UserDoc().myOverlayDocs, Doc, null).data, listSpec(Doc), []); - if (docs.includes(curPres)) docs.splice(docs.indexOf(curPres), 1); - CollectionDockingView.AddSplit(curPres, "right"); - setTimeout(() => DocumentManager.Instance.jumpToDocument(docList.lastElement(), false, undefined, []), 100); // keeps the pinned doc in view since the sidebar shifts things + const dview = CollectionDockingView.Instance.props.Document; + const fieldKey = CollectionDockingView.Instance.props.fieldKey; + const tabdocs = await DocListCastAsync(dview[fieldKey]); + runInAction(() => { + if (!pinProps?.hidePresBox && !tabdocs?.includes(curPres)) { + tabdocs?.push(curPres); // bcz: Argh! this is annoying. if multiple documents are pinned, this will get called multiple times before the presentation view is drawn. Thus it won't be in the tabdocs list and it will get created multple times. so need to explicilty add the presbox to the list of open tabs + CollectionDockingView.AddSplit(curPres, "right"); + } + PresBox.Instance?._selectedArray.clear(); + pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array + DocumentManager.Instance.jumpToDocument(doc, false, undefined, []); + batch.end(); + }); } - setTimeout(batch.end, 500); // need to wait until dockingview (goldenlayout) updates all its structurs } componentDidMount() { @@ -305,6 +272,7 @@ export class TabDocView extends React.Component<TabDocViewProps> { componentWillUnmount() { this._tabReaction?.(); this._view && DocumentManager.Instance.RemoveView(this._view); + this.tab && CollectionDockingView.Instance.tabMap.delete(this.tab); this.props.glContainer.layoutManager.off("activeContentItemChanged", this.onActiveContentItemChanged); } @@ -452,7 +420,9 @@ export class TabDocView extends React.Component<TabDocViewProps> { }} ref={ref => { if (this._mainCont = ref) { if (this._lastTab) { + console.log("DUP tab") this._view && DocumentManager.Instance.RemoveView(this._view); + CollectionDockingView.Instance.tabMap.delete(this._lastTab); } this._lastTab = this.tab; (this._mainCont as any).InitTab = (tab: any) => this.init(tab, this._document); @@ -565,11 +535,11 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> { docFilters={CollectionDockingView.Instance.childDocFilters} docRangeFilters={CollectionDockingView.Instance.childDocRangeFilters} searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs} - fitContentsToBox={returnTrue} + fitContentsToDoc={returnTrue} /> <div className="miniOverlay" onPointerDown={this.miniDown} > <div className="miniThumb" style={{ width: `${miniWidth}% `, height: `${miniHeight}% `, left: `${miniLeft}% `, top: `${miniTop}% `, }} /> </div> </div>; } -}
\ No newline at end of file +} diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 59dc5671b..23b6a7f72 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -216,11 +216,8 @@ export class TreeView extends React.Component<TreeViewProps> { this.props.hierarchyIndex !== undefined && this.props.RemFromMap?.(this.doc, this.props.hierarchyIndex); } - componentDidUpdate() { - this.props.hierarchyIndex !== undefined && this.props.AddToMap?.(this.doc, this.props.hierarchyIndex); - } - componentDidMount() { + // TODO: [AL] add these this.props.hierarchyIndex !== undefined && this.props.AddToMap?.(this.doc, this.props.hierarchyIndex); } @@ -471,7 +468,7 @@ export class TreeView extends React.Component<TreeViewProps> { const docs = expandKey === "aliases" ? this.childAliases : expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs; let downX = 0, downY = 0; return <> - {!docs?.length || this.props.AddToMap /* hack to identify pres box trees */ ? (null) : <div className={'treeView-sorting'} style={{ background: sortings[sorting]?.color }} > + {!docs?.length ? (null) : <div className={'treeView-sorting'} style={{ background: sortings[sorting]?.color }} > {sortings[sorting]?.label} </div>} <ul key={expandKey + "more"} title="click to change sort order" className={this.doc.treeViewHideTitle ? "no-indent" : ""} @@ -609,11 +606,13 @@ export class TreeView extends React.Component<TreeViewProps> { return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label })); } + // TODO: currently doc focus works, but can't seem to edit title + // onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick)); onChildClick = () => { - return this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!); + return this.props.onChildClick?.() ?? (ScriptField.MakeFunction(`DocFocusOrOpen(self)`)! || this._editTitleScript?.()); } - onChildDoubleClick = () => ScriptCast(this.props.treeView.Document.treeViewChildDoubleClick,(!this.props.treeView.outlineMode ? this._openScript?.():null)); + onChildDoubleClick = () => (!this.props.treeView.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick); refocus = () => this.props.treeView.props.focus(this.props.treeView.props.Document); ignoreEvent = (e: any) => { @@ -796,7 +795,7 @@ export class TreeView extends React.Component<TreeViewProps> { isDocumentActive={isActive} styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider} hideTitle={asText} - fitContentsToBox={returnTrue} + fitContentsToDoc={returnTrue} hideDecorationTitle={this.props.treeView.outlineMode} hideResizeHandles={this.props.treeView.outlineMode} onClick={this.onChildClick} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 52e99f26b..12ad6b02b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -9,7 +9,7 @@ import { InkData, InkField, InkTool, PointData, Segment } from "../../../../fiel import { List } from "../../../../fields/List"; import { ObjectField } from "../../../../fields/ObjectField"; import { RichTextField } from "../../../../fields/RichTextField"; -import { listSpec } from "../../../../fields/Schema"; +import { createSchema, listSpec } from "../../../../fields/Schema"; import { ScriptField } from "../../../../fields/ScriptField"; import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../fields/Types"; import { ImageField } from "../../../../fields/URLField"; @@ -26,7 +26,6 @@ import { DragManager, dropActionType } from "../../../util/DragManager"; import { HistoryUtil } from "../../../util/History"; import { InteractionUtils } from "../../../util/InteractionUtils"; import { LinkManager } from "../../../util/LinkManager"; -import { RecordingApi } from "../../../util/RecordingApi"; import { ScriptingGlobals } from "../../../util/ScriptingGlobals"; import { SearchUtil } from "../../../util/SearchUtil"; import { SelectionManager } from "../../../util/SelectionManager"; @@ -42,7 +41,6 @@ import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveIn import { LightboxView } from "../../LightboxView"; import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView"; import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment, ViewSpecPrefix } from "../../nodes/DocumentView"; -import { FieldViewProps } from "../../nodes/FieldView"; import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox"; import { PresBox } from "../../nodes/trails/PresBox"; import { VideoBox } from "../../nodes/VideoBox"; @@ -52,14 +50,26 @@ import { CollectionDockingView } from "../CollectionDockingView"; import { CollectionSubView } from "../CollectionSubView"; import { TreeViewType } from "../CollectionTreeView"; import { CollectionViewType } from "../CollectionView"; -import { TabDocView } from "../TabDocView"; import { computePivotLayout, computerPassLayout, computerStarburstLayout, computeTimelineLayout, PoolData, ViewDefBounds, ViewDefResult } from "./CollectionFreeFormLayoutEngines"; import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors"; import "./CollectionFreeFormView.scss"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); -import e = require("connect-flash"); - +import { FieldView, FieldViewProps } from "../../nodes/FieldView"; + +export const panZoomSchema = createSchema({ + _panX: "number", + _panY: "number", + _currentTimecode: "number", + _timecodeToShow: "number", + _currentFrame: "number", + _useClusters: "boolean", + _viewTransition: "string", + _xPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set + _yPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set + _fitToBox: "boolean", + scrollHeight: "number" // this will be set when the collection is an annotation overlay for a PDF/Webpage +}); export type collectionFreeformViewProps = { annotationLayerHostsContent?: boolean; // whether to force scaling of content (needed by ImageBox) @@ -127,20 +137,16 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection this.props.PanelWidth() / (this.contentBounds.r - this.contentBounds.x)) }; } - @computed get fitContentsToBox() { return (this.props.fitContentsToBox?.() || this.Document._fitContentsToBox) && !this.isAnnotationOverlay; } - @computed get contentBounds() { - const cb = Cast(this.rootDoc.contentBounds, listSpec("number")); - return cb ? {x:cb[0], y:cb[1], r:cb[2], b: cb[3]} : - this.props.contentBounds?.() ?? aggregateBounds(this._layoutElements.filter(e => e.bounds && !e.bounds.z).map(e => e.bounds!), NumCast(this.layoutDoc._xPadding, 10), NumCast(this.layoutDoc._yPadding, 10)); - } - @computed get nativeWidth() { return this.fitContentsToBox ? 0 : Doc.NativeWidth(this.Document, Cast(this.Document.resolvedDataDoc, Doc, null)); } - @computed get nativeHeight() { return this.fitContentsToBox ? 0 : Doc.NativeHeight(this.Document, Cast(this.Document.resolvedDataDoc, Doc, null)); } + @computed get fitToContent() { return (this.props.fitContentsToDoc?.() || this.Document._fitToBox) && !this.isAnnotationOverlay; } + @computed get contentBounds() { return aggregateBounds(this._layoutElements.filter(e => e.bounds && !e.bounds.z).map(e => e.bounds!), NumCast(this.layoutDoc._xPadding, 10), NumCast(this.layoutDoc._yPadding, 10)); } + @computed get nativeWidth() { return this.fitToContent ? 0 : Doc.NativeWidth(this.Document); } + @computed get nativeHeight() { return this.fitToContent ? 0 : Doc.NativeHeight(this.Document); } @computed get cachedCenteringShiftX(): number { - const scaling = this.fitContentsToBox || !this.contentScaling ? 1 : this.contentScaling; + const scaling = this.fitToContent || !this.contentScaling ? 1 : this.contentScaling; return this.props.isAnnotationOverlay ? 0 : this.props.PanelWidth() / 2 / scaling; // shift so pan position is at center of window for non-overlay collections } @computed get cachedCenteringShiftY(): number { - const scaling = this.fitContentsToBox || !this.contentScaling ? 1 : this.contentScaling; + const scaling = this.fitToContent || !this.contentScaling ? 1 : this.contentScaling; return this.props.isAnnotationOverlay ? 0 : this.props.PanelHeight() / 2 / scaling;// shift so pan position is at center of window for non-overlay collections } @computed get cachedGetLocalTransform(): Transform { @@ -165,13 +171,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection this.layoutDoc._panY = vals.bounds.cy; this.layoutDoc._viewScale = vals.scale; } - freeformData = (force?: boolean) => !this._firstRender && (this.fitContentsToBox || force) ? this.fitToContentVals : undefined; - reverseNativeScaling = () => this.fitContentsToBox ? true : false; - // panx, pany, zoomscale all attempt to get values first from the layout controller, then from the layout/dataDoc (or template layout doc), and finally from the resolved template data document. - // this search order, for example, allows icons of cropped images to find the panx/pany/zoom on the cropped image's data doc instead of the usual layout doc because the zoom/panX/panY define the cropped image - panX = () => this.freeformData()?.bounds.cx ?? NumCast(this.Document._panX, NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.panX, 1)); - panY = () => this.freeformData()?.bounds.cy ?? NumCast(this.Document._panY, NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.panY, 1)); - zoomScaling = () => this.freeformData()?.scale ?? NumCast(Doc.Layout(this.Document)[this.scaleFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.[this.scaleFieldKey], 1)); + freeformData = (force?: boolean) => !this._firstRender && (this.fitToContent || force) ? this.fitToContentVals : undefined; + reverseNativeScaling = () => this.fitToContent ? true : false; + panX = () => this.freeformData()?.bounds.cx ?? NumCast(this.Document._panX); + panY = () => this.freeformData()?.bounds.cy ?? NumCast(this.Document._panY); + zoomScaling = () => (this.freeformData()?.scale ?? NumCast(this.Document[this.scaleFieldKey], 1)); contentTransform = () => !this.cachedCenteringShiftX && !this.cachedCenteringShiftY && this.zoomScaling() === 1 ? "" : `translate(${this.cachedCenteringShiftX}px, ${this.cachedCenteringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`; getTransform = () => this.cachedGetTransform.copy(); getLocalTransform = () => this.cachedGetLocalTransform.copy(); @@ -998,16 +1002,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection @action setPan(panX: number, panY: number, panTime: number = 0, clamp: boolean = false) { - // set the current respective FFview to the tab being panned. - (Doc.UserDoc()?.presentationMode === 'recording') && RecordingApi.Instance.setRecordingFFView(this); - // TODO: make this based off the specific recording FFView - (Doc.UserDoc()?.presentationMode === 'none') && RecordingApi.Instance.setPlayFFView(this); - if (Doc.UserDoc()?.presentationMode === 'watching') { - RecordingApi.Instance.pauseVideoAndMovements(); - Doc.UserDoc().presentationMode = 'none'; - // RecordingApi.Instance.pauseMovements() - } - if (!this.isAnnotationOverlay && clamp) { // this section wraps the pan position, horizontally and/or vertically whenever the content is panned out of the viewing bounds const docs = this.childLayoutPairs.map(pair => pair.layout).filter(doc => doc instanceof Doc); @@ -1234,6 +1228,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection Document={childLayout} renderDepth={this.props.renderDepth + 1} replica={entry.replica} + dataTransition={entry.transition} suppressSetHeight={this.layoutEngine ? true : false} renderCutoffProvider={this.renderCutoffProvider} ContainingCollectionView={this.props.CollectionView} @@ -1273,7 +1268,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection dontRegisterView={this.props.dontRenderDocuments || this.props.dontRegisterView} pointerEvents={this.pointerEvents} jitterRotation={this.props.styleProvider?.(childLayout, this.props, StyleProp.JitterRotation) || 0} - //fitContentsToBox={this.props.fitContentsToBox || BoolCast(this.props.freezeChildDimensions)} // bcz: check this + //fitToBox={this.props.fitToBox || BoolCast(this.props.freezeChildDimensions)} // bcz: check this />; } addDocTab = action((doc: Doc, where: string) => { @@ -1416,9 +1411,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection bounds: this.childDataProvider(entry[1].pair.layout, entry[1].replica) })); - if (this.props.isAnnotationOverlay && this.props.Document[this.scaleFieldKey]) { // don't zoom out farther than 1-1 if it's a bounded item (image, video, pdf), otherwise don't allow zooming in closer than 1-1 if it's a text sidebar - if (this.props.scaleField) this.props.Document[this.scaleFieldKey] = Math.min(1, this.zoomScaling()); - else this.props.Document[this.scaleFieldKey] = Math.max(1,this.zoomScaling()); // NumCast(this.props.Document[this.scaleFieldKey])); + if (this.props.isAnnotationOverlay) { // don't zoom out farther than 1-1 if it's a bounded item (image, video, pdf), otherwise don't allow zooming in closer than 1-1 if it's a text sidebar + if (this.props.scaleField) this.props.Document[this.scaleFieldKey] = Math.min(1, NumCast(this.props.Document[this.scaleFieldKey], 1)); + else this.props.Document[this.scaleFieldKey] = Math.max(1, NumCast(this.props.Document[this.scaleFieldKey])); } this.Document._useClusters && !this._clusterSets.length && this.childDocs.length && this.updateClusters(true); @@ -1495,71 +1490,51 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection })); } - static replaceCanvases(oldDiv: HTMLElement, newDiv: HTMLElement) { + replaceCanvases = (oldDiv: HTMLElement, newDiv: HTMLElement) => { if (oldDiv.childNodes && newDiv) { for (let i = 0; i < oldDiv.childNodes.length; i++) { this.replaceCanvases(oldDiv.childNodes[i] as HTMLElement, newDiv.childNodes[i] as HTMLElement); } } if (oldDiv instanceof HTMLCanvasElement) { - if (oldDiv.className === "collectionFreeFormView-grid") { - const newCan = newDiv as HTMLCanvasElement; - const parEle = newCan.parentElement as HTMLElement; - parEle.removeChild(newCan); - parEle.appendChild(document.createElement('div')) - } else { - const canvas = oldDiv; - const img = document.createElement('img'); // create a Image Element - img.src = canvas.toDataURL(); //image source - img.style.width = canvas.style.width; - img.style.height = canvas.style.height; - const newCan = newDiv as HTMLCanvasElement; - const parEle = newCan.parentElement as HTMLElement; - parEle.removeChild(newCan); - parEle.appendChild(img); - } + const canvas = oldDiv; + const img = document.createElement('img'); // create a Image Element + img.src = canvas.toDataURL(); //image source + img.style.width = canvas.style.width; + img.style.height = canvas.style.height; + const newCan = newDiv as HTMLCanvasElement; + const parEle = newCan.parentElement as HTMLElement; + parEle.removeChild(newCan); + parEle.appendChild(img); } } - updateIcon = () => CollectionFreeFormView.UpdateIcon( - this.layoutDoc[Id] + "-icon" + (new Date()).getTime(), - this.props.docViewPath().lastElement().ContentDiv!, - this.layoutDoc[WidthSym](), this.layoutDoc[HeightSym](), - this.props.PanelWidth(), this.props.PanelHeight(), 0, 1, false, "", - (iconFile, nativeWidth, nativeHeight) => { - this.dataDoc.icon = new ImageField(iconFile); - this.dataDoc["icon-nativeWidth"] = nativeWidth; - this.dataDoc["icon-nativeHeight"] = nativeHeight; - }); - - public static UpdateIcon( - filename:string, docViewContent:HTMLElement, - width: number, height: number, - panelWidth:number, panelHeight: number, - scrollTop:number, - realNativeHeight: number, - noSuffix: boolean, - replaceRootFilename: string| undefined, - cb:(iconFile:string, nativeWidth:number, nativeHeight:number) => any) - { + updateIcon = () => { + const docViewContent = this.props.docViewPath().lastElement().ContentDiv!; const newDiv = docViewContent.cloneNode(true) as HTMLDivElement; - newDiv.style.width = width.toString(); - newDiv.style.height = height.toString(); + newDiv.style.width = (this.layoutDoc[WidthSym]()).toString(); + newDiv.style.height = (this.layoutDoc[HeightSym]()).toString(); this.replaceCanvases(docViewContent, newDiv); - const htmlString = new XMLSerializer().serializeToString(newDiv); - const nativeWidth = width; - const nativeHeight = height; - return CreateImage( - Utils.prepend(""), + const htmlString = this._mainCont && new XMLSerializer().serializeToString(newDiv); + const nativeWidth = this.layoutDoc[WidthSym](); + const nativeHeight = this.layoutDoc[HeightSym](); + + CreateImage( + "", document.styleSheets, htmlString, nativeWidth, - nativeWidth * panelHeight / panelWidth, - scrollTop * panelHeight / realNativeHeight + nativeWidth * this.props.PanelHeight() / this.props.PanelWidth(), + NumCast(this.layoutDoc._scrollTop) ).then - (async (data_url: any) => { - const returnedFilename = await VideoBox.convertDataUri(data_url, filename, noSuffix, replaceRootFilename); - cb(returnedFilename as string, nativeWidth, nativeHeight); + ((data_url: any) => { + VideoBox.convertDataUri(data_url, this.layoutDoc[Id] + "-icon" + (new Date()).getTime(), true, this.layoutDoc[Id] + "-icon").then( + returnedfilename => setTimeout(action(() => { + + this.dataDoc.icon = new ImageField(returnedfilename); + this.dataDoc["icon-nativeWidth"] = nativeWidth; + this.dataDoc["icon-nativeHeight"] = nativeHeight; + }), 500)); }) .catch(function (error: any) { console.error('oops, something went wrong!', error); @@ -1630,9 +1605,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection const appearanceItems = appearance && "subitems" in appearance ? appearance.subitems : []; appearanceItems.push({ description: "Reset View", event: () => { this.props.Document._panX = this.props.Document._panY = 0; this.props.Document[this.scaleFieldKey] = 1; }, icon: "compress-arrows-alt" }); !Doc.UserDoc().noviceMode && Doc.UserDoc().defaultTextLayout && appearanceItems.push({ description: "Reset default note style", event: () => Doc.UserDoc().defaultTextLayout = undefined, icon: "eye" }); - appearanceItems.push({ description: `${this.fitContentsToBox ? "Make Zoomable" : "Scale to Window"}`, event: () => this.Document._fitContentsToBox = !this.fitContentsToBox, icon: !this.fitContentsToBox ? "expand-arrows-alt" : "compress-arrows-alt" }); - appearanceItems.push({ description: `Pin View`, event: () => TabDocView.PinDoc(this.rootDoc, {pinDocView:true, panelWidth: this.props.PanelWidth(), panelHeight:this.props.PanelHeight()}), icon: "map-pin" }); - //appearanceItems.push({ description: `update icon`, event: this.updateIcon, icon: "compress-arrows-alt" }); + appearanceItems.push({ description: `${this.fitToContent ? "Make Zoomable" : "Scale to Window"}`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" }); + appearanceItems.push({ description: `update icon`, event: this.updateIcon, icon: "compress-arrows-alt" }); this.props.ContainingCollectionView && appearanceItems.push({ description: "Ungroup collection", event: this.promoteCollection, icon: "table" }); @@ -1788,7 +1762,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection isAnnotationOverlay={this.isAnnotationOverlay}> <div className="marqueeView-div" ref={this._marqueeRef} style={{ opacity: this.props.dontRenderDocuments ? 0 : undefined }}> {this.layoutDoc._backgroundGridShow ? - <div><CollectionFreeFormBackgroundGrid // bcz : UGHH don't know why, but if we don't wrap in a div, then PDF's don't render whenn taking snapshot of a dashboard and the background grid is on!!? + <CollectionFreeFormBackgroundGrid PanelWidth={this.props.PanelWidth} PanelHeight={this.props.PanelHeight} panX={this.panX} @@ -1798,7 +1772,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection isAnnotationOverlay={this.isAnnotationOverlay} cachedCenteringShiftX={this.cachedCenteringShiftX} cachedCenteringShiftY={this.cachedCenteringShiftY} - /></div> : (null)} + /> : (null)} <CollectionFreeFormViewPannableContents isAnnotationOverlay={this.isAnnotationOverlay} isAnnotationOverlayScrollable={this.props.isAnnotationOverlayScrollable} diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 051da795f..7865f2381 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -19,7 +19,7 @@ import { Transform } from "../../../util/Transform"; import { undoBatch, UndoManager } from "../../../util/UndoManager"; import { ContextMenu } from "../../ContextMenu"; import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox"; -import { PinViewProps, PresBox } from "../../nodes/trails/PresBox"; +import { PresBox } from "../../nodes/trails/PresBox"; import { PresMovement } from "../../nodes/trails/PresEnums"; import { VideoBox } from "../../nodes/VideoBox"; import { pasteImageBitmap } from "../../nodes/WebBoxRenderer"; @@ -30,7 +30,6 @@ import { TreeView } from "../TreeView"; import { MarqueeOptionsMenu } from "./MarqueeOptionsMenu"; import "./MarqueeView.scss"; import React = require("react"); -import { TabDocView } from "../TabDocView"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -44,14 +43,6 @@ interface MarqueeViewProps { ungroup?: () => void; setPreviewCursor?: (func: (x: number, y: number, drag: boolean, hide: boolean) => void) => void; } - -export interface MarqueeViewBounds { - left: number; - top: number; - width: number; - height: number; -} - @observer export class MarqueeView extends React.Component<SubCollectionViewProps & MarqueeViewProps> { @@ -70,8 +61,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque const topLeft = this.Transform.transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY); // nda - args to transformDirection is just x and y diff btw downX/Y and lastX/Y const size = this.Transform.transformDirection(this._lastX - this._downX, this._lastY - this._downY); - const bounds:MarqueeViewBounds = { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) } - return bounds; + return { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) }; } get inkDoc() { return this.props.Document; } get ink() { return Cast(this.props.Document.ink, InkField); } @@ -274,7 +264,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque document.removeEventListener("wheel", hideMarquee); }; if (PresBox.startMarquee) { - this.pinWithView(); + this.pinMarqueeView(); PresBox.startMarquee = false; } if (!this._commandExecuted && (Math.abs(this.Bounds.height * this.Bounds.width) > 100) && !PresBox.startMarquee) { @@ -395,23 +385,98 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque this.hideMarquee(); } - /** - * This triggers the TabDocView.PinDoc method which is the universal method - * used to pin documents to the currently active presentation trail. - * - * This one is unique in that it includes the bounds associated with marquee view. - */ @undoBatch @action - pinWithView = async () => { - const scale = Math.min(this.props.PanelWidth() / this.Bounds.width, this.props.PanelHeight() / this.Bounds.height); - const doc = this.props.Document; - const viewOptions:PinViewProps = { - bounds: this.Bounds, - scale: scale - }; - TabDocView.PinDoc(doc, {pinWithView: viewOptions}); - MarqueeOptionsMenu.Instance.fadeOut(true); + pinMarqueeView = async () => { + const doc = this.props.Document; + const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc; + if (curPres) { + console.log(curPres); + if (doc === curPres) { alert("Cannot pin presentation document to itself"); return; } + const pinDoc = Doc.MakeAlias(doc); + pinDoc.presentationTargetDoc = doc; + pinDoc.presMovement = PresMovement.Zoom; + pinDoc.groupWithUp = false; + pinDoc.context = curPres; + pinDoc.title = doc.title + " - Slide";// these should potentially all be props passed down by the CollectionTreeView to the TreeView elements. That way the PresBox could configure all of its children at render time + pinDoc.treeViewRenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area + pinDoc.treeViewHeaderWidth = "100%"; // forces the header to grow to be the same size as its largest sibling. + pinDoc.treeViewChildrenOnRoot = true; // tree view will look for hierarchical children on the root doc, not the data doc. + pinDoc.treeViewFieldKey = "data"; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field + pinDoc.treeViewExpandedView = "data";// in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view + pinDoc.treeViewGrowsHorizontally = true;// the document expands horizontally when displayed as a tree view header + pinDoc.treeViewHideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header + + const presArray = PresBox.Instance?.sortArray(); + const size = PresBox.Instance?._selectedArray.size; + const presSelected = presArray && size ? presArray[size - 1] : undefined; + Doc.AddDocToList(curPres, "data", pinDoc, presSelected); + if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true; + const dview = CollectionDockingView.Instance.props.Document; + const fieldKey = CollectionDockingView.Instance.props.fieldKey; + const tabdocs = await DocListCastAsync(dview[fieldKey]); + if (!tabdocs?.includes(curPres)) { + tabdocs?.push(curPres); // bcz: Argh! this is annoying. if multiple documents are pinned, this will get called multiple times before the presentation view is drawn. Thus it won't be in the tabdocs list and it will get created multple times. so need to explicilty add the presbox to the list of open tabs + CollectionDockingView.AddSplit(curPres, "right"); + } + PresBox.Instance?._selectedArray.clear(); + pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Updates selected array + const index = PresBox.Instance?.childDocs.indexOf(pinDoc); + index && (curPres._itemIndex = index); + const scale = Math.min(this.props.PanelWidth() / this.Bounds.width, this.props.PanelHeight() / this.Bounds.height); + pinDoc.presPinView = true; + pinDoc.presPinViewX = this.Bounds.left + this.Bounds.width / 2; + pinDoc.presPinViewY = this.Bounds.top + this.Bounds.height / 2; + pinDoc.presPinViewScale = scale; + } + this.hideMarquee(); + } + + @undoBatch + @action + pinWithView = async (e: KeyboardEvent | React.PointerEvent | undefined) => { + const doc = this.props.Document; + const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc; + if (curPres) { + if (doc === curPres) { alert("Cannot pin presentation document to itself"); return; } + const pinDoc = Doc.MakeAlias(doc); + pinDoc.presentationTargetDoc = doc; + pinDoc.presMovement = PresMovement.Zoom; + pinDoc.groupWithUp = false; + pinDoc.context = curPres; + pinDoc.title = doc.title + " - Slide"; + pinDoc.treeViewRenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area + pinDoc.treeViewHeaderWidth = "100%"; // forces the header to grow to be the same size as its largest sibling. + pinDoc.treeViewChildrenOnRoot = true; // tree view will look for hierarchical children on the root doc, not the data doc. + pinDoc.treeViewFieldKey = "data"; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field + pinDoc.treeViewExpandedView = "data";// in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view + pinDoc.treeViewGrowsHorizontally = true;// the document expands horizontally when displayed as a tree view header + pinDoc.treeViewHideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header + + const presArray = PresBox.Instance?.sortArray(); + const size = PresBox.Instance?._selectedArray.size; + const presSelected = presArray && size ? presArray[size - 1] : undefined; + Doc.AddDocToList(curPres, "data", pinDoc, presSelected); + if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true; const dview = CollectionDockingView.Instance.props.Document; + const fieldKey = CollectionDockingView.Instance.props.fieldKey; + const tabdocs = await DocListCastAsync(dview[fieldKey]); + if (!tabdocs?.includes(curPres)) { + tabdocs?.push(curPres); // bcz: Argh! this is annoying. if multiple documents are pinned, this will get called multiple times before the presentation view is drawn. Thus it won't be in the tabdocs list and it will get created multple times. so need to explicilty add the presbox to the list of open tabs + CollectionDockingView.AddSplit(curPres, "right"); + } + PresBox.Instance?._selectedArray.clear(); + pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Updates selected array + const index = PresBox.Instance?.childDocs.indexOf(pinDoc); + index && (curPres._itemIndex = index); + if (e instanceof KeyboardEvent ? e.key === "c" : true) { + const scale = Math.min(this.props.PanelWidth() / this.Bounds.width, this.props.PanelHeight() / this.Bounds.height); + pinDoc.presPinView = true; + pinDoc.presPinViewX = this.Bounds.left + this.Bounds.width / 2; + pinDoc.presPinViewY = this.Bounds.top + this.Bounds.height / 2; + pinDoc.presPinViewScale = scale; + } + } + MarqueeOptionsMenu.Instance.fadeOut(true); this.hideMarquee(); } @@ -434,7 +499,6 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque })); this.props.removeDocument?.(selected); } - // TODO: nda - this is the code to actually get a new grouped collection const newCollection = this.getCollection(selected, (e as KeyboardEvent)?.key === "t" ? Docs.Create.StackingDocument : undefined, group); this.props.addDocument?.(newCollection); this.props.selectDocuments([newCollection]); @@ -517,7 +581,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque d.y = NumCast(d.y) - this.Bounds.top; return d; }); - const summary = Docs.Create.TextDocument("", { _backgroundColor: "#e2ad32", x: this.Bounds.left, y: this.Bounds.top, isPushpin: true, _width: 200, _height: 200, _fitContentsToBox: true, _showSidebar: true, title: "overview" }); + const summary = Docs.Create.TextDocument("", { _backgroundColor: "#e2ad32", x: this.Bounds.left, y: this.Bounds.top, isPushpin: true, _width: 200, _height: 200, _fitToBox: true, _showSidebar: true, title: "overview" }); const portal = Docs.Create.FreeformDocument(selected, { x: this.Bounds.left + 200, y: this.Bounds.top, isGroup: true, backgroundColor: "transparent" }); DocUtils.MakeLink({ doc: summary }, { doc: portal }, "summary of:summarized by", ""); diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx index 9b1cb1601..c0a33a5e0 100644 --- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx +++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx @@ -153,7 +153,6 @@ export class CollectionLinearView extends CollectionSubView() { PanelWidth={nested ? doc[WidthSym] : this.dimension} PanelHeight={nested || doc._height ? doc[HeightSym] : this.dimension} renderDepth={this.props.renderDepth + 1} - dontRegisterView={BoolCast(this.rootDoc.childDontRegisterViews)} focus={emptyFunction} styleProvider={this.props.styleProvider} docViewPath={returnEmptyDoclist} diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index b7ba94940..e2dfb25e2 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -257,7 +257,7 @@ export class CollectionMulticolumnView extends CollectionSubView() { isDocumentActive={this.props.childDocumentsActive?.() ? this.props.isDocumentActive : this.isContentActive} hideResizeHandles={this.props.childHideResizeHandles?.()} hideDecorationTitle={this.props.childHideDecorationTitle?.()} - fitContentsToBox={this.props.fitContentsToBox} + fitContentsToDoc={this.props.fitContentsToDoc} PanelWidth={width} PanelHeight={height} rootSelected={this.rootSelected} @@ -272,7 +272,6 @@ export class CollectionMulticolumnView extends CollectionSubView() { 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} removeDocument={this.props.removeDocument} diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index 338639a83..3010e36aa 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -264,14 +264,13 @@ export class CollectionMultirowView extends CollectionSubView() { isDocumentActive={this.props.childDocumentsActive?.() ? this.props.isDocumentActive : this.isContentActive} hideResizeHandles={this.props.childHideResizeHandles?.()} hideDecorationTitle={this.props.childHideDecorationTitle?.()} - fitContentsToBox={this.props.fitContentsToBox} + fitContentsToDoc={this.props.fitContentsToDoc} focus={this.props.focus} 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} removeDocument={this.props.removeDocument} diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index f45068b6a..b731479a5 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -402,7 +402,7 @@ export class CollectionSchemaView extends CollectionSubView() { <DocumentView Document={this.previewDocument} DataDoc={undefined} - fitContentsToBox={returnTrue} + fitContentsToDoc={returnTrue} freezeDimensions={true} dontCenter={"y"} focus={DocUtils.DefaultFocus} |
