diff options
| author | James Hu <51237606+jameshu111@users.noreply.github.com> | 2023-05-04 10:36:59 -0400 |
|---|---|---|
| committer | James Hu <51237606+jameshu111@users.noreply.github.com> | 2023-05-04 10:36:59 -0400 |
| commit | 725bf38dc018cb218d8a88605234e95a2beee446 (patch) | |
| tree | 9150905cf1b67b06c03fdd8d10ac6da6e8246832 /src/client/views/nodes/DocumentView.tsx | |
| parent | 96465f2dccc974a821fa912c90def988b76808e5 (diff) | |
| parent | 1c24114bbe8f69f61948f7531277305457926498 (diff) | |
Merge branch 'master' into james-server-stats
Diffstat (limited to 'src/client/views/nodes/DocumentView.tsx')
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 88 |
1 files changed, 48 insertions, 40 deletions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7107707d1..3bdd2bf6e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -47,6 +47,7 @@ import { LinkAnchorBox } from './LinkAnchorBox'; import { PresEffect, PresEffectDirection } from './trails'; import { PinProps, PresBox } from './trails/PresBox'; import React = require('react'); +import { InkingStroke } from '../InkingStroke'; const { Howl } = require('howler'); interface Window { @@ -215,7 +216,6 @@ export interface DocumentViewProps extends DocumentViewSharedProps { radialMenu?: String[]; LayoutTemplateString?: string; dontCenter?: 'x' | 'y' | 'xy'; - dontScaleFilter?: (doc: Doc) => boolean; // decides whether a document can be scaled to fit its container vs native size with scrolling NativeWidth?: () => number; NativeHeight?: () => number; NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal NOTE: Must also be added to FieldViewProps @@ -262,7 +262,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps @observable _animateScalingTo = 0; public get animateScaleTime() { - return this._animateScaleTime ?? 300; + return this._animateScaleTime ?? 100; } public get displayName() { return 'DocumentView(' + this.props.Document.title + ')'; @@ -295,8 +295,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Decorations + (this.props.isSelected() ? ':selected' : '')); } @computed get backgroundBoxColor() { - const thumb = ImageCast(this.layoutDoc['thumb-frozen'], ImageCast(this.layoutDoc.thumb)); - return thumb ? undefined : this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor + ':box'); + return this.thumbShown() ? undefined : this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor + ':box'); } @computed get docContents() { return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.DocContents); @@ -413,6 +412,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps setTimeout(() => this._titleRef.current?.setIsFocused(true)); // use timeout in case title wasn't shown to allow re-render so that titleref will be defined }; + public static addDocTabFunc: (doc: Doc, location: OpenWhere) => boolean = returnFalse; + onClick = action((e: React.MouseEvent | React.PointerEvent) => { if (!this.Document.ignoreClick && this.pointerEvents !== 'none' && this.props.renderDepth >= 0 && Utils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) { let stopPropagate = true; @@ -446,24 +447,33 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps let clickFunc: undefined | (() => any); if (!this.disableClickScriptFunc && this.onClickHandler?.script) { const { clientX, clientY, shiftKey, altKey, metaKey } = e; - const func = () => - this.onClickHandler?.script.run( - { - this: this.layoutDoc, - self: this.rootDoc, - _readOnly_: false, - scriptContext: this.props.scriptContext, - documentView: this.props.DocumentView(), - clientX, - clientY, - shiftKey, - altKey, - metaKey, - }, - console.log - ).result?.select === true - ? this.props.select(false) - : ''; + const func = () => { + // replace default add doc func with this view's add doc func. + // to allow override behaviors for how to display links to undisplayed documents. + // e.g., if this document is part of a labeled 'lightbox' container, then documents will be shown in place + // instead of in the global lightbox + const oldFunc = DocumentViewInternal.addDocTabFunc; + DocumentViewInternal.addDocTabFunc = this.props.addDocTab; + const res = + this.onClickHandler?.script.run( + { + this: this.layoutDoc, + self: this.rootDoc, + _readOnly_: false, + scriptContext: this.props.scriptContext, + documentView: this.props.DocumentView(), + clientX, + clientY, + shiftKey, + altKey, + metaKey, + }, + console.log + ).result?.select === true + ? this.props.select(false) + : ''; + DocumentViewInternal.addDocTabFunc = oldFunc; + }; clickFunc = () => (this.props.Document.dontUndo ? func() : UndoManager.RunInBatch(func, 'on click')); } else { // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplateForField implies we're clicking on part of a template instance and we want to select the whole template, not the part @@ -473,7 +483,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps preventDefault = false; } - this._singleClickFunc = clickFunc ?? (() => (this._componentView?.select ?? this.props.select)(e.ctrlKey || e.metaKey, e.shiftKey)); + this._singleClickFunc = clickFunc ?? (() => this._componentView?.select?.(e.ctrlKey || e.metaKey, e.shiftKey) ?? this.props.select(e.ctrlKey || e.metaKey || e.shiftKey)); const waitFordblclick = this.props.waitForDoubleClickToClick?.() ?? this.Document.waitForDoubleClickToClick; if ((clickFunc && waitFordblclick !== 'never') || waitFordblclick === 'always') { this._doubleClickTimeout && clearTimeout(this._doubleClickTimeout); @@ -693,7 +703,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps !Doc.noviceMode && templateDoc && appearanceItems.push({ description: 'Open Template ', event: () => this.props.addDocTab(templateDoc, OpenWhere.addRight), icon: 'eye' }); !appearance && appearanceItems.length && cm.addItem({ description: 'UI Controls...', subitems: appearanceItems, icon: 'compass' }); - if (!Doc.IsSystem(this.rootDoc) && this.rootDoc._viewType !== CollectionViewType.Docking && this.props.docViewPath().lastElement()?.rootDoc?._viewType !== CollectionViewType.Tree) { + if (!Doc.IsSystem(this.rootDoc) && this.rootDoc.type !== DocumentType.PRES && ![CollectionViewType.Docking, CollectionViewType.Tree].includes(this.rootDoc._viewType as any)) { const existingOnClick = cm.findByDescription('OnClick...'); const onClicks: ContextMenuProps[] = existingOnClick && 'subitems' in existingOnClick ? existingOnClick.subitems : []; @@ -707,7 +717,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps event: undoBatch(action(() => (this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined))), icon: 'hand-point-up', }); - !zorders && cm.addItem({ description: 'ZOrder...', noexpand: true, subitems: zorderItems, icon: 'compass' }); + !zorders && cm.addItem({ description: 'Z Order...', addDivider: true, noexpand: true, subitems: zorderItems, icon: 'compass' }); } onClicks.push({ description: 'Enter Portal', event: this.makeIntoPortal, icon: 'window-restore' }); @@ -720,11 +730,11 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps onClicks.push({ description: this.onClickHandler ? 'Remove Click Behavior' : 'Follow Link', event: () => this.toggleFollowLink(false, false), icon: 'link' }); onClicks.push({ description: 'Edit onClick Script', event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, 'onClick'), 'edit onClick'), icon: 'terminal' }); - !existingOnClick && cm.addItem({ description: 'OnClick...', addDivider: true, noexpand: true, subitems: onClicks, icon: 'mouse-pointer' }); + !existingOnClick && cm.addItem({ description: 'OnClick...', noexpand: true, subitems: onClicks, icon: 'mouse-pointer' }); } else if (LinkManager.Links(this.Document).length) { onClicks.push({ description: 'Select on Click', event: () => this.noOnClick(), icon: 'link' }); onClicks.push({ description: 'Follow Link on Click', event: () => this.followLinkOnClick(), icon: 'link' }); - !existingOnClick && cm.addItem({ description: 'OnClick...', addDivider: true, subitems: onClicks, icon: 'mouse-pointer' }); + !existingOnClick && cm.addItem({ description: 'OnClick...', subitems: onClicks, icon: 'mouse-pointer' }); } } @@ -755,7 +765,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps !more && moreItems.length && cm.addItem({ description: 'More...', subitems: moreItems, icon: 'compass' }); } const constantItems: ContextMenuProps[] = []; - + constantItems.push({ description: 'Show Metadata', event: () => this.props.addDocTab(this.props.Document, (OpenWhere.addRight.toString() + 'KeyValue') as OpenWhere), icon: 'layer-group' }); if (!Doc.IsSystem(this.rootDoc)) { constantItems.push({ description: 'Export as Zip file', icon: 'download', event: async () => Doc.Zip(this.props.Document) }); constantItems.push({ description: 'Import Zipped file', icon: 'upload', event: ({ x, y }) => this.importDocument() }); @@ -764,11 +774,11 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps // need option to gray out menu items ... preferably with a '?' that explains why they're grayed out (eg., no permissions) constantItems.push({ description: 'Close', event: this.deleteClicked, icon: 'times' }); } - cm.addItem({ description: 'General...', noexpand: false, subitems: constantItems, icon: 'question' }); } + cm.addItem({ description: 'General...', noexpand: !Doc.IsSystem(this.rootDoc), subitems: constantItems, icon: 'question' }); + const help = cm.findByDescription('Help...'); const helpItems: ContextMenuProps[] = help && 'subitems' in help ? help.subitems : []; - helpItems.push({ description: 'Show Metadata', event: () => this.props.addDocTab(this.props.Document, (OpenWhere.addRight.toString() + 'KeyValue') as OpenWhere), icon: 'layer-group' }); !Doc.noviceMode && helpItems.push({ description: 'Text Shortcuts Ctrl+/', event: () => this.props.addDocTab(Docs.Create.PdfDocument('/assets/cheat-sheet.pdf', { _width: 300, _height: 300 }), OpenWhere.addRight), icon: 'keyboard' }); !Doc.noviceMode && helpItems.push({ description: 'Print Document in Console', event: () => console.log(this.props.Document), icon: 'hand-point-right' }); !Doc.noviceMode && helpItems.push({ description: 'Print DataDoc in Console', event: () => console.log(this.props.Document[DataSym]), icon: 'hand-point-right' }); @@ -809,13 +819,11 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps if (documentationDescription && documentationLink) { helpItems.push({ description: documentationDescription, - event: () => { - window.open(documentationLink, '_blank'); - }, + event: () => window.open(documentationLink, '_blank'), icon: 'book', }); } - if (!help) cm.addItem({ description: 'Help...', noexpand: true, subitems: helpItems, icon: 'question' }); + if (!help) cm.addItem({ description: 'Help...', noexpand: !Doc.noviceMode, subitems: helpItems, icon: 'question' }); else cm.moveAfter(help); e?.stopPropagation(); // DocumentViews should stop propagation of this event @@ -858,14 +866,16 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps ? true : false; }; + docFilters = () => [...this.props.docFilters(), ...StrListCast(this.layoutDoc.docFilters)]; contentPointerEvents = () => (!this.disableClickScriptFunc && this.onClickHandler ? 'none' : this.pointerEvents); @computed get contents() { TraceMobx(); + const isInk = StrCast(this.layoutDoc.layout).includes(InkingStroke.name); return ( <div className="documentView-contentsView" style={{ - pointerEvents: (this.pointerEvents === 'visiblePainted' ? 'none' : this.pointerEvents) ?? 'all', + pointerEvents: (isInk ? 'none' : this.pointerEvents) ?? 'all', height: this.headerMargin ? `calc(100% - ${this.headerMargin}px)` : undefined, }}> {!this._retryThumb || !this.thumbShown() ? null : ( @@ -888,6 +898,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps docViewPath={this.props.viewPath} thumbShown={this.thumbShown} setContentView={this.setContentView} + docFilters={this.docFilters} NativeDimScaling={this.props.NativeDimScaling} PanelHeight={this.panelHeight} setHeight={!this.props.suppressSetHeight ? this.setHeight : undefined} @@ -1318,9 +1329,6 @@ export class DocumentView extends React.Component<DocumentViewProps> { const hideCount = this.props.renderDepth === -1 || SnappingManager.GetIsDragging() || (this.isSelected() && this.props.renderDepth) || !this._isHovering || this.hideLinkButton; return hideCount ? null : <DocumentLinksButton View={this} scaling={this.scaleToScreenSpace} OnHover={true} Bottom={this.topMost} ShowCount={true} />; } - @computed get hidden() { - return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Hidden); - } @computed get docViewPath(): DocumentView[] { return this.props.docViewPath ? [...this.props.docViewPath(), this] : [this]; } @@ -1334,7 +1342,7 @@ export class DocumentView extends React.Component<DocumentViewProps> { return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, !this.fitWidth)); } @computed get shouldNotScale() { - return (this.fitWidth && !this.nativeWidth) || this.props.dontScaleFilter?.(this.Document) || [CollectionViewType.Docking].includes(this.Document._viewType as any); + return (this.fitWidth && !this.nativeWidth) || [CollectionViewType.Docking].includes(this.Document._viewType as any); } @computed get effectiveNativeWidth() { return this.shouldNotScale ? 0 : this.nativeWidth || NumCast(this.layoutDoc.width); @@ -1497,7 +1505,7 @@ export class DocumentView extends React.Component<DocumentViewProps> { const xshift = Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined; const yshift = Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined; - return this.hidden ? null : ( + return ( <div className="contentFittingDocumentView" onPointerEnter={action(() => (this._isHovering = true))} onPointerLeave={action(() => (this._isHovering = false))}> {!this.props.Document || !this.props.PanelWidth() ? null : ( <div |
