diff options
33 files changed, 278 insertions, 236 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index dc911ea75..2670de7a6 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -128,19 +128,24 @@ export class DocumentManager { } - static addRightSplit = (doc: Doc, finished?: () => void) => { - CollectionDockingView.AddSplit(doc, "right"); - finished?.(); + static addView = (doc: Doc, finished?: () => void, presCollection?: Doc) => { + if (presCollection) { + const collectionDocView = DocumentManager.Instance.getDocumentView(presCollection); + if (collectionDocView) collectionDocView.props.addDocTab(doc, "replace"); + } else { + CollectionDockingView.AddSplit(doc, "right"); + finished?.(); + } } public jumpToDocument = async ( targetDoc: Doc, // document to display willZoom: boolean, // whether to zoom doc to take up most of screen - createViewFunc = DocumentManager.addRightSplit, // how to create a view of the doc if it doesn't exist + createViewFunc = DocumentManager.addView, // how to create a view of the doc if it doesn't exist docContext?: Doc, // context to load that should contain the target linkDoc?: Doc, // link that's being followed closeContextIfNotFound: boolean = false, // after opening a context where the document should be, this determines whether the context should be closed if the Doc isn't actually there originatingDoc: Opt<Doc> = undefined, // doc that initiated the display of the target odoc - finished?: () => void + finished?: () => void, ): Promise<void> => { const getFirstDocView = DocumentManager.Instance.getFirstDocumentView; const focusAndFinish = () => { finished?.(); return false; }; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 3a0f306f3..9e91b4f55 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -201,7 +201,14 @@ export namespace DragManager { } // drag a document and drop it (or make an alias/copy on drop) - export function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { + export function StartDocumentDrag( + eles: HTMLElement[], + dragData: DocumentDragData, + downX: number, + downY: number, + options?: DragOptions, + dropEvent?: () => any + ) { const addAudioTag = (dropDoc: any) => { dropDoc && !dropDoc.creationDate && (dropDoc.creationDate = new DateField); dropDoc instanceof Doc && DocUtils.MakeLinkToActiveAudio(dropDoc); @@ -209,6 +216,7 @@ export namespace DragManager { }; const finishDrag = (e: DragCompleteEvent) => { const docDragData = e.docDragData; + if (dropEvent) dropEvent(); // glr: optional additional function to be called - in this case with presentation trails if (docDragData && !docDragData.droppedDocuments.length) { docDragData.dropAction = dragData.userDropAction || dragData.dropAction; docDragData.droppedDocuments = diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 66f0dd99d..4dcae8e60 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -327,8 +327,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height) { this._inkDocs.push({ x: doc.x, y: doc.y, width: doc._width, height: doc._height }); if (InkStrokeProperties.Instance?._lock) { - doc._nativeHeight = doc._height; - doc._nativeWidth = doc._width; + Doc.SetNativeHeight(doc, doc._height); + Doc.SetNativeWidth(doc, doc._width); } } })); @@ -356,11 +356,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> onPointerMove = (e: PointerEvent, down: number[], move: number[]): boolean => { const first = SelectionManager.SelectedDocuments()[0]; let thisPt = { thisX: e.clientX - this._offX, thisY: e.clientY - this._offY }; - var fixedAspect = first.layoutDoc._nativeWidth ? NumCast(first.layoutDoc._nativeWidth) / NumCast(first.layoutDoc._nativeHeight) : 0; + var fixedAspect = Doc.NativeAspect(first.layoutDoc); SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => { const doc = Document(element.rootDoc); if (doc.type === DocumentType.INK && doc._width && doc._height && InkStrokeProperties.Instance?._lock) { - fixedAspect = NumCast(doc._nativeWidth) / NumCast(doc._nativeHeight); + fixedAspect = Doc.NativeHeight(doc); } })); @@ -394,7 +394,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> ((element.rootDoc.type === DocumentType.RTF || element.rootDoc.type === DocumentType.COMPARISON || (element.rootDoc.type === DocumentType.WEB && Doc.LayoutField(element.rootDoc) instanceof HtmlField)) - && element.layoutDoc._nativeHeight) && element.toggleNativeDimensions())); + && Doc.NativeHeight(element.layoutDoc)) && element.toggleNativeDimensions())); switch (this._resizeHdlId) { case "": break; case "documentDecorations-topLeftResizer": @@ -440,11 +440,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } SelectionManager.SelectedDocuments().forEach(action((docView: DocumentView) => { - if (e.ctrlKey && !docView.props.Document._nativeHeight) docView.toggleNativeDimensions(); + if (e.ctrlKey && !Doc.NativeHeight(docView.props.Document)) docView.toggleNativeDimensions(); if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) { const doc = Document(docView.rootDoc); - let nwidth = returnVal(docView.NativeWidth?.(), doc._nativeWidth); - let nheight = returnVal(docView.NativeHeight?.(), doc._nativeHeight); + let nwidth = returnVal(docView.NativeWidth?.(), Doc.NativeWidth(doc)); + let nheight = returnVal(docView.NativeHeight?.(), Doc.NativeHeight(doc)); const width = (doc._width || 0); let height = (doc._height || (nheight / nwidth * width)); height = !height || isNaN(height) ? 20 : height; @@ -463,26 +463,23 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> doc.x = (doc.x || 0) + dX * (actualdW - width); doc.y = (doc.y || 0) + dY * (actualdH - height); const fixedAspect = (nwidth && nheight); - const fieldKey = docView.LayoutFieldKey; if (fixedAspect && (!nwidth || !nheight)) { - doc[DataSym][fieldKey + "-nativeWidth"] = doc._nativeWidth = nwidth = doc._width || 0; - doc[DataSym][fieldKey + "-nativeHeight"] = doc._nativeHeight = nheight = doc._height || 0; + doc._nativeWidth = nwidth = doc._width || 0; + doc._nativeHeight = nheight = doc._height || 0; } - const anno = Cast(doc.annotationOn, Doc, null); - if (e.ctrlKey && (anno || doc.type === DocumentType.IMG)) { + if (e.ctrlKey && [DocumentType.IMG, DocumentType.SCREENSHOT, DocumentType.VID].includes(doc.type as DocumentType)) { dW !== 0 && runInAction(() => { - const dataDoc = (anno ?? doc)[DataSym]; - const annoFieldKey = Doc.LayoutFieldKey(anno ?? doc); - const nw = NumCast(dataDoc[annoFieldKey + "-nativeWidth"]); - const nh = NumCast(dataDoc[annoFieldKey + "-nativeHeight"]); - dataDoc[annoFieldKey + "-nativeWidth"] = nw + (dW > 0 ? 10 : -10); - dataDoc[annoFieldKey + "-nativeHeight"] = nh + (dW > 0 ? 10 : -10) * nh / nw; + const dataDoc = doc[DataSym]; + const nw = Doc.NativeWidth(dataDoc); + const nh = Doc.NativeHeight(dataDoc); + Doc.SetNativeWidth(dataDoc, nw + (dW > 0 ? 10 : -10)); + Doc.SetNativeHeight(dataDoc, nh + (dW > 0 ? 10 : -10) * nh / nw); }); } else if (nwidth > 0 && nheight > 0) { if (Math.abs(dW) > Math.abs(dH) || dragRight) { if (!fixedAspect || (dragRight && e.ctrlKey)) { - doc[DataSym][fieldKey + "-nativeWidth"] = doc._nativeWidth = actualdW / (doc._width || 1) * (doc._nativeWidth || 0); + doc._nativeWidth = actualdW / (doc._width || 1) * Doc.NativeWidth(doc); } doc._width = actualdW; if (fixedAspect && !doc._fitWidth) doc._height = nheight / nwidth * doc._width; @@ -490,7 +487,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } else { if (!fixedAspect || (dragBottom && (e.ctrlKey || docView.layoutDoc._fitWidth))) { - doc[DataSym][fieldKey + "-nativeHeight"] = doc._nativeHeight = actualdH / (doc._height || 1) * (doc._nativeHeight || 0); + doc._nativeHeight = actualdH / (doc._height || 1) * Doc.NativeHeight(doc); } doc._height = actualdH; if (fixedAspect && !doc._fitWidth) doc._width = nwidth / nheight * doc._height; diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 186406424..7e424d8f0 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -38,7 +38,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume this.props.Document._backgroundColor = "rgba(0,0,0,0.7)"; this.props.Document.mixBlendMode = "hard-light"; this.props.Document.color = "#9b9b9bff"; - this.props.Document._stayInCollection = true; + //this.props.Document._stayInCollection = true; this.props.Document.isInkMask = true; } @@ -190,8 +190,6 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume return ( <svg className="inkingStroke" - width={Math.max(width, height)} - height={Math.max(width, height)} style={{ pointerEvents: this.props.Document.isInkMask ? "all" : "none", transform: this.props.Document.isInkMask ? `translate(${InkingStroke.MaskDim / 2}px, ${InkingStroke.MaskDim / 2}px)` : undefined, diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 6bdb6e21f..39a4d293b 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -91,9 +91,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { docWidth = () => { if (this.selectedDoc) { const layoutDoc = this.selectedDoc; - const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]()); - if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.width - 20)); - return NumCast(layoutDoc._nativeWidth) ? Math.min(layoutDoc[WidthSym](), this.props.width - 20) : this.props.width - 20; + const aspect = Doc.NativeAspect(layoutDoc, undefined, !layoutDoc._fitWidth); + if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT * aspect, this.props.width - 20)); + return Doc.NativeWidth(layoutDoc) ? Math.min(layoutDoc[WidthSym](), this.props.width - 20) : this.props.width - 20; } else { return 0; } @@ -103,17 +103,13 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { docHeight = () => { if (this.selectedDoc && this.dataDoc) { const layoutDoc = this.selectedDoc; - return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, (() => { - const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]()); - if (aspect) return this.docWidth() * aspect; - return layoutDoc._fitWidth ? (!this.dataDoc._nativeHeight ? NumCast(this.props.height) : - Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth, - NumCast(this.props.height)))) : - NumCast(layoutDoc._height) ? NumCast(layoutDoc._height) : 50; - })())); - } else { - return 0; + return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, + Doc.NativeAspect(layoutDoc, undefined, true) ? this.docWidth() / Doc.NativeAspect(layoutDoc, undefined, true) : + layoutDoc._fitWidth ? (!Doc.NativeHeight(this.dataDoc) ? NumCast(this.props.height) : + Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc)) / Doc.NativeWidth(layoutDoc) || NumCast(this.props.height))) : + NumCast(layoutDoc._height) || 50)); } + return 0; } @computed get expandedField() { @@ -972,7 +968,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { </div> {this.openContexts ? <div className="propertiesView-contexts-content" >{this.contexts}</div> : null} </div> - {/* <div className="propertiesView-layout"> + <div className="propertiesView-layout"> <div className="propertiesView-layout-title" onPointerDown={action(() => this.openLayout = !this.openLayout)} style={{ backgroundColor: this.openLayout ? "black" : "" }}> @@ -982,7 +978,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { </div> </div> {this.openLayout ? <div className="propertiesView-layout-content" >{this.layoutPreview}</div> : null} - </div> */} + </div> </div>; } if (this.isPres) { diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx index 0eac5136a..b6ab3f0e0 100644 --- a/src/client/views/collections/CollectionLinearView.tsx +++ b/src/client/views/collections/CollectionLinearView.tsx @@ -129,7 +129,6 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { {this.childLayoutPairs.map((pair, ind) => { const nested = pair.layout._viewType === CollectionViewType.Linear; const dref = React.createRef<HTMLDivElement>(); - const nativeWidth = NumCast(pair.layout._nativeWidth, this.dimension()); const scalable = pair.layout.onClick || pair.layout.onDragStart; return <div className={`collectionLinearView-docBtn` + (scalable ? "-scalable" : "")} key={pair.layout[Id]} ref={dref} style={{ diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index b2b1b7d25..a4f5118d6 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -400,11 +400,11 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp if (targetDoc) { TabDocView.PinDoc(targetDoc, false); const activeDoc = PresBox.Instance.childDocs[PresBox.Instance.childDocs.length - 1]; - if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.RTF || targetDoc.type === DocumentType.WEB) { + if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.RTF || targetDoc.type === DocumentType.WEB || targetDoc._viewType === CollectionViewType.Stacking) { const scroll = targetDoc._scrollTop; activeDoc.presPinView = true; activeDoc.presPinViewScroll = scroll; - } else { + } else if ((targetDoc.type === DocumentType.COL && targetDoc._viewType === CollectionViewType.Freeform) || targetDoc.type === DocumentType.IMG) { const x = targetDoc._panX; const y = targetDoc._panY; const scale = targetDoc._viewScale; @@ -412,6 +412,10 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp activeDoc.presPinViewX = x; activeDoc.presPinViewY = y; activeDoc.presPinViewScale = scale; + } else if (targetDoc.type === DocumentType.COMPARISON) { + const width = targetDoc._clipWidth; + activeDoc.presPinClipWidth = width; + activeDoc.presPinView = true; } } } @@ -421,7 +425,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp const presPinWithViewIcon = <img src={`/assets/pinWithView.png`} style={{ margin: "auto", width: 19 }} />; const targetDoc = this.selectedDoc; {/* return (!targetDoc || (targetDoc._viewType !== CollectionViewType.Freeform && targetDoc.type !== DocumentType.IMG)) ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Pin to presentation trail with current view"}</div></>} placement="top"> */ } - return (targetDoc && (targetDoc._viewType === CollectionViewType.Freeform || targetDoc.type === DocumentType.IMG || targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF)) ? <Tooltip title={<><div className="dash-tooltip">{"Pin to presentation trail with current view"}</div></>} placement="top"> + return (targetDoc && (targetDoc._viewType === CollectionViewType.Freeform || targetDoc._viewType === CollectionViewType.Stacking || targetDoc.type === DocumentType.IMG || targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF || targetDoc.type === DocumentType.COMPARISON)) ? <Tooltip title={<><div className="dash-tooltip">{"Pin to presentation trail with current view"}</div></>} placement="top"> <button className="antimodeMenu-button" style={{ borderRight: "1px solid gray", borderLeft: "1px solid gray", justifyContent: 'center' }} onClick={() => this.pinWithView(targetDoc)}> {presPinWithViewIcon} @@ -529,7 +533,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu } get document() { return this.props.docView.props.Document; } @computed get dataField() { - return this.document[this.props.docView.LayoutFieldKey]; + return this.document[this.props.docView.LayoutFieldKey + (this.props.isOverlay ? "-annotations" : "")]; } @computed get childDocs() { return DocListCast(this.dataField); diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 2896a8243..0b3dfe1e4 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -398,10 +398,10 @@ export class CollectionSchemaImageCell extends CollectionSchemaCell { const paths = field ? [this.choosePath(field.url), ...altpaths] : altpaths; const url = paths.length ? paths : [Utils.CorsProxy("http://www.cs.brown.edu/~bcz/noImage.png")]; - const heightToWidth = NumCast(this._rowDoc._nativeHeight) / NumCast(this._rowDoc._nativeWidth); + const aspect = Doc.NativeAspect(this._rowDoc); let width = Math.min(75, this.props.rowProps.width); - const height = Math.min(75, width * heightToWidth); - width = height / heightToWidth; + const height = Math.min(75, width / aspect); + width = height * aspect; const reference = React.createRef<HTMLDivElement>(); return <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}> diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index fc4ca3100..b62fde4c8 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -59,7 +59,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument, @computed get numGroupColumns() { return this.isStackingView ? Math.max(1, this.Sections.size + (this.showAddAGroup ? 1 : 0)) : 1; } @computed get showAddAGroup() { return (this.pivotField && (this.chromeStatus !== 'view-mode' && this.chromeStatus !== 'disabled')); } @computed get columnWidth() { - return Math.min(this.props.PanelWidth() / this.props.ContentScaling() - 2 * this.xMargin, + return Math.min(this.props.PanelWidth() / this.props.ContentScaling() /* / NumCast(this.layoutDoc._viewScale, 1)*/ - 2 * this.xMargin, this.isStackingView ? Number.MAX_VALUE : this.layoutDoc._columnWidth === -1 ? this.props.PanelWidth() - 2 * this.xMargin : NumCast(this.layoutDoc._columnWidth, 250)); } @computed get NodeWidth() { return this.props.PanelWidth() - this.gridGap; } @@ -233,27 +233,27 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument, getDocWidth(d?: Doc) { if (!d) return 0; const layoutDoc = Doc.Layout(d, this.props.ChildLayoutTemplate?.()); - const nw = NumCast(layoutDoc._nativeWidth); + const nw = Doc.NativeWidth(layoutDoc); return Math.min(nw && !this.layoutDoc._columnsFill ? d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns); } getDocHeight(d?: Doc) { if (!d) return 0; - const dataDoc = (!d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS) ? undefined : this.props.DataDoc; - const layoutDoc = Doc.Layout(d, this.props.ChildLayoutTemplate?.()); - const layoutField = Doc.LayoutFieldKey(layoutDoc); - const nw = NumCast(layoutDoc._nativeWidth) || NumCast(dataDoc?.[`${layoutField}-nativeWidth`]); - const nh = NumCast(layoutDoc._nativeHeight) || NumCast(dataDoc?.[`${layoutField}-nativeHeight`]); + const childDataDoc = (!d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS) ? undefined : this.props.DataDoc; + const childLayoutDoc = Doc.Layout(d, this.props.ChildLayoutTemplate?.()); + const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc); + const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc); let wid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1); + if (!this.layoutDoc._columnsFill) wid = Math.min(wid, childLayoutDoc[WidthSym]()); const hllimit = NumCast(this.layoutDoc.childLimitHeight, -1); - if (!layoutDoc._fitWidth && nw && nh) { + if (!childLayoutDoc._fitWidth && nw && nh) { const aspect = nw && nh ? nh / nw : 1; if (!(this.layoutDoc._columnsFill)) wid = Math.min(this.getDocWidth(d), wid); return Math.min(hllimit === 0 ? this.props.PanelWidth() : hllimit === -1 ? 10000 : hllimit, wid * aspect); } - return layoutDoc._fitWidth ? + return childLayoutDoc._fitWidth ? (!nh ? this.props.PanelHeight() - 2 * this.yMargin : Math.min(wid * nh / (nw || 1), this.layoutDoc._autoHeight ? 100000 : this.props.PanelHeight() - 2 * this.yMargin)) : - Math.min(hllimit === 0 ? this.props.PanelWidth() : hllimit === -1 ? 10000 : hllimit, Math.max(20, layoutDoc[HeightSym]())); + Math.min(hllimit === 0 ? this.props.PanelWidth() : hllimit === -1 ? 10000 : hllimit, Math.max(20, childLayoutDoc[HeightSym]())); } columnDividerDown = (e: React.PointerEvent) => { @@ -465,8 +465,8 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument, } - @computed get nativeWidth() { return returnVal(this.props.NativeWidth?.(), NumCast(this.layoutDoc._nativeWidth)); } - @computed get nativeHeight() { return returnVal(this.props.NativeHeight?.(), NumCast(this.layoutDoc._nativeHeight)); } + @computed get nativeWidth() { return returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc)); } + @computed get nativeHeight() { return returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc)); } @computed get scaling() { return !this.nativeWidth ? 1 : this.props.PanelHeight() / this.nativeHeight; } diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 0c7f39dc7..cd84d2d78 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -191,14 +191,14 @@ export class TabDocView extends React.Component<TabDocViewProps> { } nativeAspect = () => this.nativeWidth() ? this.nativeWidth() / this.nativeHeight() : 0; - panelWidth = () => this.layoutDoc?.maxWidth ? Math.min(Math.max(NumCast(this.layoutDoc._width), NumCast(this.layoutDoc._nativeWidth)), this._panelWidth) : + panelWidth = () => this.layoutDoc?.maxWidth ? Math.min(Math.max(NumCast(this.layoutDoc._width), Doc.NativeWidth(this.layoutDoc)), this._panelWidth) : (this.nativeAspect() && this.nativeAspect() < this._panelWidth / this._panelHeight ? this._panelHeight * this.nativeAspect() : this._panelWidth) panelHeight = () => this.nativeAspect() && this.nativeAspect() > this._panelWidth / this._panelHeight ? this._panelWidth / this.nativeAspect() : this._panelHeight; - nativeWidth = () => !this.layoutDoc?._fitWidth ? NumCast(this.layoutDoc?._nativeWidth) || this._panelWidth : 0; - nativeHeight = () => !this.layoutDoc?._fitWidth ? NumCast(this.layoutDoc?._nativeHeight) || this._panelHeight : 0; + nativeWidth = () => !this.layoutDoc?._fitWidth ? Doc.NativeWidth(this.layoutDoc) || this._panelWidth : 0; + nativeHeight = () => !this.layoutDoc?._fitWidth ? Doc.NativeHeight(this.layoutDoc) || this._panelHeight : 0; ContentScaling = () => { - const nativeH = NumCast(this.layoutDoc?._nativeHeight); - const nativeW = NumCast(this.layoutDoc?._nativeWidth); + const nativeW = Doc.NativeWidth(this.layoutDoc); + const nativeH = Doc.NativeHeight(this.layoutDoc); let scaling = 1; if (nativeW && (this.layoutDoc?._fitWidth || this._panelHeight / nativeH > this._panelWidth / nativeW)) { scaling = this._panelWidth / nativeW; // width-limited or fitWidth diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 1dfa5615a..925eb4be6 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -279,21 +279,21 @@ export class TreeView extends React.Component<TreeViewProps> { getTransform = () => this.refTransform(this._tref.current!); docWidth = () => { const layoutDoc = this.layoutDoc; - const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]()); - if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.panelWidth() - 20)); - return NumCast(layoutDoc._nativeWidth) ? Math.min(layoutDoc[WidthSym](), this.props.panelWidth() - 20) : this.props.panelWidth() - 20; + const aspect = Doc.NativeAspect(layoutDoc); + if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT * aspect, this.props.panelWidth() - 20)); + return Doc.NativeWidth(layoutDoc) ? Math.min(layoutDoc[WidthSym](), this.props.panelWidth() - 20) : this.props.panelWidth() - 20; } docHeight = () => { const layoutDoc = this.layoutDoc; const bounds = this.boundsOfCollectionDocument; return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, (() => { - const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]()); - if (aspect) return this.docWidth() * aspect; + const aspect = Doc.NativeAspect(layoutDoc); + if (aspect) return this.docWidth() / (aspect || 1); if (bounds) return this.docWidth() * (bounds.b - bounds.y) / (bounds.r - bounds.x); - return layoutDoc._fitWidth ? (!this.doc._nativeHeight ? NumCast(this.props.containingCollection._height) : - Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth, - NumCast(this.props.containingCollection._height)))) : - NumCast(layoutDoc._height) ? NumCast(layoutDoc._height) : 50; + return layoutDoc._fitWidth ? (!Doc.NativeHeight(this.doc) ? NumCast(this.props.containingCollection._height) : + Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc)) / + (Doc.NativeWidth(layoutDoc) || NumCast(this.props.containingCollection._height)) + )) : (layoutDoc[HeightSym]() || 50); })())); } @@ -728,7 +728,7 @@ export class TreeView extends React.Component<TreeViewProps> { 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 = () => { - const aspect = NumCast(childLayout._nativeWidth, 0) / NumCast(childLayout._nativeHeight, 0); + const aspect = Doc.NativeAspect(childLayout); return aspect ? Math.min(childLayout[WidthSym](), rowWidth()) / aspect : childLayout[HeightSym](); }; return <TreeView key={child[Id]} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index bc2cb2d20..edf473a90 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -241,10 +241,10 @@ export function computePivotLayout( val.docs.forEach((doc, i) => { const layoutDoc = Doc.Layout(doc); let wid = pivotAxisWidth; - let hgt = layoutDoc._nativeWidth ? (NumCast(layoutDoc._nativeHeight) / NumCast(layoutDoc._nativeWidth)) * pivotAxisWidth : pivotAxisWidth; + let hgt = pivotAxisWidth / (Doc.NativeAspect(layoutDoc) || 1); if (hgt > pivotAxisWidth) { hgt = pivotAxisWidth; - wid = layoutDoc._nativeHeight ? (NumCast(layoutDoc._nativeWidth) / NumCast(layoutDoc._nativeHeight)) * pivotAxisWidth : pivotAxisWidth; + wid = (Doc.NativeAspect(layoutDoc) || 1) * pivotAxisWidth; } docMap.set(doc[Id] + (val.replicas || ""), { x: x + xCount * pivotAxisWidth * expander + (pivotAxisWidth - wid) / 2 + (val.docs.length < numCols ? (numCols - val.docs.length) * pivotAxisWidth / 2 : 0), @@ -368,10 +368,10 @@ export function computeTimelineLayout( const stack = findStack(x, stacking); const layoutDoc = Doc.Layout(doc); let wid = pivotAxisWidth; - let hgt = layoutDoc._nativeWidth ? (NumCast(layoutDoc._nativeHeight) / NumCast(layoutDoc._nativeWidth)) * pivotAxisWidth : pivotAxisWidth; + let hgt = pivotAxisWidth / (Doc.NativeAspect(layoutDoc) || 1); if (hgt > pivotAxisWidth) { hgt = pivotAxisWidth; - wid = layoutDoc._nativeHeight ? (NumCast(layoutDoc._nativeWidth) / NumCast(layoutDoc._nativeHeight)) * pivotAxisWidth : pivotAxisWidth; + wid = (Doc.NativeAspect(layoutDoc) || 1) * pivotAxisWidth; } docMap.set(doc[Id], { x: x, y: -Math.sqrt(stack) * pivotAxisWidth / 2 - pivotAxisWidth + (pivotAxisWidth - hgt) / 2, diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index b32a3bd52..56624f42d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -105,11 +105,11 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P @observable canPanY: boolean = true; @computed get fitToContentScaling() { return this.fitToContent ? NumCast(this.layoutDoc.fitToContentScaling, 1) : 1; } - @computed get fitToContent() { return this.props.fitToBox || (this.Document._fitToBox && !this.isAnnotationOverlay); } + @computed get fitToContent() { return (this.props.fitToBox || this.Document._fitToBox) && !this.isAnnotationOverlay; } @computed get parentScaling() { return this.props.ContentScaling && this.fitToContent ? this.props.ContentScaling() : 1; } @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 : returnVal(this.props.NativeWidth?.(), NumCast(this.Document._nativeWidth)); } - @computed get nativeHeight() { return this.fitToContent ? 0 : returnVal(this.props.NativeHeight?.(), NumCast(this.Document._nativeHeight)); } + @computed get nativeWidth() { return this.fitToContent ? 0 : returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.Document)); } + @computed get nativeHeight() { return this.fitToContent ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.Document)); } private get isAnnotationOverlay() { return this.props.isAnnotationOverlay; } private get scaleFieldKey() { return this.props.scaleField || "_viewScale"; } private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; } @@ -120,7 +120,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P if (this.fitToContent) { const zs = !this.childDocs.length ? 1 : Math.min(this.props.PanelHeight() / (this.contentBounds.b - this.contentBounds.y), this.props.PanelWidth() / (this.contentBounds.r - this.contentBounds.x)); - return mult * (this.props.isAnnotationOverlay ? Math.min(zs, 1) : zs); + return mult * zs; } return mult * NumCast(this.Document[this.scaleFieldKey], 1); } @@ -202,13 +202,15 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P @action internalDocDrop(e: Event, de: DragManager.DropEvent, docDragData: DragManager.DocumentDragData, xp: number, yp: number) { if (!super.onInternalDrop(e, de)) return false; + const refDoc = docDragData.droppedDocuments[0]; const [xpo, ypo] = this.getTransformOverlay().transformPoint(de.x, de.y); - const z = NumCast(docDragData.droppedDocuments[0].z); + const z = NumCast(refDoc.z); const x = (z ? xpo : xp) - docDragData.offset[0]; const y = (z ? ypo : yp) - docDragData.offset[1]; const zsorted = this.childLayoutPairs.map(pair => pair.layout).slice().sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex)); zsorted.forEach((doc, index) => doc.zIndex = doc.isInkMask ? 5000 : index + 1); - const dropPos = [NumCast(docDragData.droppedDocuments[0].x), NumCast(docDragData.droppedDocuments[0].y)]; + const dvals = CollectionFreeFormDocumentView.getValues(refDoc, NumCast(refDoc.activeFrame, 1000)); + const dropPos = this.Document._currentFrame !== undefined ? [dvals.x, dvals.y] : [NumCast(refDoc.x), NumCast(refDoc.y)]; for (let i = 0; i < docDragData.droppedDocuments.length; i++) { const d = docDragData.droppedDocuments[i]; const layoutDoc = Doc.Layout(d); @@ -219,7 +221,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P d.x = x + NumCast(d.x) - dropPos[0]; d.y = y + NumCast(d.y) - dropPos[1]; } - const nd = [NumCast(layoutDoc._nativeWidth), NumCast(layoutDoc._nativeHeight)]; + const nd = [Doc.NativeWidth(layoutDoc), Doc.NativeHeight(layoutDoc)]; layoutDoc._width = NumCast(layoutDoc._width, 300); layoutDoc._height = NumCast(layoutDoc._height, nd[0] && nd[1] ? nd[1] / nd[0] * NumCast(layoutDoc._width) : 300); !d._isBackground && (d._raiseWhenDragged === undefined ? Doc.UserDoc()._raiseWhenDragged : d._raiseWhenDragged) && (d.zIndex = zsorted.length + 1 + i); // bringToFront @@ -925,8 +927,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P const savedState = { px: this.Document._panX, py: this.Document._panY, s: this.Document[this.scaleFieldKey], pt: this.Document._viewTransition }; willZoom && this.setScaleToZoom(layoutdoc, scale); - const newPanX = (NumCast(doc.x) + doc[WidthSym]() / 2) - (this.isAnnotationOverlay ? (NumCast(this.props.Document._nativeWidth)) / 2 / this.zoomScaling() : 0); - const newPanY = (NumCast(doc.y) + doc[HeightSym]() / 2) - (this.isAnnotationOverlay ? (NumCast(this.props.Document._nativeHeight)) / 2 / this.zoomScaling() : 0); + const newPanX = (NumCast(doc.x) + doc[WidthSym]() / 2) - (this.isAnnotationOverlay ? (Doc.NativeWidth(this.props.Document)) / 2 / this.zoomScaling() : 0); + const newPanY = (NumCast(doc.y) + doc[HeightSym]() / 2) - (this.isAnnotationOverlay ? (Doc.NativeHeight(this.props.Document)) / 2 / this.zoomScaling() : 0); const newState = HistoryUtil.getState(); newState.initializers![this.Document[Id]] = { panX: newPanX, panY: newPanY }; HistoryUtil.pushState(newState); @@ -954,8 +956,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P } setScaleToZoom = (doc: Doc, scale: number = 0.75) => { - const pw = this.isAnnotationOverlay ? NumCast(this.props.Document._nativeWidth) : this.props.PanelWidth(); - const ph = this.isAnnotationOverlay ? NumCast(this.props.Document._nativeHeight) : this.props.PanelHeight(); + const pw = this.isAnnotationOverlay ? Doc.NativeWidth(this.props.Document) : this.props.PanelWidth(); + const ph = this.isAnnotationOverlay ? Doc.NativeHeight(this.props.Document) : this.props.PanelHeight(); pw && ph && (this.Document[this.scaleFieldKey] = scale * Math.min(pw / NumCast(doc._width), ph / NumCast(doc._height))); } @@ -979,7 +981,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P LayoutTemplate: childLayout.z ? undefined : this.props.ChildLayoutTemplate, LayoutTemplateString: childLayout.z ? undefined : this.props.ChildLayoutString, FreezeDimensions: this.props.freezeChildDimensions, - layoutKey: StrCast(this.props.Document.childLayoutKey), setupDragLines: this.setupDragLines, dontRegisterView: this.props.dontRegisterView, rootSelected: childData ? this.rootSelected : returnFalse, @@ -1297,7 +1298,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P optionItems.push({ description: this.layoutDoc._lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: this.layoutDoc._lockedTransform ? "unlock" : "lock" }); this.props.renderDepth && optionItems.push({ description: "Use Background Color as Default", event: () => Cast(Doc.UserDoc().emptyCollection, Doc, null)._backgroundColor = StrCast(this.layoutDoc._backgroundColor), icon: "palette" }); if (!Doc.UserDoc().noviceMode) { - optionItems.push({ description: (!this.layoutDoc._nativeWidth || !this.layoutDoc._nativeHeight ? "Freeze" : "Unfreeze") + " Aspect", event: this.toggleNativeDimensions, icon: "snowflake" }); + optionItems.push({ description: (!Doc.NativeWidth(this.layoutDoc) || !Doc.NativeHeight(this.layoutDoc) ? "Freeze" : "Unfreeze") + " Aspect", event: this.toggleNativeDimensions, icon: "snowflake" }); optionItems.push({ description: `${this.Document._freeformLOD ? "Enable LOD" : "Disable LOD"}`, event: () => this.Document._freeformLOD = !this.Document._freeformLOD, icon: "table" }); } @@ -1454,8 +1455,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P @computed get contentScaling() { if (this.props.annotationsKey && !this.props.forceScaling) return 0; - const nw = returnVal(this.props.NativeWidth?.(), NumCast(this.Document._nativeWidth)); - const nh = returnVal(this.props.NativeHeight?.(), NumCast(this.Document._nativeHeight)); + const nw = returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.Document)); + const nh = returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.Document)); const hscale = nh ? this.props.PanelHeight() / nh : 1; const wscale = nw ? this.props.PanelWidth() / nw : 1; return wscale < hscale ? wscale : hscale; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 5a8ce4e14..7d5c224bd 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -55,8 +55,8 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF @computed get freezeDimensions() { return this.props.FreezeDimensions; } @computed get dataProvider() { return this.props.dataProvider?.(this.props.Document, this.props.replica); } @computed get sizeProvider() { return this.props.sizeProvider?.(this.props.Document, this.props.replica); } - @computed get nativeWidth() { return returnVal(this.props.NativeWidth?.(), NumCast(this.layoutDoc._nativeWidth, this.freezeDimensions ? this.layoutDoc[WidthSym]() : 0)); } - @computed get nativeHeight() { return returnVal(this.props.NativeHeight?.(), NumCast(this.layoutDoc._nativeHeight, this.freezeDimensions ? this.layoutDoc[HeightSym]() : 0)); } + @computed get nativeWidth() { return returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, undefined, this.freezeDimensions)); } + @computed get nativeHeight() { return returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, undefined, this.freezeDimensions)); } public static getValues(doc: Doc, time: number) { const timecode = Math.round(time); diff --git a/src/client/views/nodes/ComparisonBox.scss b/src/client/views/nodes/ComparisonBox.scss index acf6b1636..44cf5d046 100644 --- a/src/client/views/nodes/ComparisonBox.scss +++ b/src/client/views/nodes/ComparisonBox.scss @@ -13,6 +13,7 @@ left: 0; height: 100%; overflow: hidden; + transition: 200ms; .beforeBox-cont { height: 100%; @@ -26,6 +27,7 @@ width: 3px; display: inline-block; background: white; + transition: 200ms; .slide-handle { position: absolute; diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index 09051da78..bc3926ff4 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -22,12 +22,8 @@ export class ContentFittingDocumentView extends React.Component<DocumentViewProp } @computed get freezeDimensions() { return this.props.FreezeDimensions; } - nativeWidth = () => returnVal(this.props.NativeWidth?.(), - NumCast(this.layoutDoc?._nativeWidth || this.props.DataDoc?.[Doc.LayoutFieldKey(this.layoutDoc) + "-nativeWidth"], - (this.freezeDimensions && this.layoutDoc ? this.layoutDoc[WidthSym]() : this.props.PanelWidth()))) - nativeHeight = () => returnVal(this.props.NativeHeight?.(), - NumCast(this.layoutDoc?._nativeHeight || this.props.DataDoc?.[Doc.LayoutFieldKey(this.layoutDoc) + "-nativeHeight"], - (this.freezeDimensions && this.layoutDoc ? this.layoutDoc[HeightSym]() : this.props.PanelHeight()))) + nativeWidth = () => returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || this.props.PanelWidth()); + nativeHeight = () => returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || this.props.PanelHeight()); @computed get scaling() { const wscale = this.props.PanelWidth() / this.nativeWidth(); const hscale = this.props.PanelHeight() / this.nativeHeight(); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index e980322d5..d227d3a8e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -129,8 +129,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu } @computed get topMost() { return this.props.renderDepth === 0; } @computed get freezeDimensions() { return this.props.FreezeDimensions; } - @computed get nativeWidth() { return returnVal(this.props.NativeWidth?.(), NumCast(this.layoutDoc[(this.props.DataDoc ? this.LayoutFieldKey + "-" : "_") + "nativeWidth"], (this.freezeDimensions ? this.layoutDoc[WidthSym]() : 0))); } - @computed get nativeHeight() { return returnVal(this.props.NativeHeight?.(), NumCast(this.layoutDoc[(this.props.DataDoc ? this.LayoutFieldKey + "-" : "_") + "nativeHeight"], (this.freezeDimensions ? this.layoutDoc[HeightSym]() : 0))); } + @computed get nativeWidth() { return returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.dataDoc, this.freezeDimensions)); } + @computed get nativeHeight() { return returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.dataDoc, this.freezeDimensions)); } @computed get onClickHandler() { return this.props.onClick?.() ?? Cast(this.Document.onClick, ScriptField, Cast(this.layoutDoc.onClick, ScriptField, null)); } @computed get onDoubleClickHandler() { return this.props.onDoubleClick?.() ?? (Cast(this.layoutDoc.onDoubleClick, ScriptField, null) ?? this.Document.onDoubleClick); } @computed get onPointerDownHandler() { return this.props.onPointerDown?.() ?? ScriptCast(this.Document.onPointerDown); } @@ -494,8 +494,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) { const doc = Document(this.props.Document); const layoutDoc = Document(Doc.Layout(this.props.Document)); - let nwidth = layoutDoc._nativeWidth || 0; - let nheight = layoutDoc._nativeHeight || 0; + let nwidth = Doc.NativeWidth(layoutDoc); + let nheight = Doc.NativeHeight(layoutDoc); const width = (layoutDoc._width || 0); const height = (layoutDoc._height || (nheight / nwidth * width)); const scale = this.props.ScreenToLocalTransform().Scale * this.props.ContentScaling(); @@ -505,13 +505,13 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu doc.y = (doc.y || 0) + dY * (actualdH - height); const fixedAspect = e.ctrlKey || (nwidth && nheight); if (fixedAspect && (!nwidth || !nheight)) { - layoutDoc._nativeWidth = nwidth = layoutDoc._width || 0; - layoutDoc._nativeHeight = nheight = layoutDoc._height || 0; + Doc.SetNativeWidth(layoutDoc, nwidth = layoutDoc._width || 0); + Doc.SetNativeHeight(layoutDoc, nheight = layoutDoc._height || 0); } if (nwidth > 0 && nheight > 0) { if (Math.abs(dW) > Math.abs(dH)) { if (!fixedAspect) { - layoutDoc._nativeWidth = actualdW / (layoutDoc._width || 1) * (layoutDoc._nativeWidth || 0); + Doc.SetNativeWidth(layoutDoc, actualdW / (layoutDoc._width || 1) * Doc.NativeWidth(layoutDoc)); } layoutDoc._width = actualdW; if (fixedAspect && !layoutDoc._fitWidth) layoutDoc._height = nheight / nwidth * layoutDoc._width; @@ -519,7 +519,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu } else { if (!fixedAspect) { - layoutDoc._nativeHeight = actualdH / (layoutDoc._height || 1) * (doc._nativeHeight || 0); + Doc.SetNativeHeight(layoutDoc, actualdH / (layoutDoc._height || 1) * Doc.NativeHeight(doc)); } layoutDoc._height = actualdH; if (fixedAspect && !layoutDoc._fitWidth) layoutDoc._width = nwidth / nheight * layoutDoc._height; @@ -754,8 +754,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu this.props.bringToFront(this.props.Document, true); const wid = this.Document[WidthSym](); // change the nativewidth and height if the background is to be a collection that aggregates stuff that is added to it. const hgt = this.Document[HeightSym](); - this.props.Document[DataSym][this.LayoutFieldKey + "-nativeWidth"] = wid; - this.props.Document[DataSym][this.LayoutFieldKey + "-nativeHeight"] = hgt; + Doc.SetNativeWidth(this.props.Document[DataSym], wid); + Doc.SetNativeHeight(this.props.Document[DataSym], hgt); } } @@ -907,7 +907,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu const excluded = ["PresBox", /* "FormattedTextBox", */ "FontIconBox"]; // bcz: shifting the title for texst causes problems with collaborative use when some people see titles, and others don't return !excluded.includes(StrCast(this.layoutDoc.layout)); } - chromeHeight = () => this.showOverlappingTitle ? 1 : 25; + chromeHeight = () => this.showOverlappingTitle ? 0 : 25; @computed get finalLayoutKey() { if (typeof this.props.layoutKey === "string") { diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index bc38a17eb..88dc3b241 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -76,14 +76,11 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD componentDidMount() { this._pathDisposer = reaction(() => ({ nativeSize: this.nativeSize, width: this.layoutDoc[WidthSym]() }), - ({ nativeSize, width }) => { - if (this.props.NativeWidth?.() !== 0 || !this.layoutDoc._height) { - this.layoutDoc._nativeWidth = nativeSize.nativeWidth; - this.layoutDoc._nativeHeight = nativeSize.nativeHeight; - this.layoutDoc._nativeOrientation = nativeSize.nativeOrientation; + action(({ nativeSize, width }) => { + if (!this.layoutDoc._height) { this.layoutDoc._height = width * nativeSize.nativeHeight / nativeSize.nativeWidth; } - }, + }), { fireImmediately: true }); } @@ -106,8 +103,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD const targetDoc = layoutDoc[DataSym]; if (targetDoc[targetField] instanceof ImageField) { this.dataDoc[this.fieldKey] = ObjectField.MakeCopy(targetDoc[targetField] as ImageField); - this.dataDoc[this.fieldKey + "-nativeWidth"] = NumCast(targetDoc[targetField + "-nativeWidth"]); - this.dataDoc[this.fieldKey + "-nativeHeight"] = NumCast(targetDoc[targetField + "-nativeHeight"]); + Doc.SetNativeWidth(this.dataDoc, Doc.NativeWidth(targetDoc)); + Doc.SetNativeWidth(this.dataDoc, Doc.NativeHeight(targetDoc)); e.stopPropagation(); } } diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 79e00eed7..42b24f6f6 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -50,8 +50,8 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum constructor(props: any) { super(props); this._initialScale = this.props.ScreenToLocalTransform().Scale; - const nw = this.Document._nativeWidth = NumCast(this.dataDoc[this.props.fieldKey + "-nativeWidth"], NumCast(this.Document._nativeWidth, 927)); - const nh = this.Document._nativeHeight = NumCast(this.dataDoc[this.props.fieldKey + "-nativeHeight"], NumCast(this.Document._nativeHeight, 1200)); + const nw = Doc.NativeWidth(this.Document, this.dataDoc) || 927; + const nh = Doc.NativeHeight(this.Document, this.dataDoc) || 1200; !this.Document._fitWidth && (this.Document._height = this.Document[WidthSym]() * (nh / nw)); const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField); if (pdfUrl) { @@ -97,8 +97,9 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum loaded = (nw: number, nh: number, np: number) => { this.dataDoc[this.props.fieldKey + "-numPages"] = np; - this.dataDoc[this.props.fieldKey + "-nativeWidth"] = this.Document._nativeWidth = Math.max(NumCast(this.dataDoc[this.props.fieldKey + "-nativeWidth"]), nw * 96 / 72); - this.dataDoc[this.props.fieldKey + "-nativeHeight"] = this.Document._nativeHeight = nh * 96 / 72; + Doc.SetNativeWidth(this.dataDoc, Math.max(Doc.NativeWidth(this.dataDoc), nw * 96 / 72)); + Doc.SetNativeHeight(this.dataDoc, nh * 96 / 72); + this.layoutDoc._height = this.layoutDoc[WidthSym]() / (Doc.NativeAspect(this.dataDoc) || 1); !this.Document._fitWidth && (this.Document._height = this.Document[WidthSym]() * (nh / nw)); } @@ -254,7 +255,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField); return <div className={"pdfBox"} onContextMenu={this.specificContextMenu} style={{ height: this.props.Document._scrollTop && !this.Document._fitWidth && (window.screen.width > 600) ? NumCast(this.Document._height) * this.props.PanelWidth() / NumCast(this.Document._width) : undefined }}> <div className="pdfBox-background"></div> - <PDFViewer {...this.props} pdf={this._pdf!} url={pdfUrl!.url.pathname} active={this.props.active} loaded={this.loaded} + <PDFViewer {...this.props} pdf={this._pdf!} url={pdfUrl!.url.pathname} active={this.props.active} loaded={!Doc.NativeAspect(this.dataDoc) ? this.loaded : undefined} setPdfViewer={this.setPdfViewer} ContainingCollectionView={this.props.ContainingCollectionView} renderDepth={this.props.renderDepth} PanelHeight={this.props.PanelHeight} PanelWidth={this.props.PanelWidth} addDocTab={this.props.addDocTab} focus={this.props.focus} searchFilterDocs={this.props.searchFilterDocs} diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 8e3679452..01a7bed8c 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -46,6 +46,12 @@ export enum PresEffect { None = "none", } +enum PresStatus { + Autoplay = "auto", + Manual = "manual", + Edit = "edit" +} + type PresBoxSchema = makeInterface<[typeof documentSchema]>; const PresBoxDocument = makeInterface(documentSchema); @@ -75,6 +81,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @computed get itemIndex() { return NumCast(this.rootDoc._itemIndex); } @computed get activeItem() { return Cast(this.childDocs[this.itemIndex], Doc, null); } @computed get targetDoc() { return Cast(this.activeItem?.presentationTargetDoc, Doc, null); } + @computed get scrollable(): boolean { + if (this.targetDoc.type === DocumentType.PDF || this.targetDoc.type === DocumentType.WEB || this.targetDoc.type === DocumentType.RTF || this.targetDoc._viewType === CollectionViewType.Stacking) return true; + else return false; + } + @computed get panable(): boolean { + if ((this.targetDoc.type === DocumentType.COL && this.targetDoc._viewType === CollectionViewType.Freeform) || this.targetDoc.type === DocumentType.IMG) return true; + else return false; + } @computed get presElement() { return Cast(Doc.UserDoc().presElement, Doc, null); } constructor(props: any) { super(props); @@ -117,7 +131,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> this.rootDoc.presBox = this.rootDoc; this.rootDoc._forceRenderEngine = "timeline"; this.rootDoc._replacedChrome = "replaced"; - this.layoutDoc.presStatus = "edit"; + this.layoutDoc.presStatus = PresStatus.Edit; this.layoutDoc._gridGap = 0; this.layoutDoc._yMargin = 0; this.turnOffEdit(true); @@ -156,7 +170,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> else targetDoc.editing = true; // if (activeItem.zoomProgressivize) this.zoomProgressivizeNext(targetDoc); // Case 2: 'Play on next' for audio or video therefore first navigate to the audio/video before it should be played - } else if ((targetDoc.type === DocumentType.AUDIO || targetDoc.type === DocumentType.VID) && !activeItem.playAuto && activeItem.playNow && this.layoutDoc.presStatus !== 'auto') { + } else if ((targetDoc.type === DocumentType.AUDIO || targetDoc.type === DocumentType.VID) && !activeItem.playAuto && activeItem.playNow && this.layoutDoc.presStatus !== PresStatus.Autoplay) { if (targetDoc.type === DocumentType.AUDIO) AudioBox.Instance.playFrom(NumCast(activeItem.presStartTime)); // if (targetDoc.type === DocumentType.VID) { VideoBox.Instance.Play() }; activeItem.playNow = false; @@ -256,7 +270,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> const targetDoc: Doc = this.targetDoc; const srcContext = await DocCastAsync(targetDoc.context); const presCollection = Cast(this.layoutDoc.presCollection, Doc, null); - const collectionDocView = presCollection ? await DocumentManager.Instance.getDocumentView(presCollection) : undefined; + const collectionDocView = presCollection ? DocumentManager.Instance.getDocumentView(presCollection) : undefined; this.turnOffEdit(); if (this.itemIndex >= 0) { if (srcContext && targetDoc) { @@ -272,21 +286,23 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> this.updateCurrentPresentation(); const docToJump = curDoc; const willZoom = false; - + const openInTab = () => { + collectionDocView ? collectionDocView.props.addDocTab(activeItem, "replace") : this.props.addDocTab(activeItem, "replace:left"); + }; // If openDocument is selected then it should open the document for the user if (activeItem.openDocument) { - collectionDocView ? collectionDocView.props.addDocTab(activeItem, "replace") : this.props.addDocTab(activeItem, "replace:left"); + openInTab(); } else //docToJump stayed same meaning, it was not in the group or was the last element in the group - if (activeItem.zoomProgressivize && this.rootDoc.presStatus !== 'edit') { + if (activeItem.zoomProgressivize && this.rootDoc.presStatus !== PresStatus.Edit) { this.zoomProgressivizeNext(targetDoc); } else if (docToJump === curDoc) { //checking if curDoc has navigation open if (curDoc.presMovement === PresMovement.Pan && targetDoc) { - await DocumentManager.Instance.jumpToDocument(targetDoc, false, undefined, srcContext); + await DocumentManager.Instance.jumpToDocument(targetDoc, false, openInTab, srcContext); // documents open in new tab instead of on right } else if ((curDoc.presMovement === PresMovement.Zoom || curDoc.presMovement === PresMovement.Jump) && targetDoc) { //awaiting jump so that new scale can be found, since jumping is async - await DocumentManager.Instance.jumpToDocument(targetDoc, true, undefined, srcContext); + await DocumentManager.Instance.jumpToDocument(targetDoc, true, openInTab, srcContext); // documents open in new tab instead of on right } } else { //awaiting jump so that new scale can be found, since jumping is async @@ -301,6 +317,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> bestTarget && runInAction(() => { if (bestTarget.type === DocumentType.PDF || bestTarget.type === DocumentType.WEB || bestTarget.type === DocumentType.RTF || bestTarget._viewType === CollectionViewType.Stacking) { bestTarget._scrollY = activeItem.presPinViewScroll; + } else if (bestTarget.type === DocumentType.COMPARISON) { + bestTarget._clipWidth = activeItem.presPinClipWidth; } else { bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s'; bestTarget._panX = activeItem.presPinViewX; @@ -418,13 +436,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> if (i === this.childDocs.length - 1) { setTimeout(() => { clearTimeout(this._presTimer); - if (this.layoutDoc.presStatus === 'auto' && !this.layoutDoc.presLoop) this.layoutDoc.presStatus = "manual"; + if (this.layoutDoc.presStatus === 'auto' && !this.layoutDoc.presLoop) this.layoutDoc.presStatus = PresStatus.Manual; else if (this.layoutDoc.presLoop) this.startAutoPres(0); }, duration); } } }; - this.layoutDoc.presStatus = "auto"; + this.layoutDoc.presStatus = PresStatus.Autoplay; this.startPresentation(startSlide); this.gotoDocument(startSlide, this.itemIndex); load(); @@ -432,9 +450,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @action pauseAutoPres = () => { - if (this.layoutDoc.presStatus === "auto") { + if (this.layoutDoc.presStatus === PresStatus.Autoplay) { if (this._presTimer) clearTimeout(this._presTimer); - this.layoutDoc.presStatus = "manual"; + this.layoutDoc.presStatus = PresStatus.Manual; this.layoutDoc.presLoop = false; } } @@ -491,12 +509,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> updateMinimize = () => { const docView = DocumentManager.Instance.getDocumentView(this.layoutDoc); if (this.layoutDoc.inOverlay) { - this.layoutDoc.presStatus = 'edit'; + this.layoutDoc.presStatus = PresStatus.Edit; Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc); CollectionDockingView.AddSplit(this.rootDoc, "right"); this.layoutDoc.inOverlay = false; } else if (this.layoutDoc.context && docView) { - this.layoutDoc.presStatus = 'edit'; + this.layoutDoc.presStatus = PresStatus.Edit; clearTimeout(this._presTimer); const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); this.rootDoc.x = pt[0] + (this.props.PanelWidth() - 250); @@ -506,7 +524,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> docView.props.removeDocument?.(this.layoutDoc); Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc); } else { - this.layoutDoc.presStatus = 'edit'; + this.layoutDoc.presStatus = PresStatus.Edit; clearTimeout(this._presTimer); const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); this.rootDoc.x = pt[0] + (this.props.PanelWidth() - 250); @@ -593,7 +611,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> return true; } childLayoutTemplate = () => this.rootDoc._viewType !== CollectionViewType.Stacking ? undefined : this.presElement; - removeDocument = (doc: Doc) => { Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc); }; + removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc); getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight panelHeight = () => this.props.PanelHeight() - 40; active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc._isBackground) && @@ -662,7 +680,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> // Key for when the presentaiton is active @undoBatch - keyEvents = action((e: KeyboardEvent) => { + keyEvents = action(async (e: KeyboardEvent) => { if (e.target instanceof HTMLInputElement) return; let handled = false; const anchorNode = document.activeElement as HTMLDivElement; @@ -687,15 +705,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> if (this._presTimer) clearTimeout(this._presTimer); handled = true; } if (e.keyCode === 32) { // spacebar to 'present' or autoplay - if (this.layoutDoc.presStatus !== "edit") this.startAutoPres(0); - else this.next(); + if (this.layoutDoc.presStatus === "manual") this.startAutoPres(this.itemIndex); + else if (this.layoutDoc.presStatus === "auto") if (this._presTimer) clearTimeout(this._presTimer); handled = true; } if (e.keyCode === 8) { // delete selected items if (this.layoutDoc.presStatus === "edit") { - this._selectedArray.forEach((doc, i) => this.removeDocument(doc)); - this._selectedArray = []; - this._eleArray = []; - this._dragArray = []; + await Promise.all<boolean>(this._selectedArray.map((doc, i): boolean => { + const removed: boolean = this.removeDocument(doc); + console.log("Is removed? : " + i + " | " + removed); + return removed; + })); + action(() => this._selectedArray = []); + action(() => this._eleArray = []); + action(() => this._dragArray = []); handled = true; } } if (handled) { @@ -1755,7 +1777,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @computed get frameListHeader() { return (<div className="frameList-header"> - Frames + Frames {this.panable ? <i>Panable</i> : this.scrollable ? <i>Scrollable</i> : (null)} <div className={"frameList-headerButtons"}> <Tooltip title={<><div className="dash-tooltip">{"Add frame by example"}</div></>}><div className={"headerButton"} onClick={e => { e.stopPropagation(); this.newFrame(); }}> <FontAwesomeIcon icon={"plus"} onPointerDown={e => e.stopPropagation()} /> diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 16ce749bc..f467fef12 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, IReactionDisposer, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import * as rp from 'request-promise'; -import { Doc } from "../../../fields/Doc"; +import { Doc, WidthSym } from "../../../fields/Doc"; import { documentSchema } from "../../../fields/documentSchemas"; import { InkTool } from "../../../fields/InkField"; import { listSpec, makeInterface } from "../../../fields/Schema"; @@ -34,12 +34,12 @@ export class ScreenshotBox extends ViewBoxBaseComponent<FieldViewProps, Screensh videoLoad = () => { const aspect = this.player!.videoWidth / this.player!.videoHeight; - const nativeWidth = (this.layoutDoc._nativeWidth || 0); - const nativeHeight = (this.layoutDoc._nativeHeight || 0); + const nativeWidth = Doc.NativeWidth(this.layoutDoc); + const nativeHeight = Doc.NativeHeight(this.layoutDoc); if (!nativeWidth || !nativeHeight) { - if (!this.layoutDoc._nativeWidth) this.layoutDoc._nativeWidth = 400; - this.layoutDoc._nativeHeight = NumCast(this.layoutDoc._nativeWidth) / aspect; - this.layoutDoc._height = NumCast(this.layoutDoc._width) / aspect; + if (!nativeWidth) Doc.SetNativeWidth(this.dataDoc, 1200); + Doc.SetNativeHeight(this.dataDoc, (nativeWidth || 1200) / aspect); + this.layoutDoc._height = (this.layoutDoc[WidthSym]() || 0) / aspect; } } @@ -48,7 +48,7 @@ export class ScreenshotBox extends ViewBoxBaseComponent<FieldViewProps, Screensh const height = NumCast(this.layoutDoc._height); const canvas = document.createElement('canvas'); canvas.width = 640; - canvas.height = 640 * NumCast(this.layoutDoc._nativeHeight) / NumCast(this.layoutDoc._nativeWidth, 1); + canvas.height = 640 / (Doc.NativeAspect(this.layoutDoc) || 1); const ctx = canvas.getContext('2d');//draw image to canvas. scale to target dimensions if (ctx) { ctx.rect(0, 0, canvas.width, canvas.height); diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 998ddde9a..168c87764 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -6,7 +6,7 @@ import * as rp from 'request-promise'; import { Doc } from "../../../fields/Doc"; import { InkTool } from "../../../fields/InkField"; import { createSchema, makeInterface } from "../../../fields/Schema"; -import { Cast, StrCast } from "../../../fields/Types"; +import { Cast, StrCast, NumCast } from "../../../fields/Types"; import { VideoField } from "../../../fields/URLField"; import { Utils, emptyFunction, returnOne, returnZero, OmitKeys } from "../../../Utils"; import { Docs, DocUtils } from "../../documents/Documents"; @@ -51,8 +51,8 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD videoLoad = () => { const aspect = this.player!.videoWidth / this.player!.videoHeight; - this.layoutDoc._nativeWidth = this.player!.videoWidth; - this.layoutDoc._nativeHeight = (this.layoutDoc._nativeWidth || 0) / aspect; + Doc.SetNativeWidth(this.dataDoc, this.player!.videoWidth); + Doc.SetNativeHeight(this.dataDoc, this.player!.videoHeight); this.layoutDoc._height = (this.layoutDoc._width || 0) / aspect; this.dataDoc[this.fieldKey + "-" + "duration"] = this.player!.duration; } @@ -97,7 +97,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD const height = (this.layoutDoc._height || 0); const canvas = document.createElement('canvas'); canvas.width = 640; - canvas.height = 640 * (this.layoutDoc._nativeHeight || 0) / (this.layoutDoc._nativeWidth || 1); + canvas.height = 640 * Doc.NativeHeight(this.layoutDoc) / (Doc.NativeWidth(this.layoutDoc) || 1); const ctx = canvas.getContext('2d');//draw image to canvas. scale to target dimensions if (ctx) { // ctx.rect(0, 0, canvas.width, canvas.height); @@ -139,15 +139,15 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD private createRealSummaryLink = (relative: string) => { const url = this.choosePath(Utils.prepend(relative)); - const width = (this.layoutDoc._width || 0); - const height = (this.layoutDoc._height || 0); + const width = this.layoutDoc._width || 0; + const height = this.layoutDoc._height || 0; const imageSummary = Docs.Create.ImageDocument(url, { - _nativeWidth: this.layoutDoc._nativeWidth, _nativeHeight: this.layoutDoc._nativeHeight, + _nativeWidth: Doc.NativeWidth(this.layoutDoc), _nativeHeight: Doc.NativeHeight(this.layoutDoc), x: (this.layoutDoc.x || 0) + width, y: (this.layoutDoc.y || 0), _width: 150, _height: height / width * 150, title: "--snapshot" + (this.layoutDoc._currentTimecode || 0) + " image-" }); - Doc.GetProto(imageSummary)["data-nativeWidth"] = this.layoutDoc._nativeWidth; - Doc.GetProto(imageSummary)["data-nativeHeight"] = this.layoutDoc._nativeHeight; + Doc.SetNativeWidth(Doc.GetProto(imageSummary), Doc.NativeWidth(this.layoutDoc)); + Doc.SetNativeHeight(Doc.GetProto(imageSummary), Doc.NativeHeight(this.layoutDoc)); imageSummary.isLinkButton = true; this.props.addDocument?.(imageSummary); DocUtils.MakeLink({ doc: imageSummary }, { doc: this.rootDoc }, "video snapshot"); @@ -164,11 +164,11 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD if (this.youtubeVideoId) { const youtubeaspect = 400 / 315; - const nativeWidth = (this.layoutDoc._nativeWidth || 0); - const nativeHeight = (this.layoutDoc._nativeHeight || 0); + const nativeWidth = Doc.NativeWidth(this.layoutDoc); + const nativeHeight = Doc.NativeHeight(this.layoutDoc); if (!nativeWidth || !nativeHeight) { - if (!this.layoutDoc._nativeWidth) this.layoutDoc._nativeWidth = 600; - this.layoutDoc._nativeHeight = (this.layoutDoc._nativeWidth || 0) / youtubeaspect; + if (!nativeWidth) Doc.SetNativeWidth(this.dataDoc, 600); + Doc.SetNativeHeight(this.dataDoc, (nativeWidth || 600) / youtubeaspect); this.layoutDoc._height = (this.layoutDoc._width || 0) / youtubeaspect; } } @@ -346,17 +346,15 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD const style = "videoBox-content-YouTube" + (this._fullScreen ? "-fullScreen" : ""); const start = untracked(() => Math.round((this.layoutDoc._currentTimecode || 0))); return <iframe key={this._youtubeIframeId} id={`${this.youtubeVideoId + this._youtubeIframeId}-player`} - onLoad={this.youtubeIframeLoaded} className={`${style}`} width={(this.layoutDoc._nativeWidth || 640)} height={(this.layoutDoc._nativeHeight || 390)} + onLoad={this.youtubeIframeLoaded} className={`${style}`} width={Doc.NativeWidth(this.layoutDoc) || 640} height={Doc.NativeHeight(this.layoutDoc) || 390} src={`https://www.youtube.com/embed/${this.youtubeVideoId}?enablejsapi=1&rel=0&showinfo=1&autoplay=0&mute=1&start=${start}&modestbranding=1&controls=${VideoBox._showControls ? 1 : 0}`} />; } @action.bound addDocumentWithTimestamp(doc: Doc | Doc[]): boolean { const docs = doc instanceof Doc ? [doc] : doc; - docs.forEach(doc => { - const curTime = (this.layoutDoc._currentTimecode || -1); - curTime !== -1 && (doc.displayTimecode = curTime); - }); + const curTime = NumCast(this.layoutDoc._currentTimecode); + docs.forEach(doc => doc.displayTimecode = curTime); return this.addDocument(doc); } diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 66dc3cdcc..eb9e08e20 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -72,8 +72,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum constructor(props: any) { super(props); - this.dataDoc[this.fieldKey + "-nativeWidth"] = this.Document._nativeWidth = NumCast(this.dataDoc[this.props.fieldKey + "-nativeWidth"], NumCast(this.Document._nativeWidth, 850)); - this.dataDoc[this.fieldKey + "-nativeHeight"] = this.Document._nativeHeight = NumCast(this.dataDoc[this.props.fieldKey + "-nativeHeight"], NumCast(this.Document._nativeHeight, this.Document[HeightSym]() / this.Document[WidthSym]() * 850)); + Doc.SetNativeWidth(this.dataDoc, Doc.NativeWidth(this.dataDoc) || 850); + Doc.SetNativeHeight(this.dataDoc, Doc.NativeHeight(this.dataDoc) || this.Document[HeightSym]() / this.Document[WidthSym]() * 850); } iframeLoaded = action((e: any) => { @@ -151,13 +151,13 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum const field = Cast(this.rootDoc[this.props.fieldKey], WebField); if (field?.url.href.indexOf("youtube") !== -1) { const youtubeaspect = 400 / 315; - const nativeWidth = NumCast(this.layoutDoc._nativeWidth); - const nativeHeight = NumCast(this.layoutDoc._nativeHeight); + const nativeWidth = Doc.NativeWidth(this.layoutDoc); + const nativeHeight = Doc.NativeHeight(this.layoutDoc); if (field) { if (!nativeWidth || !nativeHeight || Math.abs(nativeWidth / nativeHeight - youtubeaspect) > 0.05) { - if (!nativeWidth) this.layoutDoc._nativeWidth = 600; - this.layoutDoc._nativeHeight = NumCast(this.layoutDoc._nativeWidth) / youtubeaspect; - this.layoutDoc._height = NumCast(this.layoutDoc._width) / youtubeaspect; + if (!nativeWidth) Doc.SetNativeWidth(this.layoutDoc, 600); + Doc.SetNativeHeight(this.layoutDoc, (nativeWidth || 600) / youtubeaspect); + this.layoutDoc._height = this.layoutDoc[WidthSym]() / youtubeaspect; } } // else it's an HTMLfield } else if (field?.url) { @@ -388,17 +388,11 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum } } - - @undoBatch - @action - toggleNativeDimensions = () => { - Doc.toggleNativeDimensions(this.layoutDoc, this.props.ContentScaling(), this.props.NativeWidth?.() || 0, this.props.NativeHeight?.() || 0); - } specificContextMenu = (e: React.MouseEvent): void => { const cm = ContextMenu.Instance; const funcs: ContextMenuProps[] = []; funcs.push({ description: (this.layoutDoc.useCors ? "Don't Use" : "Use") + " Cors", event: () => this.layoutDoc.useCors = !this.layoutDoc.useCors, icon: "snowflake" }); - funcs.push({ description: (this.layoutDoc[this.fieldKey + "-contentWidth"] ? "Unfreeze" : "Freeze") + " Content Width", event: () => this.layoutDoc[this.fieldKey + "-contentWidth"] = this.layoutDoc[this.fieldKey + "-contentWidth"] ? undefined : NumCast(this.layoutDoc._nativeWidth), icon: "snowflake" }); + funcs.push({ description: (this.layoutDoc[this.fieldKey + "-contentWidth"] ? "Unfreeze" : "Freeze") + " Content Width", event: () => this.layoutDoc[this.fieldKey + "-contentWidth"] = this.layoutDoc[this.fieldKey + "-contentWidth"] ? undefined : Doc.NativeWidth(this.layoutDoc), icon: "snowflake" }); cm.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" }); } @@ -468,7 +462,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum } @computed get annotationLayer() { TraceMobx(); - return <div className="webBox-annotationLayer" style={{ height: NumCast(this.Document._nativeHeight) }} ref={this._annotationLayer}> + return <div className="webBox-annotationLayer" style={{ height: Doc.NativeHeight(this.Document) }} ref={this._annotationLayer}> {this.nonDocAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).map(anno => <Annotation {...this.props} showInfo={emptyFunction} focus={this.props.focus} dataDoc={this.dataDoc} fieldKey={this.props.fieldKey} anno={anno} key={`${anno[Id]}-annotation`} />) } @@ -543,9 +537,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum else if (this._mainCont.current) { // set marquee x and y positions to the spatially transformed position const boundingRect = this._mainCont.current.getBoundingClientRect(); - const boundingHeight = (this.Document._nativeHeight || 1) / (this.Document._nativeWidth || 1) * boundingRect.width; - this._startX = (e.clientX - boundingRect.left) / boundingRect.width * (this.Document._nativeWidth || 1); - this._startY = (e.clientY - boundingRect.top) / boundingHeight * (this.Document._nativeHeight || 1); + const boundingHeight = (Doc.NativeHeight(this.Document) || 1) / (Doc.NativeWidth(this.Document) || 1) * boundingRect.width; + this._startX = (e.clientX - boundingRect.left) / boundingRect.width * (Doc.NativeWidth(this.Document) || 1); + this._startY = (e.clientY - boundingRect.top) / boundingHeight * (Doc.NativeHeight(this.Document) || 1); this._marqueeHeight = this._marqueeWidth = 0; this._marqueeing = true; } @@ -560,9 +554,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum if (this._marqueeing && this._mainCont.current) { // transform positions and find the width and height to set the marquee to const boundingRect = this._mainCont.current.getBoundingClientRect(); - const boundingHeight = (this.Document._nativeHeight || 1) / (this.Document._nativeWidth || 1) * boundingRect.width; - const curX = (e.clientX - boundingRect.left) / boundingRect.width * (this.Document._nativeWidth || 1); - const curY = (e.clientY - boundingRect.top) / boundingHeight * (this.Document._nativeHeight || 1); + const boundingHeight = (Doc.NativeHeight(this.Document) || 1) / (Doc.NativeWidth(this.Document) || 1) * boundingRect.width; + const curX = (e.clientX - boundingRect.left) / boundingRect.width * (Doc.NativeWidth(this.Document) || 1); + const curY = (e.clientY - boundingRect.top) / boundingHeight * (Doc.NativeHeight(this.Document) || 1); this._marqueeWidth = curX - this._startX; this._marqueeHeight = curY - this._startY; this._marqueeX = Math.min(this._startX, this._startX + this._marqueeWidth); @@ -622,7 +616,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum visibleHeiht = () => { if (this._mainCont.current) { const boundingRect = this._mainCont.current.getBoundingClientRect(); - const scalin = (this.Document._nativeWidth || 0) / boundingRect.width; + const scalin = (Doc.NativeWidth(this.Document) || 0) / boundingRect.width; return Math.min(boundingRect.height * scalin, this.props.PanelHeight() * scalin); } return this.props.PanelHeight(); diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx index 123946dea..7cd92b8b9 100644 --- a/src/client/views/nodes/formattedText/DashDocView.tsx +++ b/src/client/views/nodes/formattedText/DashDocView.tsx @@ -82,7 +82,7 @@ export class DashDocView extends React.Component<IDashDocView> { const { scale, translateX, translateY } = Utils.GetScreenTransform(outerElement); return new Transform(-translateX, -translateY, 1).scale(1 / this.contentScaling() / scale); } - contentScaling = () => NumCast(this._dashDoc!._nativeWidth) > 0 ? this._dashDoc![WidthSym]() / NumCast(this._dashDoc!._nativeWidth) : 1; + contentScaling = () => Doc.NativeWidth(this._dashDoc) > 0 ? this._dashDoc![WidthSym]() / Doc.NativeWidth(this._dashDoc) : 1; outerFocus = (target: Doc) => this._textBox.props.focus(this._textBox.props.Document); // ideally, this would scroll to show the focus target diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss index 0d92d7062..9307f1649 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.scss +++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss @@ -23,7 +23,6 @@ overflow-y: auto; overflow-x: hidden; color: initial; - max-height: 100%; display: flex; flex-direction: row; transition: opacity 1s; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 903bbaaa3..d44f35a96 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -663,7 +663,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const optionItems = options && "subitems" in options ? options.subitems : []; !Doc.UserDoc().noviceMode && optionItems.push({ description: !this.Document._singleLine ? "Make Single Line" : "Make Multi Line", event: () => this.layoutDoc._singleLine = !this.layoutDoc._singleLine, icon: "expand-arrows-alt" }); optionItems.push({ description: `${this.Document._autoHeight ? "Lock" : "Auto"} Height`, event: () => this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight, icon: "plus" }); - optionItems.push({ description: `${!this.layoutDoc._nativeWidth || !this.layoutDoc._nativeHeight ? "Lock" : "Unlock"} Aspect`, event: this.toggleNativeDimensions, icon: "snowflake" }); + optionItems.push({ description: `${!Doc.NativeWidth(this.layoutDoc) || !Doc.NativeHeight(this.layoutDoc) ? "Lock" : "Unlock"} Aspect`, event: this.toggleNativeDimensions, icon: "snowflake" }); !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "eye" }); this._downX = this._downY = Number.NaN; } @@ -1454,10 +1454,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp public endUndoTypingBatch() { const wasUndoing = this._undoTyping; - if (this._undoTyping) { - this._undoTyping.end(); - this._undoTyping = undefined; - } + this._undoTyping?.end(); + this._undoTyping = undefined; return wasUndoing; } public static LiveTextUndo: UndoManager.Batch | undefined; @@ -1470,8 +1468,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp FormattedTextBox.LiveTextUndo?.end(); FormattedTextBox.LiveTextUndo = undefined; - // move the richtextmenu offscreen - //if (!RichTextMenu.Instance.Pinned) RichTextMenu.Instance.delayHide(); } _lastTimedMark: Mark | undefined = undefined; @@ -1574,10 +1570,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp />; } + sidebarContentScaling = () => this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1); @computed get sidebarCollection() { const fitToBox = this.props.Document._fitToBox; const collectionProps = { ...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit, + NativeWidth: returnZero, + NativeHeight: returnZero, PanelHeight: this.props.PanelHeight, PanelWidth: this.sidebarWidth, xMargin: 0, @@ -1591,7 +1590,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp isSelected: this.props.isSelected, select: emptyFunction, active: this.annotationsActive, - ContentScaling: returnOne, + ContentScaling: this.sidebarContentScaling, whenActiveChanged: this.whenActiveChanged, removeDocument: this.removeDocument, moveDocument: this.moveDocument, @@ -1626,7 +1625,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const padding = Math.max(margins + ((selected && !this.layoutDoc._singleLine) || minimal ? -selPad : 0), 0); const selclass = selected && !this.layoutDoc._singleLine && margins >= 10 ? "-selected" : ""; return ( - <div className={"formattedTextBox-cont"} ref={this._boxRef} + <div className="formattedTextBox-cont" ref={this._boxRef} style={{ transform: `scale(${scale})`, transformOrigin: "top left", diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index 32038d1ee..3e5a40084 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -320,8 +320,8 @@ export class FormattedTextBoxComment { whenActiveChanged={returnFalse} bringToFront={returnFalse} ContentScaling={returnOne} - NativeWidth={target._nativeWidth ? (() => NumCast(target._nativeWidth)) : undefined} - NativeHeight={target._natvieHeight ? (() => NumCast(target._nativeHeight)) : undefined} + NativeWidth={Doc.NativeWidth(target) ? (() => Doc.NativeWidth(target)) : undefined} + NativeHeight={Doc.NativeHeight(target) ? (() => Doc.NativeHeight(target)) : undefined} /> </div> </div>; diff --git a/src/client/views/nodes/formattedText/RichTextSchema.tsx b/src/client/views/nodes/formattedText/RichTextSchema.tsx index 1767a04de..40c1d1cac 100644 --- a/src/client/views/nodes/formattedText/RichTextSchema.tsx +++ b/src/client/views/nodes/formattedText/RichTextSchema.tsx @@ -31,7 +31,7 @@ export class DashDocView { } //moved - contentScaling = () => NumCast(this._dashDoc!._nativeWidth) > 0 ? this._dashDoc![WidthSym]() / NumCast(this._dashDoc!._nativeWidth) : 1; + contentScaling = () => Doc.NativeWidth(this._dashDoc) > 0 ? this._dashDoc![WidthSym]() / Doc.NativeWidth(this._dashDoc) : 1; //moved outerFocus = (target: Doc) => this._textBox.props.focus(this._textBox.props.Document); // ideally, this would scroll to show the focus target diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index a8a6e8c33..76b218972 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -73,7 +73,7 @@ interface IViewerProps { renderDepth: number; focus: (doc: Doc) => void; isSelected: (outsideReaction?: boolean) => boolean; - loaded: (nw: number, nh: number, np: number) => void; + loaded?: (nw: number, nh: number, np: number) => void; active: (outsideReaction?: boolean) => boolean; isChildActive: (outsideReaction?: boolean) => boolean; addDocTab: (document: Doc, where: string) => boolean; @@ -238,7 +238,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu width: (page.view[page.rotate === 0 || page.rotate === 180 ? 2 : 3] - page.view[page.rotate === 0 || page.rotate === 180 ? 0 : 1]), height: (page.view[page.rotate === 0 || page.rotate === 180 ? 3 : 2] - page.view[page.rotate === 0 || page.rotate === 180 ? 1 : 0]) }); - i === this.props.pdf.numPages - 1 && this.props.loaded((page.view[page.rotate === 0 || page.rotate === 180 ? 2 : 3] - page.view[page.rotate === 0 || page.rotate === 180 ? 0 : 1]), + i === this.props.pdf.numPages - 1 && this.props.loaded?.((page.view[page.rotate === 0 || page.rotate === 180 ? 2 : 3] - page.view[page.rotate === 0 || page.rotate === 180 ? 0 : 1]), (page.view[page.rotate === 0 || page.rotate === 180 ? 3 : 2] - page.view[page.rotate === 0 || page.rotate === 180 ? 1 : 0]), i); })))); this.Document.scrollHeight = this._pageSizes.reduce((size, page) => size + page.height, 0) * 96 / 72; @@ -681,14 +681,14 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu getCoverImage = () => { - if (!this.props.Document[HeightSym]() || !this.props.Document._nativeHeight) { + if (!this.props.Document[HeightSym]() || !Doc.NativeHeight(this.props.Document)) { setTimeout((() => { this.Document._height = this.Document[WidthSym]() * this._coverPath.height / this._coverPath.width; - this.Document._nativeHeight = (this.Document._nativeWidth || 0) * this._coverPath.height / this._coverPath.width; + Doc.SetNativeWidth(this.Document, (Doc.NativeWidth(this.Document) || 0) * this._coverPath.height / this._coverPath.width); }).bind(this), 0); } - const nativeWidth = (this.Document._nativeWidth || 0); - const nativeHeight = (this.Document._nativeHeight || 0); + const nativeWidth = Doc.NativeWidth(this.Document); + const nativeHeight = Doc.NativeHeight(this.Document); const resolved = Utils.prepend(this._coverPath.path); return <img key={resolved} src={resolved} onError={action(() => this._coverPath.path = "http://www.cs.brown.edu/~bcz/face.gif")} onLoad={action(() => this._showWaiting = false)} style={{ position: "absolute", display: "inline-block", top: 0, left: 0, width: `${nativeWidth}px`, height: `${nativeHeight}px` }} />; @@ -708,7 +708,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu @computed get annotationLayer() { TraceMobx(); - return <div className="pdfViewerDash-annotationLayer" style={{ height: NumCast(this.Document._nativeHeight), transform: `scale(${this._zoomed})` }} ref={this._annotationLayer}> + return <div className="pdfViewerDash-annotationLayer" style={{ height: Doc.NativeHeight(this.Document), transform: `scale(${this._zoomed})` }} ref={this._annotationLayer}> {this.nonDocAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).map(anno => <Annotation {...this.props} showInfo={this.showInfo} select={this.props.select} focus={this.props.focus} dataDoc={this.dataDoc} fieldKey={this.props.fieldKey} anno={anno} key={`${anno[Id]}-annotation`} />) } @@ -726,11 +726,15 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu showInfo = action((anno: Opt<Doc>) => this._overlayAnnoInfo = anno); overlayTransform = () => this.scrollXf().scale(1 / this._zoomed); - panelWidth = () => (this.Document.scrollHeight || this.Document._nativeHeight || 0); - panelHeight = () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : (this.Document._nativeWidth || 0); + panelWidth = () => (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0); + panelHeight = () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document); @computed get overlayLayer() { return <div className={`pdfViewerDash-overlay${Doc.GetSelectedTool() !== InkTool.None || SnappingManager.GetIsDragging() ? "-inking" : ""}`} - style={{ pointerEvents: SnappingManager.GetIsDragging() ? "all" : undefined, transform: `scale(${this._zoomed})` }}> + style={{ + pointerEvents: SnappingManager.GetIsDragging() ? "all" : undefined, + mixBlendMode: this.allAnnotations.some(anno => anno.mixBlendMode) ? "hard-light" : undefined, + transform: `scale(${this._zoomed})` + }}> <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit} LibraryPath={this.props.ContainingCollectionView?.props.LibraryPath ?? emptyPath} annotationsKey={this.annotationKey} @@ -783,8 +787,8 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu onScroll={this.onScroll} onWheel={this.onZoomWheel} onPointerDown={this.onPointerDown} onClick={this.onClick} style={{ overflowX: this._zoomed !== 1 ? "scroll" : undefined, - width: !this.props.Document._fitWidth && (window.screen.width > 600) ? NumCast(this.props.Document._nativeWidth) : `${100 / this.contentScaling}%`, - height: !this.props.Document._fitWidth && (window.screen.width > 600) ? NumCast(this.props.Document._nativeHeight) : `${100 / this.contentScaling}%`, + width: !this.props.Document._fitWidth && (window.screen.width > 600) ? Doc.NativeWidth(this.props.Document) : `${100 / this.contentScaling}%`, + height: !this.props.Document._fitWidth && (window.screen.width > 600) ? Doc.NativeHeight(this.props.Document) : `${100 / this.contentScaling}%`, transform: `scale(${this.props.ContentScaling()})` }} > {this.pdfViewerDiv} diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index ab4cadab0..aea00f812 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -20,6 +20,8 @@ import { DragManager } from "../../util/DragManager"; import { CurrentUserUtils } from "../../util/CurrentUserUtils"; import { undoBatch } from "../../util/UndoManager"; import { EditableView } from "../EditableView"; +import { DocUtils } from "../../documents/Documents"; +import { DateField } from "../../../fields/DateField"; export const presSchema = createSchema({ presentationTargetDoc: Doc, @@ -175,8 +177,9 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc doc.className = "presItem-slide"; dragItem.push(doc); }); + const dropEvent = () => runInAction(() => this._dragging = false); if (activeItem) { - DragManager.StartDocumentDrag(dragItem.map(ele => ele), dragData, e.clientX, e.clientY); + DragManager.StartDocumentDrag(dragItem.map(ele => ele), dragData, e.clientX, e.clientY, undefined, dropEvent); runInAction(() => this._dragging = true); return true; } @@ -242,13 +245,22 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc PresBox.Instance._dragArray.push(this._dragRef.current!); } + /** + * Method called for updating the view of the currently selected document + * + * @param targetDoc + * @param activeItem + */ @undoBatch @action - pinWithView = (targetDoc: Doc, activeItem: Doc) => { + updateView = (targetDoc: Doc, activeItem: Doc) => { console.log(targetDoc.type); if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF) { const scroll = targetDoc._scrollTop; activeItem.presPinViewScroll = scroll; + } else if (targetDoc.type === DocumentType.COMPARISON) { + const clipWidth = targetDoc._clipWidth; + activeItem.presPinClipWidth = clipWidth; } else { const x = targetDoc._panX; const y = targetDoc._panY; @@ -316,7 +328,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc <div className={"presItem-slideButtons"}> <Tooltip title={<><div className="dash-tooltip">{"Update view"}</div></>}> <div className="slideButton" - onClick={() => this.pinWithView(targetDoc, activeItem)} + onClick={() => this.updateView(targetDoc, activeItem)} style={{ fontWeight: 700, display: activeItem.presPinView ? "flex" : "none" }}>V</div> </Tooltip> <Tooltip title={<><div className="dash-tooltip">{this.rootDoc.presExpandInlineButton ? "Minimize" : "Expand"}</div></>}><div className={"slideButton"} onClick={e => { e.stopPropagation(); this.presExpandDocumentClick(); }}> diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 3872cbb18..6cfd1f9d0 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -354,7 +354,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc doc.x = x; doc.y = y; const size = 200; - const aspect = NumCast(doc._nativeHeight) / NumCast(doc._nativeWidth, 1); + const aspect = Doc.NativeHeight(doc) / (Doc.NativeWidth(doc) || 1); if (aspect > 1) { doc._height = size; doc._width = size / aspect; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 1a062fa3b..adda40621 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -25,6 +25,7 @@ import JSZip = require("jszip"); import { saveAs } from "file-saver"; import { CollectionDockingView } from "../client/views/collections/CollectionDockingView"; import { SelectionManager } from "../client/util/SelectionManager"; +import { DocumentView } from "../client/views/nodes/DocumentView"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -882,6 +883,15 @@ export namespace Doc { export function SetLayout(doc: Doc, layout: Doc | string) { doc[StrCast(doc.layoutKey, "layout")] = layout; } export function LayoutField(doc: Doc) { return doc[StrCast(doc.layoutKey, "layout")]; } export function LayoutFieldKey(doc: Doc): string { return StrCast(Doc.Layout(doc).layout).split("'")[1]; } + export function NativeAspect(doc: Doc, dataDoc?: Doc, useDim?: boolean) { + return Doc.NativeWidth(doc, dataDoc, useDim) / (Doc.NativeHeight(doc, dataDoc, useDim) || 1); + } + export function NativeWidth(doc?: Doc, dataDoc?: Doc, useWidth?: boolean) { return !doc ? 0 : NumCast(doc._nativeWidth, NumCast((dataDoc || doc)[Doc.LayoutFieldKey(doc) + "-nativeWidth"], useWidth ? doc[WidthSym]() : 0)); } + export function NativeHeight(doc?: Doc, dataDoc?: Doc, useHeight?: boolean) { return !doc ? 0 : NumCast(doc._nativeHeight, NumCast((dataDoc || doc)[Doc.LayoutFieldKey(doc) + "-nativeHeight"], useHeight ? doc[HeightSym]() : 0)); } + export function SetNativeWidth(doc: Doc, width: number | undefined) { doc[Doc.LayoutFieldKey(doc) + "-nativeWidth"] = width; } + export function SetNativeHeight(doc: Doc, height: number | undefined) { doc[Doc.LayoutFieldKey(doc) + "-nativeHeight"] = height; } + + const manager = new DocData(); export function SearchQuery(): string { return manager._searchQuery; } export function SetSearchQuery(query: string) { runInAction(() => manager._searchQuery = query); } @@ -1086,14 +1096,14 @@ export namespace Doc { export function toggleNativeDimensions(layoutDoc: Doc, contentScale: number, panelWidth: number, panelHeight: number) { runInAction(() => { - if (layoutDoc._nativeWidth || layoutDoc._nativeHeight) { + if (Doc.NativeWidth(layoutDoc) || Doc.NativeHeight(layoutDoc)) { layoutDoc._viewScale = NumCast(layoutDoc._viewScale, 1) * contentScale; layoutDoc._nativeWidth = undefined; layoutDoc._nativeHeight = undefined; } else { layoutDoc._autoHeight = false; - if (!layoutDoc._nativeWidth) { + if (!Doc.NativeWidth(layoutDoc)) { layoutDoc._nativeWidth = NumCast(layoutDoc._width, panelWidth); layoutDoc._nativeHeight = NumCast(layoutDoc._height, panelHeight); } diff --git a/src/server/websocket.ts b/src/server/websocket.ts index 490760441..6ceb9e29f 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -278,8 +278,8 @@ export namespace WebSocket { diff.diff.$set = diff.diff.$addToSet; delete diff.diff.$addToSet;// convert add to set to a query of the current fields, and then a set of the composition of the new fields with the old ones const updatefield = Array.from(Object.keys(diff.diff.$set))[0]; const newListItems = diff.diff.$set[updatefield].fields; - const curList = (curListItems as any)?.fields?.[updatefield.replace("fields.", "")]?.fields || []; - diff.diff.$set[updatefield].fields = [...curList, ...newListItems.filter((newItem: any) => !curList.some((curItem: any) => curItem.fieldId ? curItem.fieldId === newItem.fieldId : curItem.heading ? curItem.heading === newItem.heading : curItem === newItem))]; + const curList = (curListItems as any)?.fields?.[updatefield.replace("fields.", "")]?.fields.filter((item: any) => item !== undefined) || []; + diff.diff.$set[updatefield].fields = [...curList, ...newListItems.filter((newItem: any) => newItem && !curList.some((curItem: any) => curItem.fieldId ? curItem.fieldId === newItem.fieldId : curItem.heading ? curItem.heading === newItem.heading : curItem === newItem))]; const sendBack = diff.diff.length !== diff.diff.$set[updatefield].fields.length; delete diff.diff.length; Database.Instance.update(diff.id, diff.diff, |