aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/DocumentView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/DocumentView.tsx')
-rw-r--r--src/client/views/nodes/DocumentView.tsx282
1 files changed, 84 insertions, 198 deletions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index f2add9856..091a6b050 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,10 +1,9 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Tooltip } from '@material-ui/core';
import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
+import { computedFn } from 'mobx-utils';
import { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal';
-import { AclAdmin, AclEdit, AclPrivate, AnimationSym, DataSym, Doc, DocListCast, Field, Opt, StrListCast, WidthSym } from '../../../fields/Doc';
+import { AclPrivate, AnimationSym, DataSym, Doc, DocListCast, Field, Opt, StrListCast, WidthSym } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
import { List } from '../../../fields/List';
@@ -12,8 +11,7 @@ import { listSpec } from '../../../fields/Schema';
import { ScriptField } from '../../../fields/ScriptField';
import { BoolCast, Cast, DocCast, ImageCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { AudioField } from '../../../fields/URLField';
-import { GetEffectiveAcl, SharingPermissions, TraceMobx } from '../../../fields/util';
-import { MobileInterface } from '../../../mobile/MobileInterface';
+import { GetEffectiveAcl, TraceMobx } from '../../../fields/util';
import { emptyFunction, isTargetChildOf as isParentOf, lightOrDark, OmitKeys, returnEmptyString, returnFalse, returnTrue, returnVal, simulateMouseClick, Utils } from '../../../Utils';
import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils';
import { DocServer } from '../../DocServer';
@@ -28,7 +26,6 @@ import { LinkFollower } from '../../util/LinkFollower';
import { LinkManager } from '../../util/LinkManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SelectionManager } from '../../util/SelectionManager';
-import { SettingsManager } from '../../util/SettingsManager';
import { SharingManager } from '../../util/SharingManager';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
@@ -48,7 +45,6 @@ import './DocumentView.scss';
import { FieldViewProps } from './FieldView';
import { FormattedTextBox } from './formattedText/FormattedTextBox';
import { LinkAnchorBox } from './LinkAnchorBox';
-import { RadialMenu } from './RadialMenu';
import { PresEffect, PresEffectDirection } from './trails';
import { PinProps, PresBox } from './trails/PresBox';
import React = require('react');
@@ -155,7 +151,6 @@ export interface DocumentViewSharedProps {
ContainingCollectionDoc: Opt<Doc>;
suppressSetHeight?: boolean;
thumbShown?: () => boolean;
- isHovering?: () => boolean;
setContentView?: (view: DocComponentView) => any;
CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView;
PanelWidth: () => number;
@@ -240,7 +235,6 @@ export interface DocumentViewInternalProps extends DocumentViewProps {
NativeWidth: () => number;
NativeHeight: () => number;
isSelected: (outsideReaction?: boolean) => boolean;
- isHovering: () => boolean;
select: (ctrlPressed: boolean, shiftPress?: boolean) => void;
DocumentView: () => DocumentView;
viewPath: () => DocumentView[];
@@ -289,9 +283,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
@computed get thumb() {
return ImageCast(this.layoutDoc['thumb-frozen'], ImageCast(this.layoutDoc.thumb))?.url?.href.replace('.png', '_m.png');
}
- @computed get hidden() {
- return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Hidden);
- }
@computed get opacity() {
return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Opacity);
}
@@ -379,30 +370,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
Object.values(this._disposers).forEach(disposer => disposer?.());
}
- @action
- onRadialMenu = (e: Event, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>): void => {
- const pt = me.touchEvent.touches[me.touchEvent.touches.length - 1];
- RadialMenu.Instance.openMenu(pt.pageX - 15, pt.pageY - 15);
-
- // RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), OpenWhere.addRight), icon: "map-pin", selected: -1 });
- const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]);
- (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) &&
- RadialMenu.Instance.addItem({
- description: 'Delete',
- event: () => {
- this.props.ContainingCollectionView?.removeDocument(this.props.Document);
- RadialMenu.Instance.closeMenu();
- },
- icon: 'external-link-square-alt',
- selected: -1,
- });
- // RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, OpenWhere.addRight), icon: "trash", selected: -1 });
- RadialMenu.Instance.addItem({ description: 'Pin', event: () => this.props.pinToPres(this.props.Document, {}), icon: 'map-pin', selected: -1 });
- RadialMenu.Instance.addItem({ description: 'Open', event: () => MobileInterface.Instance.handleClick(this.props.Document), icon: 'trash', selected: -1 });
-
- SelectionManager.DeselectAll();
- };
-
startDragging(x: number, y: number, dropAction: dropActionType, hideSource = false) {
if (this._mainCont.current) {
const views = SelectionManager.Views().filter(dv => dv.docView?._mainCont.current);
@@ -435,7 +402,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
defaultRestoreTargetView = (docView: DocumentView, anchor: Doc, focusSpeed: number, options: DocFocusOptions) => {
const targetMatch =
Doc.AreProtosEqual(anchor, this.rootDoc) || // anchor is this document, so anchor's properties apply to this document
- (DocCast(anchor)?.unrendered && Doc.AreProtosEqual(DocCast(anchor.annotationOn), this.rootDoc)) // the anchor is an unrendered annotation on this document, so anchor properties applie to this document
+ (DocCast(anchor)?.unrendered && Doc.AreProtosEqual(DocCast(anchor.annotationOn), this.rootDoc)) // the anchor is an unrendered annotation on this document, so anchor properties apply to this document
? true
: false;
return targetMatch && PresBox.restoreTargetDocView(docView, anchor, focusSpeed) ? focusSpeed : undefined;
@@ -573,11 +540,9 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
}
};
- cancelMoveEvents = () => document.removeEventListener('pointermove', this.onPointerMove);
-
cleanupPointerEvents = () => {
this.cleanUpInteractions();
- this.cancelMoveEvents();
+ document.removeEventListener('pointermove', this.onPointerMove);
document.removeEventListener('pointerup', this.onPointerUp);
};
@@ -586,7 +551,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
this.cleanupPointerEvents();
this._longPressSelector && clearTimeout(this._longPressSelector);
- if (this.onPointerUpHandler?.script && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) {
+ if (this.onPointerUpHandler?.script) {
this.onPointerUpHandler.script.run({ self: this.rootDoc, this: this.layoutDoc }, console.log);
} else if (e.button === 0 && Utils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) {
this._doubleTap = Date.now() - this._lastTap < Utils.CLICK_TIME;
@@ -676,7 +641,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
@undoBatch
@action
makeIntoPortal = () => {
- const portalLink = this.allLinks.find(d => d.anchor1 === this.props.Document);
+ const portalLink = this.allLinks.find(d => d.anchor1 === this.props.Document && d.linkRelationship === 'portal to:portal from');
if (!portalLink) {
DocUtils.MakeLink(
{ doc: this.props.Document },
@@ -928,25 +893,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
? true
: false;
};
- get audioAnnoState() {
- return this.dataDoc.audioAnnoState ?? 'stopped';
- }
- @computed get audioAnnoView() {
- const audioAnnosCount = Cast(this.dataDoc[this.LayoutFieldKey + '-audioAnnotations'], listSpec(AudioField), null)?.length;
- const audioTextAnnos = Cast(this.dataDoc[this.LayoutFieldKey + '-audioAnnotations-text'], listSpec('string'), null);
- const audioIconColors = new Map<string, string>([
- ['recording', 'red'],
- ['playing', 'green'],
- ['stopped', audioAnnosCount ? 'blue' : 'gray'],
- ]);
- return this.props.renderDepth === -1 || SnappingManager.GetIsDragging() || (!this.props.isSelected() && !this.props.isHovering() && this.audioAnnoState !== 'recording') || (!audioAnnosCount && this.audioAnnoState === 'stopped') ? null : (
- <Tooltip title={<div>{audioTextAnnos?.lastElement()}</div>}>
- <div className="documentView-audioBackground" onPointerDown={this.playAnnotation}>
- <FontAwesomeIcon className="documentView-audioFont" style={{ color: audioIconColors.get(StrCast(this.audioAnnoState)) }} icon={!audioAnnosCount ? 'microphone' : 'file-audio'} size="sm" />
- </div>
- </Tooltip>
- );
- }
contentPointerEvents = () => (!this.disableClickScriptFunc && this.onClickHandler ? 'none' : this.pointerEvents);
@computed get contents() {
TraceMobx();
@@ -965,10 +911,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
height={this.props.PanelHeight()}
onError={(e: any) => {
setTimeout(action(() => (this._retryThumb = 0)));
- setTimeout(
- action(() => (this._retryThumb = 1)),
- 150
- );
+ // prettier-ignore
+ setTimeout(action(() => (this._retryThumb = 1)), 150 );
}}
/>
)}
@@ -978,7 +922,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
pointerEvents={this.contentPointerEvents}
docViewPath={this.props.viewPath}
thumbShown={this.thumbShown}
- isHovering={this.props.isHovering}
setContentView={this.setContentView}
NativeDimScaling={this.props.NativeDimScaling}
PanelHeight={this.panelHeight}
@@ -992,19 +935,10 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
layoutKey={this.finalLayoutKey}
/>
{this.layoutDoc.hideAllLinks ? null : this.allLinkEndpoints}
- {this.audioAnnoView}
</div>
);
}
- get indicatorIcon() {
- if (this.props.Document['acl-Public'] !== SharingPermissions.None) return 'globe-americas';
- else if (this.props.Document.numGroupsShared || NumCast(this.props.Document.numUsersShared, 0) > 1) return 'users';
- else return 'user';
- }
-
- @undoBatch
- hideLinkAnchor = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && (doc.hidden = true), true);
anchorPanelWidth = () => this.props.PanelWidth() || 1;
anchorPanelHeight = () => this.props.PanelHeight() || 1;
anchorStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any => {
@@ -1036,12 +970,13 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
TraceMobx();
return LinkManager.Instance.getAllRelatedLinks(this.rootDoc);
}
+ hideLink = computedFn((link: Doc) => () => (link.linkDisplay = false));
@computed get allLinkEndpoints() {
// the small blue dots that mark the endpoints of links
TraceMobx();
if (this.props.hideLinkAnchors || this.layoutDoc.hideLinkAnchors || this.props.dontRegisterView || this.layoutDoc.unrendered) return null;
const filtered = DocUtils.FilterDocs(this.directLinks, this.props.docFilters?.() ?? [], []).filter(d => d.linkDisplay);
- return filtered.map((link, i) => (
+ return filtered.map(link => (
<div className="documentView-anchorCont" key={link[Id]}>
<DocumentView
{...this.props}
@@ -1055,8 +990,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
hideCaptions={true}
hideLinkAnchors={true}
fitWidth={returnTrue}
+ removeDocument={this.hideLink(link)}
styleProvider={this.anchorStyleProvider}
- removeDocument={this.hideLinkAnchor}
LayoutTemplate={undefined}
LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(link, this.rootDoc)}`)}
/>
@@ -1064,26 +999,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
));
}
- @action
- playAnnotation = () => {
- const self = this;
- const audioAnnos = Cast(this.dataDoc[this.LayoutFieldKey + '-audioAnnotations'], listSpec(AudioField), null);
- const anno = audioAnnos?.lastElement();
- if (anno instanceof AudioField && this.audioAnnoState === 'stopped') {
- new Howl({
- src: [anno.url.href],
- format: ['mp3'],
- autoplay: true,
- loop: false,
- volume: 0.5,
- onend: function () {
- runInAction(() => (self.dataDoc.audioAnnoState = 'stopped'));
- },
- });
- this.dataDoc.audioAnnoState = 'playing';
- }
- };
-
static recordAudioAnnotation(dataDoc: Doc, field: string, onRecording?: (stop: () => void) => void, onEnd?: () => void) {
let gumStream: any;
let recorder: any;
@@ -1131,6 +1046,23 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
else setTimeout(stopFunc, 5000);
});
}
+ playAnnotation = () => {
+ const self = this;
+ const audioAnnoState = this.dataDoc.audioAnnoState ?? 'stopped';
+ const audioAnnos = Cast(this.dataDoc[this.LayoutFieldKey + '-audioAnnotations'], listSpec(AudioField), null);
+ const anno = audioAnnos?.lastElement();
+ if (anno instanceof AudioField && audioAnnoState === 'stopped') {
+ new Howl({
+ src: [anno.url.href],
+ format: ['mp3'],
+ autoplay: true,
+ loop: false,
+ volume: 0.5,
+ onend: action(() => (self.dataDoc.audioAnnoState = 'stopped')),
+ });
+ this.dataDoc.audioAnnoState = 'playing';
+ }
+ };
captionStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewInternalProps>, property: string) => this.props?.styleProvider?.(doc, props, property + ':caption');
@computed get innards() {
@@ -1225,7 +1157,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
renderDoc = (style: object) => {
TraceMobx();
- return !DocCast(this.Document) || GetEffectiveAcl(this.Document[DataSym]) === AclPrivate || this.hidden
+ return !DocCast(this.Document) || GetEffectiveAcl(this.Document[DataSym]) === AclPrivate
? null
: this.docContents ?? (
<div
@@ -1280,7 +1212,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
render() {
TraceMobx();
const highlighting = this.props.styleProvider?.(this.props.Document, this.props, StyleProp.Highlighting);
- const borderPath = this.props.styleProvider?.(this.props.Document, this.props, StyleProp.BorderPath) || { path: undefined };
+ const borderPath = this.props.styleProvider?.(this.props.Document, this.props, StyleProp.BorderPath);
const boxShadow =
this.props.treeViewDoc || !highlighting
? this.boxShadow
@@ -1292,11 +1224,10 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
outline: highlighting && !this.borderRounding && !highlighting.highlightStroke ? `${highlighting.highlightColor} ${highlighting.highlightStyle} ${highlighting.highlightIndex}px` : 'solid 0px',
border: highlighting && this.borderRounding && highlighting.highlightStyle === 'dashed' ? `${highlighting.highlightStyle} ${highlighting.highlightColor} ${highlighting.highlightIndex}px` : undefined,
boxShadow,
- clipPath: borderPath.path ? `path('${borderPath.path}')` : undefined,
+ clipPath: borderPath?.clipPath,
});
- const animRenderDoc = DocumentViewInternal.AnimationEffect(renderDoc, this.rootDoc[AnimationSym], this.rootDoc);
- return this.hidden ? null : (
+ return (
<div
className={`${DocumentView.ROOT_DIV} docView-hack`}
ref={this._mainCont}
@@ -1307,22 +1238,13 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
onPointerOver={e => (!SnappingManager.GetIsDragging() || DragManager.CanEmbed) && Doc.BrushDoc(this.props.Document)}
onPointerLeave={e => !isParentOf(this.ContentDiv, document.elementFromPoint(e.nativeEvent.x, e.nativeEvent.y)) && Doc.UnBrushDoc(this.props.Document)}
style={{
- display: this.hidden ? 'inline' : undefined,
borderRadius: this.borderRounding,
pointerEvents: this.pointerEvents === 'visiblePainted' ? 'none' : this.pointerEvents,
}}>
- {!borderPath.path ? (
- animRenderDoc
- ) : (
- <>
- {animRenderDoc}
- <div key="border2" className="documentView-customBorder" style={{ pointerEvents: 'none' }}>
- <svg style={{ overflow: 'visible', height: '100%' }} viewBox={`0 0 ${this.props.PanelWidth()} ${this.props.PanelHeight()}`}>
- <path d={borderPath.path} style={{ stroke: 'black', fill: 'transparent', strokeWidth: borderPath.width }} />
- </svg>
- </div>
- </>
- )}
+ <>
+ {DocumentViewInternal.AnimationEffect(renderDoc, this.rootDoc[AnimationSym], this.rootDoc)}
+ {borderPath?.jsx}
+ </>
</div>
);
}
@@ -1332,6 +1254,11 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
export class DocumentView extends React.Component<DocumentViewProps> {
public static ROOT_DIV = 'documentView-effectsWrapper';
@observable public static LongPress = false;
+ @observable public docView: DocumentViewInternal | undefined | null;
+ @observable public textHtmlOverlay: Opt<string>;
+ @observable private _isHovering = false;
+
+ public htmlOverlayEffect = '';
public get displayName() {
return 'DocumentView(' + this.props.Document?.title + ')';
} // this makes mobx trace() statements more descriptive
@@ -1343,6 +1270,10 @@ export class DocumentView extends React.Component<DocumentViewProps> {
this.ViewTimer && clearTimeout(this.ViewTimer);
this.rootDoc._viewTransition = undefined;
};
+ public startDragging = (x: number, y: number, dropAction: dropActionType, hideSource = false) => this.docView?.startDragging(x, y, dropAction, hideSource);
+
+ public showContextMenu = (pageX: number, pageY: number) => this.docView?.onContextMenu(undefined, pageX, pageY);
+
public setAnimEffect = (presEffect: Doc, timeInMs: number, afterTrans?: () => void) => {
this.AnimEffectTimer && clearTimeout(this.AnimEffectTimer);
this.rootDoc[AnimationSym] = presEffect;
@@ -1374,34 +1305,18 @@ export class DocumentView extends React.Component<DocumentViewProps> {
);
}
+ // shows a stacking view collection (by default, but the user can change) of all documents linked to the source
public static showBackLinks(linkSource: Doc) {
const docId = Doc.CurrentUserEmail + Doc.GetProto(linkSource)[Id] + '-pivotish';
- DocServer.GetRefField(docId).then(docx => {
- const rootAlias = () => {
- const rootAlias = Doc.MakeAlias(linkSource);
- rootAlias.x = rootAlias.y = 0;
- return rootAlias;
- };
- const linkCollection =
- (docx instanceof Doc && docx) ||
- Docs.Create.StackingDocument(
- [
- /*rootAlias()*/
- ],
- { title: linkSource.title + '-pivot', _width: 500, _height: 500 },
- docId
- );
- linkCollection.linkSource = linkSource;
- if (!linkCollection.reactionScript) linkCollection.reactionScript = ScriptField.MakeScript('updateLinkCollection(self)');
- LightboxView.SetLightboxDoc(linkCollection);
- });
+ // prettier-ignore
+ DocServer.GetRefField(docId).then(docx => docx instanceof Doc &&
+ LightboxView.SetLightboxDoc(
+ docx || // reuse existing pivot view of documents, or else create a new collection
+ Docs.Create.StackingDocument([], { title: linkSource.title + '-pivot', _width: 500, _height: 500, linkSource, updateContentsScript: ScriptField.MakeScript('updateLinkCollection(self)') }, docId)
+ )
+ );
}
- @observable public docView: DocumentViewInternal | undefined | null;
-
- showContextMenu(pageX: number, pageY: number) {
- return this.docView?.onContextMenu(undefined, pageX, pageY);
- }
get Document() {
return this.props.Document;
}
@@ -1409,13 +1324,10 @@ export class DocumentView extends React.Component<DocumentViewProps> {
return this.props.renderDepth === 0;
}
get rootDoc() {
- return this.docView?.rootDoc || this.Document;
+ return this.docView?.rootDoc ?? this.Document;
}
get dataDoc() {
- return this.docView?.dataDoc || this.Document;
- }
- get finalLayoutKey() {
- return this.docView?.finalLayoutKey || 'layout';
+ return this.docView?.dataDoc ?? this.Document;
}
get ContentDiv() {
return this.docView?.ContentDiv;
@@ -1429,23 +1341,22 @@ export class DocumentView extends React.Component<DocumentViewProps> {
get LayoutFieldKey() {
return this.docView?.LayoutFieldKey || 'layout';
}
- get fitWidth() {
+ @computed get fitWidth() {
return this.docView?._componentView?.fitWidth?.() ?? this.props.fitWidth?.(this.rootDoc) ?? this.layoutDoc?.fitWidth;
}
-
+ @computed get anchorViewDoc() {
+ return this.props.LayoutTemplateString?.includes('anchor2') ? DocCast(this.rootDoc['anchor2']) : this.props.LayoutTemplateString?.includes('anchor1') ? DocCast(this.rootDoc['anchor1']) : undefined;
+ }
@computed get hideLinkButton() {
return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HideLinkButton + (this.isSelected() ? ':selected' : ''));
}
- linkButtonInverseScaling = () => (this.props.NativeDimScaling?.() || 1) * this.screenToLocalTransform().Scale;
-
@computed get linkCountView() {
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.linkButtonInverseScaling} OnHover={true} Bottom={this.topMost} ShowCount={true} />;
+ 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];
}
@@ -1475,7 +1386,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
return Math.max(minTextScale, this.props.PanelHeight() / (this.effectiveNativeHeight || 1)); // height-limited or unscaled
}
-
@computed get panelWidth() {
return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling : this.props.PanelWidth();
}
@@ -1500,12 +1410,12 @@ export class DocumentView extends React.Component<DocumentViewProps> {
return this.props.dontCenter?.includes('y') ? 0 : this.Yshift;
}
- toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.NativeDimScaling, this.props.PanelWidth(), this.props.PanelHeight());
- getBounds = () => {
- if (!this.docView || !this.docView.ContentDiv || this.props.treeViewDoc || Doc.AreProtosEqual(this.props.Document, Doc.UserDoc())) {
+ public toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.NativeDimScaling, this.props.PanelWidth(), this.props.PanelHeight());
+ public getBounds = () => {
+ if (!this.docView?.ContentDiv || this.props.treeViewDoc || Doc.AreProtosEqual(this.props.Document, Doc.UserDoc())) {
return undefined;
}
- const xf = this.docView?.props
+ const xf = this.docView.props
.ScreenToLocalTransform()
.scale(this.trueNativeWidth() ? this.nativeScaling : 1)
.inverse();
@@ -1542,7 +1452,8 @@ export class DocumentView extends React.Component<DocumentViewProps> {
Doc.setNativeView(this.props.Document);
custom && DocUtils.makeCustomViewClicked(this.props.Document, Docs.Create.StackingDocument, layout, undefined);
};
- switchViews = action((custom: boolean, view: string, finished?: () => void, useExistingLayout = false) => {
+ @action
+ switchViews = (custom: boolean, view: string, finished?: () => void, useExistingLayout = false) => {
this.docView && (this.docView._animateScalingTo = 0.1); // shrink doc
setTimeout(
action(() => {
@@ -1562,14 +1473,9 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}),
this.docView ? Math.max(0, this.docView?.animateScaleTime - 10) : 0
);
- });
-
- startDragging = (x: number, y: number, dropAction: dropActionType, hideSource = false) => this.docView?.startDragging(x, y, dropAction, hideSource);
+ };
- @observable textHtmlOverlay: Opt<string>;
- @computed get anchorViewDoc() {
- return this.props.LayoutTemplateString?.includes('anchor2') ? DocCast(this.rootDoc['anchor2']) : this.props.LayoutTemplateString?.includes('anchor1') ? DocCast(this.rootDoc['anchor1']) : undefined;
- }
+ scaleToScreenSpace = () => (1 / (this.props.NativeDimScaling?.() || 1)) * this.screenToLocalTransform().Scale;
docViewPathFunc = () => this.docViewPath;
isSelected = (outsideReaction?: boolean) => SelectionManager.IsSelected(this, outsideReaction);
select = (extendSelection: boolean) => SelectionManager.SelectView(this, !SelectionManager.Views().some(v => v.props.Document === this.props.ContainingCollectionDoc) && extendSelection);
@@ -1586,11 +1492,12 @@ export class DocumentView extends React.Component<DocumentViewProps> {
.translate(-this.centeringX, -this.centeringY)
.scale(this.trueNativeWidth() ? 1 / this.nativeScaling : 1);
componentDidMount() {
- this._disposers.reactionScript = reaction(
- () => ScriptCast(this.rootDoc.reactionScript)?.script?.run({ this: this.props.Document, self: Cast(this.rootDoc, Doc, null) || this.props.Document }).result,
+ this._disposers.updateContentsScript = reaction(
+ () => ScriptCast(this.rootDoc.updateContentsScript)?.script?.run({ this: this.props.Document, self: Cast(this.rootDoc, Doc, null) || this.props.Document }).result,
output => output
);
this._disposers.height = reaction(
+ // increase max auto height if document has been resized to be greater than current max
() => NumCast(this.layoutDoc._height),
action(height => {
const docMax = NumCast(this.layoutDoc.docMaxAutoHeight);
@@ -1603,24 +1510,20 @@ export class DocumentView extends React.Component<DocumentViewProps> {
Object.values(this._disposers).forEach(disposer => disposer?.());
!BoolCast(this.props.Document.dontRegisterView, this.props.dontRegisterView) && DocumentManager.Instance.RemoveView(this);
}
- _hoverTimeout: any = undefined;
- isHovering = () => this._isHovering;
- @observable _isHovering = false;
-
- htmlOverlayEffect = '';
@computed get htmlOverlay() {
- const effectProps = {
- delay: 0,
- duration: 500,
- };
- const highlight = (
- <div className="webBox-textHighlight">
- <ObserverJsxParser autoCloseVoidElements={true} key={42} onError={(e: any) => console.log('PARSE error', e)} renderInWrapper={false} jsx={StrCast(this.textHtmlOverlay)} />
- </div>
- );
return !this.textHtmlOverlay ? null : (
<div className="documentView-htmlOverlay">
- <div className="documentView-htmlOverlayInner">{<Fade {...effectProps}>{DocumentViewInternal.AnimationEffect(highlight, { presEffect: this.htmlOverlayEffect ?? 'Zoom' } as any as Doc, this.rootDoc)} </Fade>}</div>
+ <div className="documentView-htmlOverlayInner">
+ <Fade delay={0} duration={500}>
+ {DocumentViewInternal.AnimationEffect(
+ <div className="webBox-textHighlight">
+ <ObserverJsxParser autoCloseVoidElements={true} key={42} onError={(e: any) => console.log('PARSE error', e)} renderInWrapper={false} jsx={StrCast(this.textHtmlOverlay)} />
+ </div>,
+ { presEffect: this.htmlOverlayEffect ?? 'Zoom' } as any as Doc,
+ this.rootDoc
+ )}{' '}
+ </Fade>
+ </div>
</div>
);
}
@@ -1631,19 +1534,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
const yshift = Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined;
return this.hidden ? null : (
- <div
- className="contentFittingDocumentView"
- onPointerEnter={action(() => {
- clearTimeout(this._hoverTimeout);
- this._isHovering = true;
- })}
- onPointerLeave={action(() => {
- clearTimeout(this._hoverTimeout);
- this._hoverTimeout = setTimeout(
- action(() => (this._isHovering = false)),
- 500
- );
- })}>
+ <div className="contentFittingDocumentView" onPointerEnter={action(() => (this._isHovering = true))} onPointerLeave={action(() => (this._isHovering = false))}>
{!this.props.Document || !this.props.PanelWidth() ? null : (
<div
className="contentFittingDocumentView-previewDoc"
@@ -1667,7 +1558,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
NativeDimScaling={this.NativeDimScaling}
isSelected={this.isSelected}
select={this.select}
- isHovering={this.isHovering}
ScreenToLocalTransform={this.screenToLocalTransform}
focus={this.props.focus || emptyFunction}
ref={action((r: DocumentViewInternal | null) => r && (this.docView = r))}
@@ -1682,10 +1572,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
}
-export function deiconifyViewFunc(documentView: DocumentView) {
- documentView.iconify();
- //StrCast(doc.layoutKey).split("_")[1] === "icon" && setNativeView(doc);
-}
ScriptingGlobals.add(function deiconifyView(documentView: DocumentView) {
documentView.iconify();
documentView.select(false);