aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ClientUtils.ts17
-rw-r--r--src/client/util/DocumentManager.ts4
-rw-r--r--src/client/util/SerializationHelper.ts4
-rw-r--r--src/client/views/MarqueeAnnotator.tsx12
-rw-r--r--src/client/views/PropertiesSection.tsx3
-rw-r--r--src/client/views/PropertiesView.tsx9
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx4
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx3
-rw-r--r--src/client/views/nodes/FieldView.tsx1
-rw-r--r--src/client/views/nodes/FontIconBox/FontIconBox.tsx2
-rw-r--r--src/client/views/nodes/PDFBox.scss2
-rw-r--r--src/client/views/nodes/PDFBox.tsx12
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx3
-rw-r--r--src/client/views/pdf/Annotation.tsx89
-rw-r--r--src/client/views/pdf/PDFViewer.tsx54
-rw-r--r--src/client/views/search/SearchBox.tsx189
-rw-r--r--src/client/views/selectedDoc/SelectedDocView.tsx2
-rw-r--r--src/client/views/selectedDoc/index.ts2
-rw-r--r--src/fields/Doc.ts3
-rw-r--r--src/fields/List.ts2
20 files changed, 253 insertions, 164 deletions
diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts
index 57e0373c4..402f6613a 100644
--- a/src/ClientUtils.ts
+++ b/src/ClientUtils.ts
@@ -3,7 +3,7 @@ import * as React from 'react';
import { ColorResult } from 'react-color';
import * as rp from 'request-promise';
import { numberRange, decimalToHexString } from './Utils';
-import { DocumentType } from './client/documents/DocumentTypes';
+import { CollectionViewType, DocumentType } from './client/documents/DocumentTypes';
import { Colors } from './client/views/global/globalEnums';
export function DashColor(color: string) {
@@ -100,11 +100,22 @@ export namespace ClientUtils {
return Date.now() - downTime < ClientUtils.CLICK_TIME && Math.abs(x - downX) < ClientUtils.DRAG_THRESHOLD && Math.abs(y - downY) < ClientUtils.DRAG_THRESHOLD;
}
- export function cleanDocumentType(type: DocumentType) {
+ export function cleanDocumentTypeExt(type: DocumentType) {
switch (type) {
+ case DocumentType.PDF: return 'PDF';
+ case DocumentType.IMG: return 'Img';
+ case DocumentType.AUDIO: return 'Aud';
+ case DocumentType.COL: return 'Col';
+ case DocumentType.RTF: return 'Rtf';
+ default: return type.charAt(0).toUpperCase() + type.substring(1,3);
+ } // prettier-ignore
+ }
+ export function cleanDocumentType(type: DocumentType, colType: CollectionViewType) {
+ switch (type) {
+ case DocumentType.PDF: return 'PDF';
case DocumentType.IMG: return 'Image';
case DocumentType.AUDIO: return 'Audio';
- case DocumentType.COL: return 'Collection';
+ case DocumentType.COL: return 'Collection:'+colType;
case DocumentType.RTF: return 'Text';
default: return type.charAt(0).toUpperCase() + type.slice(1);
} // prettier-ignore
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index cca92816f..ac3721436 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -310,8 +310,8 @@ export class DocumentManager {
focused = focused || nextFocus !== undefined; // keep track of whether focusing on a view needed to actually change anything
// eslint-disable-next-line no-await-in-loop
const { childDocView, viewSpec } = await iterator(docView);
- if (!childDocView) return { viewSpec: options.anchorDoc ?? viewSpec ?? docView.Document, docView, contextView, focused };
- contextView = options.anchorDoc?.layout_unrendered && !childDocView.Document.layout_unrendered ? childDocView : docView;
+ if (!childDocView) return { viewSpec: viewSpec ?? docView.Document, docView, contextView, focused };
+ contextView = !childDocView.Document.layout_unrendered ? childDocView : docView;
docView = childDocView;
}
return undefined;
diff --git a/src/client/util/SerializationHelper.ts b/src/client/util/SerializationHelper.ts
index fa1a911f7..d9d22437c 100644
--- a/src/client/util/SerializationHelper.ts
+++ b/src/client/util/SerializationHelper.ts
@@ -65,7 +65,7 @@ export namespace SerializationHelper {
}
}
-export function Deserializable(className: string, afterDeserialize?: (obj: any) => void | Promise<any>, constructorArgs?: [string]): (constructor: { new (...args: any[]): any }) => void {
+export function Deserializable(classNameForSerializer: string, afterDeserialize?: (obj: any) => void | Promise<any>, constructorArgs?: [string]): (constructor: { new (...args: any[]): any }) => void {
function addToMap(className: string, Ctor: { new (...args: any[]): any }) {
const schema = getDefaultModelSchema(Ctor) as any;
if (schema.targetClass !== Ctor || constructorArgs) {
@@ -78,7 +78,7 @@ export function Deserializable(className: string, afterDeserialize?: (obj: any)
throw new Error(`Name ${className} has already been registered as deserializable`);
}
}
- return (ctor: { new (...args: any[]): any }) => addToMap(className, ctor);
+ return (ctor: { new (...args: any[]): any }) => addToMap(classNameForSerializer, ctor);
}
export function autoObject(): PropSchema {
diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx
index 0301632ec..c4c00e0c3 100644
--- a/src/client/views/MarqueeAnnotator.tsx
+++ b/src/client/views/MarqueeAnnotator.tsx
@@ -95,6 +95,7 @@ export class MarqueeAnnotator extends ObservableReactComponent<MarqueeAnnotatorP
presentation_zoomText: true,
title: '>' + this.props.Document.title,
});
+ const textRegionAnnoProto = textRegionAnno[DocData];
let minX = Number.MAX_VALUE;
let maxX = -Number.MAX_VALUE;
let minY = Number.MAX_VALUE;
@@ -107,7 +108,7 @@ export class MarqueeAnnotator extends ObservableReactComponent<MarqueeAnnotatorP
textRegion.y = parseInt(anno.style.top ?? '0');
textRegion._height = parseInt(anno.style.height ?? '0');
textRegion._width = parseInt(anno.style.width ?? '0');
- textRegion.annoTextRegion = textRegionAnno;
+ textRegion.embedContainer = textRegionAnnoProto;
textRegion.backgroundColor = color;
annoDocs.push(textRegion);
anno.remove();
@@ -118,7 +119,6 @@ export class MarqueeAnnotator extends ObservableReactComponent<MarqueeAnnotatorP
})
);
- const textRegionAnnoProto = textRegionAnno[DocData];
textRegionAnnoProto.y = Math.max(minY, 0);
textRegionAnnoProto.x = Math.max(minX, 0);
textRegionAnnoProto.height = Math.max(maxY, 0) - Math.max(minY, 0);
@@ -202,10 +202,10 @@ export class MarqueeAnnotator extends ObservableReactComponent<MarqueeAnnotatorP
return target;
};
DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.docView(), sourceAnchorCreator, targetCreator), e.pageX, e.pageY, {
- dragComplete: e => {
- if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) {
- e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this.props.Document;
- e.annoDragData.linkSourceDoc.followLinkZoom = false;
+ dragComplete: dragEv => {
+ if (!dragEv.aborted && dragEv.annoDragData && dragEv.annoDragData.linkSourceDoc && dragEv.annoDragData.dropDocument && dragEv.linkDocument) {
+ dragEv.annoDragData.linkSourceDoc.followLinkToggle = dragEv.annoDragData.dropDocument.annotationOn === this.props.Document;
+ dragEv.annoDragData.linkSourceDoc.followLinkZoom = false;
}
},
});
diff --git a/src/client/views/PropertiesSection.tsx b/src/client/views/PropertiesSection.tsx
index f083f03b9..b9a587719 100644
--- a/src/client/views/PropertiesSection.tsx
+++ b/src/client/views/PropertiesSection.tsx
@@ -13,7 +13,6 @@ export interface PropertiesSectionProps {
children?: JSX.Element | string | null;
isOpen: boolean;
setIsOpen: (bool: boolean) => any;
- setInSection?: (bool: boolean) => any;
onDoubleClick?: () => void;
}
@@ -30,7 +29,7 @@ export class PropertiesSection extends React.Component<PropertiesSectionProps> {
render() {
if (this.props.children === undefined || this.props.children === null) return null;
return (
- <div className="propertiesView-section" onPointerEnter={action(() => this.props.setInSection && this.props.setInSection(true))} onPointerLeave={action(() => this.props.setInSection && this.props.setInSection(false))}>
+ <div className="propertiesView-section">
<div
className="propertiesView-sectionTitle"
onDoubleClick={action(() => {
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 8ac0f7d7b..5e1c80f0c 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -114,7 +114,6 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@observable openAddSlide: boolean = false;
@observable openSlideOptions: boolean = false;
- @observable inOptions: boolean = false;
@observable _controlButton: boolean = false;
private _disposers: { [name: string]: IReactionDisposer } = {};
@@ -602,9 +601,9 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
@computed get currentType() {
- const documentType = StrCast(this.selectedDoc?.type);
- const currentType: string = documentType;
- const capitalizedDocType = ClientUtils.cleanDocumentType(currentType as DocumentType);
+ const docType = StrCast(this.selectedDoc?.type) as DocumentType;
+ const colType = StrCast(this.selectedDoc?.type_collection) as CollectionViewType;
+ const capitalizedDocType = ClientUtils.cleanDocumentType(docType, colType);
return (
<div>
@@ -1080,7 +1079,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get optionsSubMenu() {
return (
// prettier-ignore
- <PropertiesSection title="Options" inSection={this.inOptions} isOpen={this.openOptions} setInSection={bool => { this.inOptions = bool; }} setIsOpen={bool => { this.openOptions = bool; }} onDoubleClick={this.CloseAll}>
+ <PropertiesSection title="Options" isOpen={this.openOptions} setIsOpen={bool => { this.openOptions = bool; }} onDoubleClick={this.CloseAll}>
<PropertiesButtons />
</PropertiesSection>
);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx
index 707f6c198..90977d955 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx
@@ -11,7 +11,7 @@ export interface CollectionFreeFormPannableContentsProps {
Document: Doc;
viewDefDivClick?: ScriptField;
children?: React.ReactNode | undefined;
- transition?: string;
+ transition: () => string;
isAnnotationOverlay: boolean | undefined;
showPresPaths: () => boolean;
transform: () => string;
@@ -53,7 +53,7 @@ export class CollectionFreeFormPannableContents extends ObservableReactComponent
}}
style={{
transform: this._props.transform(),
- transition: this._props.transition,
+ transition: this._props.transition(),
width: this._props.isAnnotationOverlay ? undefined : 0, // if not an overlay, then this will be the size of the collection, but panning and zooming will move it outside the visible border of the collection and make it selectable. This problem shows up after zooming/panning on a background collection -- you can drag the collection by clicking on apparently empty space outside the collection
}}>
{this.props.children}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index d9c988d54..12a299ce6 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -246,6 +246,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
onChildDoubleClickHandler = () => this._props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick);
elementFunc = () => this._layoutElements;
viewTransition = () => (this._panZoomTransition ? '' + this._panZoomTransition : undefined);
+ panZoomTransition = () => (this._panZoomTransition ? `transform ${this._panZoomTransition}ms` : Cast(this.layoutDoc._viewTransition, 'string', Cast(this.Document._viewTransition, 'string', null)));
fitContentOnce = () => {
const vals = this.fitToContentVals;
this.layoutDoc._freeform_panX = vals.bounds.cx;
@@ -1854,7 +1855,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
isAnnotationOverlay={this.isAnnotationOverlay}
transform={this.PanZoomCenterXf}
showPresPaths={this.showPresPaths}
- transition={this._panZoomTransition ? `transform ${this._panZoomTransition}ms` : Cast(this.layoutDoc._viewTransition, 'string', Cast(this.Document._viewTransition, 'string', null))}
+ transition={this.panZoomTransition}
viewDefDivClick={this._props.viewDefDivClick}>
{this.props.children ?? null} {/* most likely case of children is document content that's being annoated: eg., an image */}
{this.contentViews}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 5c91d5aca..3f453eb93 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -29,7 +29,6 @@ export interface FocusViewOptions {
openLocation?: OpenWhere; // where to open a missing document
zoomTextSelections?: boolean; // whether to display a zoomed overlay of anchor text selections
toggleTarget?: boolean; // whether to toggle target on and off
- anchorDoc?: Doc; // doc containing anchor info to apply at end of focus to target doc
easeFunc?: 'linear' | 'ease'; // transition method for scrolling
}
export type FocusFuncType = (doc: Doc, options: FocusViewOptions) => Opt<number>;
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 79738c452..1b2aefbe2 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -178,7 +178,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
if (selected.length > 1) {
text = selected.length + ' selected';
} else {
- text = ClientUtils.cleanDocumentType(StrCast(selected.lastElement().type) as DocumentType);
+ text = ClientUtils.cleanDocumentType(StrCast(selected.lastElement().type) as DocumentType, '' as CollectionViewType);
icon = Doc.toIcon(selected.lastElement());
}
return (
diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss
index 0f5e25a0c..7bca1230f 100644
--- a/src/client/views/nodes/PDFBox.scss
+++ b/src/client/views/nodes/PDFBox.scss
@@ -236,7 +236,7 @@
//pointer-events: none;
.pdfViewerDash-text {
.textLayer {
- display: none;
+ // display: none; // this makes search highlights not show up
span {
user-select: none;
}
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index cc897aaef..b03b90418 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -28,6 +28,7 @@ import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
import { Colors } from '../global/globalEnums';
+// eslint-disable-next-line import/extensions
import { CreateImage } from './WebBoxRenderer';
import { PDFViewer } from '../pdf/PDFViewer';
import { SidebarAnnos } from '../SidebarAnnos';
@@ -225,12 +226,13 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
);
}
- sidebarAddDocTab = (doc: Doc, where: OpenWhere) => {
- if (DocListCast(this.Document[this._props.fieldKey + '_sidebar']).includes(doc) && !this.SidebarShown) {
+ sidebarAddDocTab = (docIn: Doc | Doc[], where: OpenWhere) => {
+ const docs = docIn instanceof Doc ? [docIn] : docIn;
+ if (docs.some(doc => DocListCast(this.Document[this._props.fieldKey + '_sidebar']).includes(doc)) && !this.SidebarShown) {
this.toggleSidebar(false);
return true;
}
- return this._props.addDocTab(doc, where);
+ return this._props.addDocTab(docs, where);
};
focus = (anchor: Doc, options: FocusViewOptions) => {
this._initialScrollTarget = anchor;
@@ -344,7 +346,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
setupMoveUpEvents(
this,
e,
- (e, down, delta) => {
+ (moveEv, down, delta) => {
const localDelta = this._props
.ScreenToLocalTransform()
.scale(this._props.NativeDimScaling?.() || 1)
@@ -359,7 +361,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
}
return false;
},
- (e, movement, isClick) => !isClick && batch.end(),
+ (clickEv, movement, isClick) => !isClick && batch.end(),
() => {
onButton && this.toggleSidebar();
batch.end();
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index a3b1a419b..0a4efbfe4 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -104,7 +104,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
return DocCast(this.childDocs[NumCast(this.Document._itemIndex)]);
}
@computed get targetDoc() {
- return Cast(this.activeItem?.presentation_targetDoc, Doc, null);
+ return DocCast(this.activeItem?.presentation_targetDoc);
}
public static targetRenderedDoc = (doc: Doc) => {
const targetDoc = Cast(doc?.presentation_targetDoc, Doc, null);
@@ -774,7 +774,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
effect: activeItem,
noSelect: true,
openLocation: targetDoc.type === DocumentType.PRES ? ((OpenWhere.replace + ':' + PresBox.PanelName) as OpenWhere) : OpenWhere.addLeft,
- anchorDoc: activeItem,
easeFunc: StrCast(activeItem.presEaseFunc, 'ease') as any,
zoomTextSelections: BoolCast(activeItem.presentation_zoomText),
playAudio: BoolCast(activeItem.presPlayAudio),
diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index 053c88e17..38578837a 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -1,18 +1,20 @@
+/* eslint-disable react/jsx-props-no-spreading */
import { action, computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, DocListCast, Opt } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
-import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types';
+import { BoolCast, DocCast, NumCast, StrCast } from '../../../fields/Types';
import { LinkFollower } from '../../util/LinkFollower';
import { LinkManager } from '../../util/LinkManager';
-import { undoBatch } from '../../util/UndoManager';
+import { undoable } from '../../util/UndoManager';
+import { ObservableReactComponent } from '../ObservableReactComponent';
import { OpenWhere } from '../nodes/DocumentView';
import { FieldViewProps } from '../nodes/FieldView';
import { AnchorMenu } from './AnchorMenu';
import './Annotation.scss';
-import { ObservableReactComponent } from '../ObservableReactComponent';
+import { Highlight } from '../../../fields/DocSymbols';
interface IAnnotationProps extends FieldViewProps {
anno: Doc;
@@ -27,11 +29,41 @@ export class Annotation extends ObservableReactComponent<IAnnotationProps> {
super(props);
makeObservable(this);
}
+
+ @computed get linkHighlighted() {
+ const found = LinkManager.Instance.getAllDirectLinks(this._props.anno).find(link => {
+ const a1 = LinkManager.getOppositeAnchor(link, this._props.anno);
+ return a1 && Doc.GetBrushStatus(DocCast(a1.annotationOn, a1));
+ });
+ return found;
+ }
+ linkHighlightedFunc = () => this.linkHighlighted;
+ highlightedFunc = () => this._props.anno[Highlight];
+
+ deleteAnnotation = undoable(() => {
+ const docAnnotations = DocListCast(this._props.dataDoc[this._props.fieldKey]);
+ this._props.dataDoc[this._props.fieldKey] = new List<Doc>(docAnnotations.filter(a => a !== this._props.anno));
+ AnchorMenu.Instance.fadeOut(true);
+ this._props.select(false);
+ }, 'delete annotation');
+
+ pinToPres = undoable(() => this._props.pinToPres(this._props.anno, {}), 'pin to pres');
+
render() {
return (
<div style={{ display: this._props.anno.textCopied && !Doc.GetBrushHighlightStatus(this._props.anno) ? 'none' : undefined }}>
{DocListCast(this._props.anno.text_inlineAnnotations).map(a => (
- <RegionAnnotation pointerEvents={this._props.pointerEvents} {...this._props} document={a} key={a[Id]} />
+ // eslint-disable-next-line no-use-before-define
+ <RegionAnnotation
+ pointerEvents={this._props.pointerEvents}
+ {...this._props}
+ highlighted={this.highlightedFunc}
+ linkHighlighted={this.linkHighlightedFunc}
+ pinToPres={this.pinToPres}
+ deleteAnnotation={this.deleteAnnotation}
+ document={a}
+ key={a[Id]}
+ />
))}
</div>
);
@@ -40,49 +72,41 @@ export class Annotation extends ObservableReactComponent<IAnnotationProps> {
interface IRegionAnnotationProps extends IAnnotationProps {
document: Doc;
+ linkHighlighted: () => Doc | undefined;
+ highlighted: () => any;
+ deleteAnnotation: () => void;
+ pinToPres: (...args: any[]) => void;
pointerEvents?: () => Opt<string>;
}
@observer
class RegionAnnotation extends ObservableReactComponent<IRegionAnnotationProps> {
private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
- @computed get annoTextRegion() {
- return Cast(this._props.document.annoTextRegion, Doc, null) || this._props.document;
+ @computed get regionDoc() {
+ return DocCast(this._props.document.embedContainer, this._props.document);
}
- @undoBatch
- deleteAnnotation = () => {
- const docAnnotations = DocListCast(this._props.dataDoc[this._props.fieldKey]);
- this._props.dataDoc[this._props.fieldKey] = new List<Doc>(docAnnotations.filter(a => a !== this.annoTextRegion));
- AnchorMenu.Instance.fadeOut(true);
- this._props.select(false);
- };
-
- @undoBatch
- pinToPres = () => this._props.pinToPres(this.annoTextRegion, {});
+ makeTargetToggle = undoable(() => { this.regionDoc.followLinkToggle = !this.regionDoc.followLinkToggle }, "set link toggle"); // prettier-ignore
- @undoBatch
- makeTargetToggle = () => { this.annoTextRegion.followLinkToggle = !this.annoTextRegion.followLinkToggle }; // prettier-ignore
+ isTargetToggler = () => BoolCast(this.regionDoc.followLinkToggle);
- isTargetToggler = () => BoolCast(this.annoTextRegion.followLinkToggle);
- @undoBatch
- showTargetTrail = (anchor: Doc) => {
+ showTargetTrail = undoable((anchor: Doc) => {
const trail = DocCast(anchor.presentationTrail);
if (trail) {
Doc.ActivePresentation = trail;
this._props.addDocTab(trail, OpenWhere.replaceRight);
}
- };
+ }, 'show target trail');
@action
onContextMenu = (e: React.MouseEvent) => {
AnchorMenu.Instance.Status = 'annotation';
- AnchorMenu.Instance.Delete = this.deleteAnnotation.bind(this);
+ AnchorMenu.Instance.Delete = this._props.deleteAnnotation;
AnchorMenu.Instance.Pinned = false;
- AnchorMenu.Instance.PinToPres = this.pinToPres;
+ AnchorMenu.Instance.PinToPres = this._props.pinToPres;
AnchorMenu.Instance.MakeTargetToggle = this.makeTargetToggle;
AnchorMenu.Instance.IsTargetToggler = this.isTargetToggler;
- AnchorMenu.Instance.ShowTargetTrail = () => this.showTargetTrail(this.annoTextRegion);
+ AnchorMenu.Instance.ShowTargetTrail = () => this.showTargetTrail(this.regionDoc);
AnchorMenu.Instance.jumpTo(e.clientX, e.clientY, true);
e.stopPropagation();
e.preventDefault();
@@ -94,19 +118,12 @@ class RegionAnnotation extends ObservableReactComponent<IRegionAnnotationProps>
e.preventDefault();
} else if (e.button === 0) {
e.stopPropagation();
- LinkFollower.FollowLink(undefined, this.annoTextRegion, false);
+ LinkFollower.FollowLink(undefined, this.regionDoc, false);
}
};
- @computed get linkHighlighted() {
- for (const link of LinkManager.Instance.getAllDirectLinks(this._props.document)) {
- const a1 = LinkManager.getOppositeAnchor(link, this._props.document);
- if (a1 && Doc.GetBrushStatus(DocCast(a1.annotationOn, this._props.document))) return true;
- }
- }
-
render() {
- const brushed = this.annoTextRegion && Doc.GetBrushHighlightStatus(this.annoTextRegion);
+ const brushed = this.regionDoc && Doc.GetBrushHighlightStatus(this.regionDoc);
return (
<div
className="htmlAnnotation"
@@ -128,8 +145,8 @@ class RegionAnnotation extends ObservableReactComponent<IRegionAnnotationProps>
height: NumCast(this._props.document._height),
opacity: brushed === Doc.DocBrushStatus.highlighted ? 0.5 : undefined,
pointerEvents: this._props.pointerEvents?.() as any,
- outline: brushed === Doc.DocBrushStatus.unbrushed && this.linkHighlighted ? 'solid 1px lightBlue' : undefined,
- backgroundColor: brushed === Doc.DocBrushStatus.highlighted ? 'orange' : StrCast(this._props.document.backgroundColor),
+ outline: this._props.linkHighlighted() ? 'solid 1px lightBlue' : undefined,
+ backgroundColor: this._props.highlighted() ? 'orange' : StrCast(this._props.document.backgroundColor),
}}
/>
);
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 0ab952e84..a3fd192f7 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -1,3 +1,5 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as Pdfjs from 'pdfjs-dist';
@@ -10,7 +12,7 @@ import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
import { Cast, NumCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, Utils } from '../../../Utils';
+import { emptyFunction } from '../../../Utils';
import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, ClientUtils, returnAll, returnFalse, returnNone, returnZero, smoothScroll } from '../../../ClientUtils';
import { DocUtils } from '../../documents/Documents';
import { SelectionManager } from '../../util/SelectionManager';
@@ -27,9 +29,8 @@ import { AnchorMenu } from './AnchorMenu';
import { Annotation } from './Annotation';
import { GPTPopup } from './GPTPopup/GPTPopup';
import './PDFViewer.scss';
-const _global = (window /* browser */ || global) /* node */ as any;
-//pdfjsLib.GlobalWorkerOptions.workerSrc = `/assets/pdf.worker.js`;
+// pdfjsLib.GlobalWorkerOptions.workerSrc = `/assets/pdf.worker.js`;
// The workerSrc property shall be specified.
Pdfjs.GlobalWorkerOptions.workerSrc = 'https://unpkg.com/pdfjs-dist@4.1.392/build/pdf.worker.mjs';
@@ -43,6 +44,7 @@ interface IViewerProps extends FieldViewProps {
url: string;
sidebarAddDoc: (doc: Doc | Doc[], sidebarKey?: string | undefined) => boolean;
loaded?: (nw: number, nh: number, np: number) => void;
+ // eslint-disable-next-line no-use-before-define
setPdfViewer: (view: PDFViewer) => void;
anchorMenuClick?: () => undefined | ((anchor: Doc) => void);
crop: (region: Doc | undefined, addCrop?: boolean) => Doc | undefined;
@@ -109,8 +111,8 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
this._disposers.layout_autoHeight = reaction(
() => this._props.layoutDoc._layout_autoHeight,
- layout_autoHeight => {
- if (layout_autoHeight) {
+ layoutAutoHeight => {
+ if (layoutAutoHeight) {
this._props.layoutDoc._nativeHeight = NumCast(this._props.Document[this._props.fieldKey + '_nativeHeight']);
this._props.setHeight?.(NumCast(this._props.Document[this._props.fieldKey + '_nativeHeight']) * (this._props.NativeDimScaling?.() || 1));
}
@@ -119,7 +121,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
this._disposers.selected = reaction(
() => this._props.isSelected(),
- selected => SelectionManager.Views.length === 1 && this.setupPdfJsViewer(),
+ () => SelectionManager.Views.length === 1 && this.setupPdfJsViewer(),
{ fireImmediately: true }
);
this._disposers.curPage = reaction(
@@ -169,7 +171,9 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
)
);
}
- runInAction(() => (this._scrollHeight = (this._pageSizes.reduce((size, page) => size + page.height, 0) * 96) / 72));
+ runInAction(() => {
+ this._scrollHeight = (this._pageSizes.reduce((size, page) => size + page.height, 0) * 96) / 72;
+ });
};
_scrollStopper: undefined | (() => void);
@@ -207,14 +211,18 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
pagesinit = () => {
if (this._pdfViewer._setDocumentViewerElement?.offsetParent) {
- runInAction(() => (this._pdfViewer.currentScaleValue = this._props.layoutDoc._freeform_scale = 1));
+ runInAction(() => {
+ this._pdfViewer.currentScaleValue = this._props.layoutDoc._freeform_scale = 1;
+ });
this.gotoPage(NumCast(this._props.Document._layout_curPage, 1));
}
document.removeEventListener('pagesinit', this.pagesinit);
- var quickScroll: { loc?: string; easeFunc?: 'ease' | 'linear' } | undefined = { loc: this._initialScroll ? this._initialScroll.loc?.toString() : '', easeFunc: this._initialScroll ? this._initialScroll.easeFunc : undefined };
+ let quickScroll: { loc?: string; easeFunc?: 'ease' | 'linear' } | undefined = { loc: this._initialScroll ? this._initialScroll.loc?.toString() : '', easeFunc: this._initialScroll ? this._initialScroll.easeFunc : undefined };
this._disposers.scale = reaction(
() => NumCast(this._props.layoutDoc._freeform_scale, 1),
- scale => (this._pdfViewer.currentScaleValue = scale),
+ scale => {
+ this._pdfViewer.currentScaleValue = scale;
+ },
{ fireImmediately: true }
);
this._disposers.scroll = reaction(
@@ -231,7 +239,9 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
setTimeout(
() => {
this._mainCont.current && (this._scrollStopper = smoothScroll(duration, this._mainCont.current, pos, this._initialScroll?.easeFunc ?? 'ease', this._scrollStopper));
- setTimeout(() => (this._forcedScroll = false), duration);
+ setTimeout(() => {
+ this._forcedScroll = false;
+ }, duration);
},
this._mainCont.current ? 0 : 250
); // wait for mainCont and try again to scroll
@@ -267,7 +277,9 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
eventBus._on('pagesinit', this.pagesinit);
eventBus._on(
'pagerendered',
- action(() => (this._showWaiting = false))
+ action(() => {
+ this._showWaiting = false;
+ })
);
const pdfLinkService = new PDFJSViewer.PDFLinkService({ eventBus });
const pdfFindController = new PDFJSViewer.PDFFindController({ linkService: pdfLinkService, eventBus });
@@ -310,7 +322,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
@observable private _scrollTimer: any = undefined;
- onScroll = (e: React.UIEvent<HTMLElement>) => {
+ onScroll = () => {
if (this._mainCont.current && !this._forcedScroll) {
this._ignoreScroll = true; // the pdf scrolled, so we need to tell the Doc to scroll but we don't want the doc to then try to set the PDF scroll pos (which would interfere with the smooth scroll animation)
if (!LinkInfo.Instance?.LinkInfo) {
@@ -345,7 +357,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
query: searchString,
};
if (clear) {
- this._pdfViewer?.eventBus.dispatch('reset', {});
+ this._pdfViewer?.eventBus.dispatch('findbarclose', {});
} else if (!searchString) {
bwd ? this.prevAnnotation() : this.nextAnnotation();
} else if (this._pdfViewer?.pageViewsReady) {
@@ -392,7 +404,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
};
@action
- finishMarquee = (x?: number, y?: number) => {
+ finishMarquee = (/* x?: number, y?: number */) => {
this._getAnchor = AnchorMenu.Instance?.GetAnchor;
this.isAnnotating = false;
this._marqueeref.current?.onTerminateSelection();
@@ -467,7 +479,9 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
// e.stopPropagation(); // bcz: not sure why this was here. We need to allow the DocumentView to get clicks to process doubleClicks
};
- setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void) => (this._setPreviewCursor = func);
+ setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void) => {
+ this._setPreviewCursor = func;
+ };
@action
onZoomWheel = (e: React.WheelEvent) => {
@@ -490,6 +504,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
return (
<div className="pdfViewerDash-annotationLayer" style={{ height: Doc.NativeHeight(this._props.Document), transform: `scale(${NumCast(this._props.layoutDoc._freeform_scale, 1)})` }} ref={this._annotationLayer}>
{inlineAnnos.map(anno => (
+ // eslint-disable-next-line react/jsx-props-no-spreading
<Annotation {...this._props} fieldKey={this._props.fieldKey + '_annotations'} pointerEvents={this.pointerEvents} dataDoc={this._props.dataDoc} anno={anno} key={`${anno[Id]}-annotation`} />
))}
</div>
@@ -522,6 +537,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
pointerEvents: Doc.ActiveTool !== InkTool.None ? 'all' : undefined,
}}>
<CollectionFreeFormView
+ // eslint-disable-next-line react/jsx-props-no-spreading
{...this._props}
NativeWidth={returnZero}
NativeHeight={returnZero}
@@ -529,7 +545,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
pointerEvents={this._props.isContentActive() && (SnappingManager.IsDragging || Doc.ActiveTool !== InkTool.None) ? returnAll : returnNone} // freeform view doesn't get events unless something is being dragged onto it.
childPointerEvents={this.childPointerEvents} // but freeform children need to get events to allow text editing, etc
renderDepth={this._props.renderDepth + 1}
- isAnnotationOverlay={true}
+ isAnnotationOverlay
fieldKey={this._props.fieldKey + '_annotations'}
getScrollHeight={this.getScrollHeight}
setPreviewCursor={this.setPreviewCursor}
@@ -582,7 +598,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
{this.pdfViewerDiv}
{this.annotationLayer}
{this.overlayLayer}
- {this._showWaiting ? <img className="pdfViewerDash-waiting" src={'/assets/loading.gif'} /> : null}
+ {this._showWaiting ? <img alt="" className="pdfViewerDash-waiting" src="/assets/loading.gif" /> : null}
{!this._mainCont.current || !this._annotationLayer.current ? null : (
<MarqueeAnnotator
ref={this._marqueeref}
@@ -590,7 +606,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
getPageFromScroll={this.getPageFromScroll}
anchorMenuClick={this._props.anchorMenuClick}
scrollTop={0}
- isNativeScaled={true}
+ isNativeScaled
annotationLayerScrollTop={NumCast(this._props.Document._layout_scrollTop)}
addDocument={this.addDocumentWrapper}
docView={this._props.pdfBox.DocumentView!}
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 0c1a419aa..384e6d654 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -6,7 +6,6 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, DocListCastAsync, Field, FieldType } from '../../../fields/Doc';
import { DirectLinks, DocData } from '../../../fields/DocSymbols';
-import { Id } from '../../../fields/FieldSymbols';
import { DocCast, StrCast } from '../../../fields/Types';
import { DocumentType } from '../../documents/DocumentTypes';
import { DocUtils } from '../../documents/Documents';
@@ -16,16 +15,111 @@ import { SearchUtil } from '../../util/SearchUtil';
import { SettingsManager } from '../../util/SettingsManager';
import { undoBatch } from '../../util/UndoManager';
import { ViewBoxBaseComponent } from '../DocComponent';
+import { ObservableReactComponent } from '../ObservableReactComponent';
import { CollectionDockingView } from '../collections/CollectionDockingView';
import { IRecommendation, Recommendation } from '../newlightbox/components';
import { fetchRecommendations } from '../newlightbox/utils';
import { FieldView, FieldViewProps } from '../nodes/FieldView';
import './SearchBox.scss';
+import { Id } from '../../../fields/FieldSymbols';
+import { ClientUtils } from '../../../ClientUtils';
const DAMPENING_FACTOR = 0.9;
const MAX_ITERATIONS = 25;
const ERROR = 0.03;
+export interface SearchBoxItemProps {
+ Document: Doc;
+ searchString: string;
+ isLinkSearch: boolean;
+ matchedKeys: string[];
+ className: string;
+ linkFrom: Doc | undefined;
+ selectItem: (doc: Doc) => void;
+ linkCreateAnchor?: () => Doc | undefined;
+ linkCreated?: (link: Doc) => void;
+}
+@observer
+export class SearchBoxItem extends ObservableReactComponent<SearchBoxItemProps> {
+ constructor(props: SearchBoxItemProps) {
+ super(props);
+ makeObservable(this);
+ }
+
+ /**
+ * @param {Doc} doc - doc to be selected
+ *
+ * This method selects a doc by either jumping to it (centering/zooming in on it)
+ * or opening it in a new tab.
+ */
+ selectElement = async (doc: Doc, finishFunc: () => void) => {
+ await DocumentManager.Instance.showDocument(doc, { willZoomCentered: true }, finishFunc);
+ };
+
+ /**
+ * @param {Doc} doc - doc of the search result that has been clicked on
+ *
+ * This method is called when the user clicks on a search result. The _selectedResult is
+ * updated accordingly and the doc is highlighted with the selectElement method.
+ */
+ onResultClick = action(async (doc: Doc) => {
+ this._props.selectItem(doc);
+ this.selectElement(doc, () => DocumentManager.Instance.getFirstDocumentView(doc)?.ComponentView?.search?.(this._props.searchString, undefined, false));
+ });
+
+ componentWillUnmount(): void {
+ const doc = this._props.Document;
+ DocumentManager.Instance.getFirstDocumentView(doc)?.ComponentView?.search?.('', undefined, true);
+ }
+
+ @undoBatch
+ makeLink = action((linkTo: Doc) => {
+ const linkFrom = this._props.linkCreateAnchor?.();
+ if (linkFrom) {
+ const link = DocUtils.MakeLink(linkFrom, linkTo, {});
+ link && this._props.linkCreated?.(link);
+ }
+ });
+
+ render() {
+ // eslint-disable-next-line no-use-before-define
+ const formattedType = SearchBox.formatType(StrCast(this._props.Document.type), StrCast(this._props.Document.type_collection));
+ const { title } = this._props.Document;
+
+ return (
+ <Tooltip placement="right" title={<div className="dash-tooltip">{title as string}</div>}>
+ <div
+ onClick={
+ this._props.isLinkSearch
+ ? () => this.makeLink(this._props.Document)
+ : e => {
+ this.onResultClick(this._props.Document);
+ e.stopPropagation();
+ }
+ }
+ style={{
+ fontWeight: LinkManager.Links(this._props.linkFrom).find(
+ link =>
+ Doc.AreProtosEqual(LinkManager.getOppositeAnchor(link, this._props.linkFrom!), this._props.Document) ||
+ Doc.AreProtosEqual(DocCast(LinkManager.getOppositeAnchor(link, this._props.linkFrom!)?.annotationOn), this._props.Document)
+ )
+ ? 'bold'
+ : '',
+ }}
+ className={this._props.className}>
+ <div className="searchBox-result-title">{title as string}</div>
+ <div className="searchBox-result-type" style={{ color: SettingsManager.userVariantColor }}>
+ {formattedType}
+ </div>
+ <div className="searchBox-result-keys" style={{ color: SettingsManager.userVariantColor }}>
+ {this._props.matchedKeys.join(', ')}
+ </div>
+ </div>
+ </Tooltip>
+ );
+ }
+}
+
export interface SearchBoxProps extends FieldViewProps {
linkSearch: boolean;
linkFrom?: (() => Doc | undefined) | undefined;
@@ -112,26 +206,6 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
});
/**
- * @param {Doc} doc - doc of the search result that has been clicked on
- *
- * This method is called when the user clicks on a search result. The _selectedResult is
- * updated accordingly and the doc is highlighted with the selectElement method.
- */
- onResultClick = action(async (doc: Doc) => {
- this._selectedResult = doc;
- this.selectElement(doc, () => DocumentManager.Instance.getFirstDocumentView(doc)?.ComponentView?.search?.(this._searchString, undefined, false));
- });
-
- @undoBatch
- makeLink = action((linkTo: Doc) => {
- const linkFrom = this._props.linkCreateAnchor?.();
- if (linkFrom) {
- const link = DocUtils.MakeLink(linkFrom, linkTo, {});
- link && this._props.linkCreated?.(link);
- }
- });
-
- /**
* @param {Doc[]} docs - docs to be searched through recursively
* @param {number, Doc => void} func - function to be called on each doc
*
@@ -217,7 +291,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
if (doc[DocData][DirectLinks].size === 0) {
this._linkedDocsOut.set(doc, new Set(this._results.keys()));
- this._results.forEach((_, linkedDoc) => {
+ this._results.forEach((__, linkedDoc) => {
this._linkedDocsIn.get(linkedDoc)?.add(doc);
});
} else {
@@ -251,7 +325,6 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
pageRankIteration(): boolean {
let converged = true;
const pageRankFromAll = (1 - DAMPENING_FACTOR) / this._results.size;
-
const nextPageRanks = new Map<Doc, number>();
this._results.forEach((_, doc) => {
@@ -346,16 +419,6 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
});
/**
- * @param {Doc} doc - doc to be selected
- *
- * This method selects a doc by either jumping to it (centering/zooming in on it)
- * or opening it in a new tab.
- */
- selectElement = async (doc: Doc, finishFunc: () => void) => {
- await DocumentManager.Instance.showDocument(doc, { willZoomCentered: true }, finishFunc);
- };
-
- /**
* This method returns a JSX list of the options in the select drop-down menu, which
* is used to filter the types of documents that appear in the search results.
*/
@@ -365,7 +428,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
return selectValues.map(value => (
<option key={value} value={value}>
- {SearchBox.formatType(value, '')}
+ {ClientUtils.cleanDocumentTypeExt(value as DocumentType)}
</option>
));
}
@@ -374,56 +437,36 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
* This method renders the search input box, select drop-down menu, and search results.
*/
render() {
- let validResults = 0;
-
const isLinkSearch: boolean = this._props.linkSearch;
-
const sortedResults = Array.from(this._results.entries()).sort((a, b) => (this._pageRanks.get(b[0]) ?? 0) - (this._pageRanks.get(a[0]) ?? 0)); // sorted by page rank
-
const resultsJSX = [] as any[];
+ const linkFrom = this._props.linkFrom?.();
- const fromDoc = this._props.linkFrom?.();
-
- sortedResults.forEach(result => {
+ let validResults = 0;
+ sortedResults.forEach(([Document, matchedKeys]) => {
let className = 'searchBox-results-scroll-view-result';
- if (this._selectedResult === result[0]) {
+ if (this._selectedResult === Document) {
className += ' searchBox-results-scroll-view-result-selected';
}
- const formattedType = SearchBox.formatType(StrCast(result[0].type), StrCast(result[0].type_collection));
- const { title } = result[0];
-
- if (this._docTypeString === 'keys' || this._docTypeString === 'all' || this._docTypeString === result[0].type) {
+ if (this._docTypeString === 'keys' || this._docTypeString === 'all' || this._docTypeString === Document.type) {
validResults++;
resultsJSX.push(
- <Tooltip key={result[0][Id]} placement="right" title={<div className="dash-tooltip">{title as string}</div>}>
- <div
- onClick={
- isLinkSearch
- ? () => this.makeLink(result[0])
- : e => {
- this.onResultClick(result[0]);
- e.stopPropagation();
- }
- }
- style={{
- fontWeight: LinkManager.Links(fromDoc).find(
- link => Doc.AreProtosEqual(LinkManager.getOppositeAnchor(link, fromDoc!), result[0] as Doc) || Doc.AreProtosEqual(DocCast(LinkManager.getOppositeAnchor(link, fromDoc!)?.annotationOn), result[0] as Doc)
- )
- ? 'bold'
- : '',
- }}
- className={className}>
- <div className="searchBox-result-title">{title as string}</div>
- <div className="searchBox-result-type" style={{ color: SettingsManager.userVariantColor }}>
- {formattedType}
- </div>
- <div className="searchBox-result-keys" style={{ color: SettingsManager.userVariantColor }}>
- {result[1].join(', ')}
- </div>
- </div>
- </Tooltip>
+ <SearchBoxItem
+ key={Document[Id]}
+ Document={Document}
+ selectItem={action((doc: Doc) => {
+ this._selectedResult = doc;
+ })}
+ isLinkSearch={isLinkSearch}
+ searchString={this._searchString}
+ matchedKeys={matchedKeys}
+ linkFrom={linkFrom}
+ className={className}
+ linkCreateAnchor={this._props.linkCreateAnchor}
+ linkCreated={this._props.linkCreated}
+ />
);
}
});
diff --git a/src/client/views/selectedDoc/SelectedDocView.tsx b/src/client/views/selectedDoc/SelectedDocView.tsx
index c9c01189e..7ad7b2927 100644
--- a/src/client/views/selectedDoc/SelectedDocView.tsx
+++ b/src/client/views/selectedDoc/SelectedDocView.tsx
@@ -35,7 +35,7 @@ export class SelectedDocView extends React.Component<SelectedDocViewProps> {
val: StrCast(doc._id),
color: SettingsManager.userColor,
background: SettingsManager.userBackgroundColor,
- icon: <FontAwesomeIcon size={'1x'} icon={Doc.toIcon(doc)} />,
+ icon: <FontAwesomeIcon size="1x" icon={Doc.toIcon(doc)} />,
onClick: () => DocumentManager.Instance.showDocument(doc, options, emptyFunction),
};
})}
diff --git a/src/client/views/selectedDoc/index.ts b/src/client/views/selectedDoc/index.ts
index 1f1db91f6..968e9c2d4 100644
--- a/src/client/views/selectedDoc/index.ts
+++ b/src/client/views/selectedDoc/index.ts
@@ -1 +1 @@
-export * from './SelectedDocView' \ No newline at end of file
+export * from './SelectedDocView';
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 5028e1f8f..7b5e21ab7 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1235,6 +1235,8 @@ export namespace Doc {
// if doc is a layout template then we don't want to highlight the proto since that will be the entire template, not just the specific layout field
highlightedDocs.add(doc[DocData]);
doc[DocData][Highlight] = true;
+ // want to highlight the targets of presentation docs explicitly since following a pres target does not highlight PDf <Annotations> which are not DocumentViews
+ if (doc.presentation_targetDoc) DocCast(doc.presentation_targetDoc)[Highlight] = true;
}
});
}
@@ -1246,6 +1248,7 @@ export namespace Doc {
highlightedDocs.delete(doc[DocData]);
doc[Highlight] = doc[DocData][Highlight] = false;
doc[Animation] = undefined;
+ if (doc.presentation_targetDoc) DocCast(doc.presentation_targetDoc)[Highlight] = false;
});
});
}
diff --git a/src/fields/List.ts b/src/fields/List.ts
index 852b05bc6..38c47d546 100644
--- a/src/fields/List.ts
+++ b/src/fields/List.ts
@@ -308,7 +308,7 @@ class ListImpl<T extends FieldType> extends ObjectField {
// eslint-disable-next-line no-use-before-define
private [SelfProxy]: List<FieldType>; // also used in utils.ts even though it won't be found using find all references
- [ToScriptString]() { return `new List(${this[ToJavascriptString]})`; } // prettier-ignore
+ [ToScriptString]() { return `new List(${this[ToJavascriptString]()})`; } // prettier-ignore
[ToJavascriptString]() { return `[${(this as any).map((field: any) => Field.toScriptString(field))}]`; } // prettier-ignore
[ToString]() { return `[${(this as any).map((field: any) => Field.toString(field))}]`; } // prettier-ignore
}