aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/LinkDocPreview.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/LinkDocPreview.tsx')
-rw-r--r--src/client/views/nodes/LinkDocPreview.tsx145
1 files changed, 76 insertions, 69 deletions
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 198cbe851..4b242649a 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -1,101 +1,110 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Tooltip } from '@material-ui/core';
-import { action, computed, observable } from 'mobx';
+import { Tooltip } from '@mui/material';
+import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
+import * as React from 'react';
import wiki from 'wikijs';
-import { Doc, DocCastAsync, Opt } from '../../../fields/Doc';
-import { Height, Width } from '../../../fields/DocSymbols';
-import { Cast, DocCast, NumCast, PromiseValue, StrCast } from '../../../fields/Types';
import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnNone, setupMoveUpEvents } from '../../../Utils';
+import { Doc, Opt } from '../../../fields/Doc';
+import { Cast, DocCast, NumCast, PromiseValue, StrCast } from '../../../fields/Types';
import { DocServer } from '../../DocServer';
-import { Docs } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
+import { Docs } from '../../documents/Documents';
+import { DocumentManager } from '../../util/DocumentManager';
import { DragManager } from '../../util/DragManager';
import { LinkFollower } from '../../util/LinkFollower';
import { LinkManager } from '../../util/LinkManager';
import { SearchUtil } from '../../util/SearchUtil';
import { SettingsManager } from '../../util/SettingsManager';
import { Transform } from '../../util/Transform';
-import { DocumentView, DocumentViewSharedProps, OpenWhere } from './DocumentView';
+import { ObservableReactComponent } from '../ObservableReactComponent';
+import { DocumentView, OpenWhere } from './DocumentView';
+import { StyleProviderFuncType } from './FieldView';
import './LinkDocPreview.scss';
-import React = require('react');
-import { DocumentManager } from '../../util/DocumentManager';
+
+export class LinkInfo {
+ private static _instance: Opt<LinkInfo>;
+ constructor() {
+ LinkInfo._instance = this;
+ makeObservable(this);
+ }
+ @observable public LinkInfo: Opt<LinkDocPreviewProps> = undefined;
+
+ public static get Instance() {
+ return LinkInfo._instance ?? new LinkInfo();
+ }
+ public static Clear() {
+ runInAction(() => LinkInfo.Instance && (LinkInfo.Instance.LinkInfo = undefined));
+ }
+ public static SetLinkInfo(info?: LinkDocPreviewProps) {
+ runInAction(() => LinkInfo.Instance && (LinkInfo.Instance.LinkInfo = info));
+ }
+}
interface LinkDocPreviewProps {
linkDoc?: Doc;
linkSrc?: Doc;
- docProps: DocumentViewSharedProps;
+ DocumentView?: () => DocumentView;
+ styleProvider?: StyleProviderFuncType;
location: number[];
hrefs?: string[];
showHeader?: boolean;
noPreview?: boolean;
}
@observer
-export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
- @action public static Clear() {
- LinkDocPreview.LinkInfo = undefined;
- }
- @action public static SetLinkInfo(info?: LinkDocPreviewProps) {
- LinkDocPreview.LinkInfo !== info && (LinkDocPreview.LinkInfo = info);
- }
-
- static _instance: Opt<LinkDocPreview>;
-
+export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps> {
_infoRef = React.createRef<HTMLDivElement>();
_linkDocRef = React.createRef<HTMLDivElement>();
- @observable public static LinkInfo: Opt<LinkDocPreviewProps>;
- @observable _targetDoc: Opt<Doc>;
- @observable _markerTargetDoc: Opt<Doc>;
- @observable _linkDoc: Opt<Doc>;
- @observable _linkSrc: Opt<Doc>;
+ @observable _targetDoc: Opt<Doc> = undefined;
+ @observable _markerTargetDoc: Opt<Doc> = undefined;
+ @observable _linkDoc: Opt<Doc> = undefined;
+ @observable _linkSrc: Opt<Doc> = undefined;
@observable _toolTipText = '';
@observable _hrefInd = 0;
-
constructor(props: any) {
super(props);
- LinkDocPreview._instance = this;
+ makeObservable(this);
}
- @action init() {
- var linkTarget = this.props.linkDoc;
- this._linkSrc = this.props.linkSrc;
- this._linkDoc = this.props.linkDoc;
- const link_anchor_1 = this._linkDoc?.link_anchor_1 as Doc;
- const link_anchor_2 = this._linkDoc?.link_anchor_2 as Doc;
+ @action
+ init() {
+ var linkTarget = this._props.linkDoc;
+ this._linkSrc = this._props.linkSrc;
+ this._linkDoc = this._props.linkDoc;
+ const link_anchor_1 = DocCast(this._linkDoc?.link_anchor_1);
+ const link_anchor_2 = DocCast(this._linkDoc?.link_anchor_2);
if (link_anchor_1 && link_anchor_2) {
linkTarget = Doc.AreProtosEqual(link_anchor_1, this._linkSrc) || Doc.AreProtosEqual(link_anchor_1?.annotationOn as Doc, this._linkSrc) ? link_anchor_2 : link_anchor_1;
}
if (linkTarget?.annotationOn && linkTarget?.type !== DocumentType.RTF) {
- // want to show annotation embedContainer document if annotation is not text
- linkTarget && DocCastAsync(linkTarget.annotationOn).then(action(anno => (this._markerTargetDoc = this._targetDoc = anno)));
- } else {
- this._markerTargetDoc = this._targetDoc = linkTarget;
+ linkTarget = DocCast(linkTarget.annotationOn); // want to show annotation embedContainer document if annotation is not text
}
+ this._markerTargetDoc = this._targetDoc = linkTarget;
this._toolTipText = '';
this.updateHref();
}
- componentDidUpdate(props: any) {
- if (props.linkSrc !== this.props.linkSrc || props.linkDoc !== this.props.linkDoc || props.hrefs !== this.props.hrefs) this.init();
+ componentDidUpdate(prevProps: Readonly<LinkDocPreviewProps>) {
+ super.componentDidUpdate(prevProps);
+ if (prevProps.linkSrc !== this._props.linkSrc || prevProps.linkDoc !== this._props.linkDoc || prevProps.hrefs !== this._props.hrefs) this.init();
}
componentDidMount() {
this.init();
document.addEventListener('pointerdown', this.onPointerDown, true);
}
- @action
componentWillUnmount() {
- LinkDocPreview.SetLinkInfo(undefined);
+ LinkInfo.Clear();
document.removeEventListener('pointerdown', this.onPointerDown, true);
}
onPointerDown = (e: PointerEvent) => {
- !this._linkDocRef.current?.contains(e.target as any) && LinkDocPreview.Clear(); // close preview when not clicking anywhere other than the info bar of the preview
+ !this._linkDocRef.current?.contains(e.target as any) && LinkInfo.Clear(); // close preview when not clicking anywhere other than the info bar of the preview
};
@action
updateHref() {
- if (this.props.hrefs?.length) {
- const href = this.props.hrefs[this._hrefInd];
+ if (this._props.hrefs?.length) {
+ const href = this._props.hrefs[this._hrefInd];
if (href.indexOf(Doc.localServerPath()) !== 0) {
// link to a web page URL -- try to show a preview
if (href.startsWith('https://en.wikipedia.org/wiki/')) {
@@ -125,7 +134,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
this._markerTargetDoc = linkTarget;
this._targetDoc = /*linkTarget?.type === DocumentType.MARKER &&*/ linkTarget?.annotationOn ? Cast(linkTarget.annotationOn, Doc, null) ?? linkTarget : linkTarget;
}
- if (LinkDocPreview.LinkInfo?.noPreview || this._linkSrc?.followLinkToggle || this._markerTargetDoc?.type === DocumentType.PRES) this.followLink();
+ if (LinkInfo.Instance?.LinkInfo?.noPreview || this._linkSrc?.followLinkToggle || this._markerTargetDoc?.type === DocumentType.PRES) this.followLink();
}
})
);
@@ -145,9 +154,9 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
action(() => {
LinkManager.currentLink = this._linkDoc;
LinkManager.currentLinkAnchor = this._linkSrc;
- this.props.docProps.DocumentView?.().select(false);
- if ((SettingsManager.propertiesWidth ?? 0) < 100) {
- SettingsManager.propertiesWidth = 250;
+ this._props.DocumentView?.().select(false);
+ if ((SettingsManager.Instance.propertiesWidth ?? 0) < 100) {
+ SettingsManager.Instance.propertiesWidth = 250;
}
})
);
@@ -159,7 +168,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
returnFalse,
emptyFunction,
action(() => {
- const nextHrefInd = (this._hrefInd + 1) % (this.props.hrefs?.length || 1);
+ const nextHrefInd = (this._hrefInd + 1) % (this._props.hrefs?.length || 1);
if (nextHrefInd !== this._hrefInd) {
this._linkDoc = undefined;
this._hrefInd = nextHrefInd;
@@ -170,19 +179,19 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
};
followLink = () => {
- LinkDocPreview.Clear();
+ LinkInfo.Clear();
if (this._linkDoc && this._linkSrc) {
LinkFollower.FollowLink(this._linkDoc, this._linkSrc, false);
- } else if (this.props.hrefs?.length) {
+ } else if (this._props.hrefs?.length) {
const webDoc =
- Array.from(SearchUtil.SearchCollection(Doc.MyFilesystem, this.props.hrefs[0]).keys()).lastElement() ??
- Docs.Create.WebDocument(this.props.hrefs[0], { title: this.props.hrefs[0], _nativeWidth: 850, _width: 200, _height: 400, data_useCors: true });
+ Array.from(SearchUtil.SearchCollection(Doc.MyFilesystem, this._props.hrefs[0]).keys()).lastElement() ??
+ Docs.Create.WebDocument(this._props.hrefs[0], { title: this._props.hrefs[0], _nativeWidth: 850, _width: 200, _height: 400, data_useCors: true });
DocumentManager.Instance.showDocument(webDoc, {
openLocation: OpenWhere.lightbox,
willPan: true,
zoomTime: 500,
});
- //this.props.docProps?.addDocTab(webDoc, OpenWhere.lightbox);
+ //this._props.docProps?.addDocTab(webDoc, OpenWhere.lightbox);
}
};
@@ -190,17 +199,17 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
width = () => {
if (!this._targetDoc) return 225;
- if (this._targetDoc[Width]() < this._targetDoc?.[Height]()) {
- return (Math.min(225, this._targetDoc[Height]()) * this._targetDoc[Width]()) / this._targetDoc[Height]();
+ if (NumCast(this._targetDoc._width) < NumCast(this._targetDoc._height)) {
+ return (Math.min(225, NumCast(this._targetDoc._height)) * NumCast(this._targetDoc._width)) / NumCast(this._targetDoc._height);
}
- return Math.min(225, NumCast(this._targetDoc?.[Width](), 225));
+ return Math.min(225, NumCast(this._targetDoc._width, 225));
};
height = () => {
if (!this._targetDoc) return 225;
- if (this._targetDoc[Width]() > this._targetDoc?.[Height]()) {
- return (Math.min(225, this._targetDoc[Width]()) * this._targetDoc[Height]()) / this._targetDoc[Width]();
+ if (NumCast(this._targetDoc._width) > NumCast(this._targetDoc._height)) {
+ return (Math.min(225, NumCast(this._targetDoc._width)) * NumCast(this._targetDoc._height)) / NumCast(this._targetDoc._width);
}
- return Math.min(225, NumCast(this._targetDoc?.[Height](), 225));
+ return Math.min(225, NumCast(this._targetDoc._height, 225));
};
@computed get previewHeader() {
return !this._linkDoc || !this._markerTargetDoc || !this._targetDoc || !this._linkSrc ? null : (
@@ -218,7 +227,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
</div>
<div className="linkDocPreview-buttonBar" style={{ float: 'right' }}>
<Tooltip title={<div className="dash-tooltip">Next Link</div>} placement="top">
- <div className="linkDocPreview-button" style={{ background: (this.props.hrefs?.length || 0) <= 1 ? 'gray' : 'green' }} onPointerDown={this.nextHref}>
+ <div className="linkDocPreview-button" style={{ background: (this._props.hrefs?.length || 0) <= 1 ? 'gray' : 'green' }} onPointerDown={this.nextHref}>
<FontAwesomeIcon className="linkDocPreview-fa-icon" icon="chevron-right" color="white" size="sm" />
</div>
</Tooltip>
@@ -230,7 +239,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
@computed get docPreview() {
return (!this._linkDoc || !this._targetDoc || !this._linkSrc) && !this._toolTipText ? null : (
<div className="linkDocPreview-inner">
- {!this.props.showHeader ? null : this.previewHeader}
+ {!this._props.showHeader ? null : this.previewHeader}
<div
className="linkDocPreview-preview-wrapper"
onPointerDown={e =>
@@ -240,7 +249,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
(e, down, delta) => {
if (Math.abs(e.clientX - down[0]) + Math.abs(e.clientY - down[1]) > 100) {
DragManager.StartDocumentDrag([this._infoRef.current!], new DragManager.DocumentDragData([this._targetDoc!]), e.pageX, e.pageY);
- LinkDocPreview.Clear();
+ LinkInfo.Clear();
return true;
}
return false;
@@ -258,13 +267,12 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
<DocumentView
ref={r => {
const targetanchor = this._linkDoc && this._linkSrc && LinkManager.getOppositeAnchor(this._linkDoc, this._linkSrc);
- targetanchor && this._targetDoc !== targetanchor && r?.props.focus?.(targetanchor, {});
+ targetanchor && this._targetDoc !== targetanchor && r?._props.focus?.(targetanchor, {});
}}
Document={this._targetDoc!}
moveDocument={returnFalse}
- rootSelected={returnFalse}
- styleProvider={this.props.docProps?.styleProvider}
- docViewPath={returnEmptyDoclist}
+ styleProvider={this._props.styleProvider}
+ containerViewPath={returnEmptyDoclist}
ScreenToLocalTransform={Transform.Identity}
isDocumentActive={returnFalse}
isContentActive={returnFalse}
@@ -285,7 +293,6 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
focus={emptyFunction}
whenChildContentsActiveChanged={returnFalse}
ignoreAutoHeight={true} // need to ignore layout_autoHeight otherwise layout_autoHeight text boxes will expand beyond the preview panel size.
- bringToFront={returnFalse}
NativeWidth={Doc.NativeWidth(this._targetDoc) ? () => Doc.NativeWidth(this._targetDoc) : undefined}
NativeHeight={Doc.NativeHeight(this._targetDoc) ? () => Doc.NativeHeight(this._targetDoc) : undefined}
/>
@@ -302,7 +309,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
className="linkDocPreview"
ref={this._linkDocRef}
onPointerDown={this.followLinkPointerDown}
- style={{ borderColor: SettingsManager.userColor, left: this.props.location[0], top: this.props.location[1], width: this.width() + borders, height: this.height() + borders + (this.props.showHeader ? 37 : 0) }}>
+ style={{ borderColor: SettingsManager.userColor, left: this._props.location[0], top: this._props.location[1], width: this.width() + borders, height: this.height() + borders + (this._props.showHeader ? 37 : 0) }}>
{this.docPreview}
</div>
);