diff options
| -rw-r--r-- | src/client/util/DocumentManager.ts | 5 | ||||
| -rw-r--r-- | src/client/util/SelectionManager.ts | 7 | ||||
| -rw-r--r-- | src/client/views/collections/CollectionStackedTimeline.tsx | 4 | ||||
| -rw-r--r-- | src/client/views/collections/TreeView.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.scss | 1 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 40 |
6 files changed, 34 insertions, 25 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 01230bc06..3c59a8060 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -327,14 +327,15 @@ export class DocumentManager { if (options.zoomTextSelections && Doc.UnhighlightTimer && contextView && viewSpec.text_html) { // if the docView is a text anchor, the contextView is the PDF/Web/Text doc - contextView.htmlOverlayEffect = StrCast(options?.effect?.presentation_effect, StrCast(options?.effect?.followLinkAnimEffect)); + contextView.htmlOverlayEffect = options.effect; + contextView.textHtmlOverlayTime = options.zoomTime; contextView.textHtmlOverlay = StrCast(targetDoc.text_html); DocumentManager._overlayViews.add(contextView); } Doc.AddUnHighlightWatcher(() => { docView.rootDoc[Animation] = undefined; DocumentManager.removeOverlayViews(); - contextView && (contextView.htmlOverlayEffect = ''); + contextView && (contextView.htmlOverlayEffect = undefined); }); } } diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index e864458d8..f7e6fa2dc 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -64,11 +64,8 @@ export namespace SelectionManager { manager.SelectSchemaViewDoc(document); } - // computed functions, such as used in IsSelected generate errors if they're called outside of a - // reaction context. Specifying the context with 'outsideReaction' allows an efficiency feature - // to avoid unnecessary mobx invalidations when running inside a reaction. - export function IsSelected(dv?: DocumentView | Doc): boolean { - return (dv instanceof Doc ? Array.from(dv[DocViews]) : dv ? [dv] : []).some(dv => dv?.SELECTED); + export function IsSelected(doc?: Doc): boolean { + return Array.from(doc?.[DocViews] ?? []).some(dv => dv?.SELECTED); } export function DeselectAll(except?: Doc): void { diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 584098d35..3351ca48e 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -784,7 +784,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps> // renders anchor LabelBox renderInner = computedFn(function (this: StackedTimelineAnchor, mark: Doc, script: undefined | (() => ScriptField), doublescript: undefined | (() => ScriptField), screenXf: () => Transform, width: () => number, height: () => number) { - const anchor = observable({ view: undefined as any }); + const anchor = observable({ view: undefined as Opt<DocumentView> | null }); const focusFunc = (doc: Doc, options: DocFocusOptions): number | undefined => { this.props.playLink(mark, options); return undefined; @@ -838,7 +838,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps> return ( <div style={{ pointerEvents: this.noEvents ? 'none' : undefined }}> {inner.view} - {!inner.anchor.view || !SelectionManager.IsSelected(inner.anchor.view) ? null : ( + {!inner.anchor.view || !inner.anchor.view.SELECTED ? null : ( <> <div key="left" className="collectionStackedTimeline-left-resizer" style={{ pointerEvents: this.noEvents ? 'none' : undefined }} onPointerDown={e => this.onAnchorDown(e, this.props.mark, true)} /> <div key="right" className="collectionStackedTimeline-resizer" style={{ pointerEvents: this.noEvents ? 'none' : undefined }} onPointerDown={e => this.onAnchorDown(e, this.props.mark, false)} /> diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index dbce45fda..004857ed1 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -165,7 +165,7 @@ export class TreeView extends React.Component<TreeViewProps> { return this.childDocList(this.fieldKey + '_annotations'); } @computed get selected() { - return SelectionManager.IsSelected(this._docRef); + return this._docRef?.SELECTED; } childDocList(field: string) { diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index 505e937c5..406a1b8fb 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -61,7 +61,6 @@ .documentView-htmlOverlayInner { box-shadow: black 0.2vw 0.2vw 0.8vw; background: rgb(255, 255, 255); - overflow: auto; position: relative; margin: auto; padding: 20px; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 9d30a92b0..66a431bf0 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1364,9 +1364,10 @@ export class DocumentView extends React.Component<DocumentViewProps> { } @observable public docView: DocumentViewInternal | undefined | null; @observable public textHtmlOverlay: Opt<string>; + @observable public textHtmlOverlayTime: Opt<number>; @observable private _isHovering = false; - public htmlOverlayEffect = ''; + public htmlOverlayEffect: Opt<Doc>; public get displayName() { return 'DocumentView(' + this.props.Document?.title + ')'; } // this makes mobx trace() statements more descriptive @@ -1596,7 +1597,7 @@ export class DocumentView extends React.Component<DocumentViewProps> { scaleToScreenSpace = () => (1 / (this.props.NativeDimScaling?.() || 1)) * this.screenToLocalTransform().Scale; docViewPathFunc = () => this.docViewPath; - isSelected = () => SelectionManager.IsSelected(this); + isSelected = () => this.SELECTED; select = (extendSelection: boolean, focusSelection?: boolean) => { if (this.isSelected() && SelectionManager.Views().length > 1) SelectionManager.DeselectView(this); else { @@ -1643,19 +1644,30 @@ 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); } + // want the htmloverlay to be able to fade in but we also want it to be display 'none' until it is needed. + // unfortunately, CSS can't transition animate any properties for something that is display 'none'. + // so we need to first activate the div, then, after a render timeout, start the opacity transition. + @observable enableHtmlOverlayTransitions: boolean = false; @computed get htmlOverlay() { - return !this.textHtmlOverlay ? null : ( - <div className="documentView-htmlOverlay"> - <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>, - { presentation_effect: this.htmlOverlayEffect ?? 'Zoom' } as any as Doc, - this.rootDoc - )}{' '} - </Fade> + const effect = StrCast(this.htmlOverlayEffect?.presentation_effect, StrCast(this.htmlOverlayEffect?.followLinkAnimEffect)); + return ( + <div + className="documentView-htmlOverlay" + ref={r => { + const val = r?.style.display !== 'none'; // if the outer overlay has been displayed, trigger the innner div to start it's opacity fade in transition + if (r && val !== this.enableHtmlOverlayTransitions) { + setTimeout(action(() => (this.enableHtmlOverlayTransitions = val))); + } + }} + style={{ display: !this.textHtmlOverlay ? 'none' : undefined }}> + <div className="documentView-htmlOverlayInner" style={{ transition: `all 500ms`, opacity: this.enableHtmlOverlayTransitions ? 0.9 : 0 }}> + {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>, + { ...(this.htmlOverlayEffect ?? {}), presentation_effect: effect ?? PresEffect.Zoom } as any as Doc, + this.rootDoc + )} </div> </div> ); |
