From 12d8267533d9b646247914e965b3cf7c32019e4b Mon Sep 17 00:00:00 2001 From: geireann Date: Thu, 2 Sep 2021 04:45:01 -0400 Subject: Many updates - Fixed image uploads so it clones rather than makes an alias - Updated context menu - Removed tools panel from novice mode in favour of ":" menu - Added explainers to menus in novice mode - Re-added the trails button - Changed UI for text, PDF & websites so that it is more consistent --- src/client/views/nodes/PDFBox.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src/client/views/nodes/PDFBox.tsx') diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 5e07229c1..3a399bfdb 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -24,6 +24,7 @@ import { pageSchema } from "./ImageBox"; import "./PDFBox.scss"; import React = require("react"); import { AnchorMenu } from '../pdf/AnchorMenu'; +import { Colors } from '../global/globalEnums'; type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>; const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema); @@ -208,11 +209,15 @@ export class PDFBox extends ViewBoxAnnotatableComponent this._pageControls = !this._pageControls)} /> {this._pageControls ? pageBtns : (null)} - + + ; } sidebarWidth = () => !this.SidebarShown ? 0 : -- cgit v1.2.3-70-g09d2 From 80baae4dcf49f818dca4dbfe340013e0e9d197bb Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 3 Sep 2021 03:58:21 -0400 Subject: fixed drawing of link lines - doesn't generate duplicates, and works with text regions, scroll locations, and document anchors. --- src/client/documents/Documents.ts | 9 +++--- src/client/util/DocumentManager.ts | 37 ++++++++++++++-------- .../CollectionFreeFormLinkView.tsx | 8 ++--- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 24 ++++++++++---- src/client/views/nodes/PDFBox.tsx | 10 +++--- src/client/views/nodes/WebBox.tsx | 10 +++--- .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- 8 files changed, 63 insertions(+), 39 deletions(-) (limited to 'src/client/views/nodes/PDFBox.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index bd247bd01..671e27408 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -157,6 +157,7 @@ export class DocumentOptions { z?: number; // whether document is in overlay (1) or not (0 or undefined) author?: string; _layoutKey?: string; + unrendered?: boolean; // denotes an annotation that is not rendered with a DocumentView (e.g, rtf/pdf text selections and links to scroll locations in web/pdf) type?: string; title?: string; "acl-Public"?: string; // public permissions @@ -277,7 +278,7 @@ export class DocumentOptions { // Action Button buttonMenu?: boolean; // whether a action button should be displayed buttonMenuDoc?: Doc; - explainer?:string; + explainer?: string; treeViewOpenIsTransient?: boolean; // ignores the treeViewOpen Doc flag, allowing a treeViewItem's expand/collapse state to be independent of other views of the same document in the same or any other tree view _treeViewOpen?: boolean; // whether this document is expanded in a tree view (note: need _ and regular versions since this can be specified for both proto and layout docs) @@ -1188,7 +1189,7 @@ export namespace DocUtils { })) as ContextMenuProps[], icon: "sticky-note" }); - const math:ContextMenuProps = ({ + const math: ContextMenuProps = ({ description: ":Math", event: () => { const created = Docs.Create.EquationDocument(); if (created) { @@ -1202,7 +1203,7 @@ export namespace DocUtils { } }, icon: "calculator" }); - const documentList:ContextMenuProps[] = DocListCast(Cast(Doc.UserDoc().myItemCreators, Doc, null)?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({ + const documentList: ContextMenuProps[] = DocListCast(Cast(Doc.UserDoc().myItemCreators, Doc, null)?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({ description: ":" + StrCast(dragDoc.title), event: undoBatch((args: { x: number, y: number }) => { const newDoc = Doc.copyDragFactory(dragDoc); @@ -1215,7 +1216,7 @@ export namespace DocUtils { } }), icon: Doc.toIcon(dragDoc), - })) as ContextMenuProps[]; + })) as ContextMenuProps[]; documentList.push(math) ContextMenu.Instance.addItem({ description: "Create document", diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index cb0ee411c..b72a3189d 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -25,24 +25,35 @@ export class DocumentManager { @action public AddView = (view: DocumentView) => { - DocListCast(view.rootDoc.links).forEach(link => { - const whichOtherAnchor = view.props.LayoutTemplateString?.includes("anchor2") ? "anchor1" : "anchor2"; - const otherDoc = link && (link[whichOtherAnchor] as Doc); - const otherDocAnno = DocumentType.MARKER === otherDoc?.type ? otherDoc.annotationOn as Doc : undefined; - otherDoc && DocumentManager.Instance.DocumentViews?.filter(dv => Doc.AreProtosEqual(dv.rootDoc, otherDoc) || Doc.AreProtosEqual(dv.rootDoc, otherDocAnno)). - forEach(otherView => { - if (otherView.rootDoc.type !== DocumentType.LINK || otherView.props.LayoutTemplateString !== view.props.LayoutTemplateString) { - this.LinkedDocumentViews.push({ a: whichOtherAnchor === "anchor1" ? otherView : view, b: whichOtherAnchor === "anchor1" ? view : otherView, l: link }); - } - }); - }); + //console.log("MOUNT " + view.props.Document.title + "/" + view.props.LayoutTemplateString); + if (view.props.LayoutTemplateString?.includes("LinkAnchorBox")) { + const viewAnchorIndex = view.props.LayoutTemplateString.includes("anchor2") ? "anchor2" : "anchor1"; + view.props.LayoutTemplateString && DocListCast(view.rootDoc.links).forEach(link => { + DocumentManager.Instance.DocumentViews?.filter(dv => Doc.AreProtosEqual(dv.rootDoc, link) && !dv.props.LayoutTemplateString?.includes(viewAnchorIndex)). + forEach(otherView => { + this.LinkedDocumentViews.push( + { + a: viewAnchorIndex === "anchor2" ? otherView : view, + b: viewAnchorIndex === "anchor2" ? view : otherView, + l: link + }); + }); + }); + // this.LinkedDocumentViews.forEach(view => console.log(" LV = " + view.a.props.Document.title + "/" + view.a.props.LayoutTemplateString + " --> " + + // view.b.props.Document.title + "/" + view.b.props.LayoutTemplateString)); + } this.DocumentViews.push(view); } public RemoveView = action((view: DocumentView) => { + this.LinkedDocumentViews.slice().forEach(action(pair => { + if (pair.a === view || pair.b === view) { + const li = this.LinkedDocumentViews.indexOf(pair); + li !== -1 && this.LinkedDocumentViews.splice(li, 1); + } + })); + const index = this.DocumentViews.indexOf(view); index !== -1 && this.DocumentViews.splice(index, 1); - - this.LinkedDocumentViews.slice().forEach(action((pair, i) => pair.a === view || pair.b === view ? this.LinkedDocumentViews.splice(i, 1) : null)); }); //gets all views diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 16258404d..6fe46bbb2 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -43,8 +43,8 @@ export class CollectionFreeFormLinkView extends React.Component this._opacity = 1), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render() setTimeout(action(() => (!LinkDocs.length || !linkDoc.linkDisplay) && (this._opacity = 0.05)), 750); // this will unhighlight the link line. - const acont = A.rootDoc.type === DocumentType.LINK ? A.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; - const bcont = B.rootDoc.type === DocumentType.LINK ? B.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; + const acont = A.ContentDiv.getElementsByClassName("linkAnchorBox-cont"); + const bcont = B.ContentDiv.getElementsByClassName("linkAnchorBox-cont"); const adiv = acont.length ? acont[0] : A.ContentDiv; const bdiv = bcont.length ? bcont[0] : B.ContentDiv; const a = adiv.getBoundingClientRect(); @@ -140,8 +140,8 @@ export class CollectionFreeFormLinkView extends React.Component + Doc.AreProtosEqual(link.anchor1 as Doc, this.rootDoc) || + Doc.AreProtosEqual(link.anchor2 as Doc, this.rootDoc) || + ((link.anchor1 as Doc).unrendered && Doc.AreProtosEqual((link.anchor1 as Doc).annotationOn as Doc, this.rootDoc)) || + ((link.anchor2 as Doc).unrendered && Doc.AreProtosEqual((link.anchor2 as Doc).annotationOn as Doc, this.rootDoc)) + ); + } @computed get allLinks() { TraceMobx(); return LinkManager.Instance.getAllRelatedLinks(this.rootDoc); } @computed get allLinkEndpoints() { // the small blue dots that mark the endpoints of links TraceMobx(); - if (this.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return null; + if (this.layoutDoc.unrendered || this.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return null; if (this.layoutDoc.presBox || this.rootDoc.type === DocumentType.LINK || this.props.dontRegisterView) return (null); - // need to use allLinks for RTF since embedded linked text anchors are not rendered with DocumentViews. All other documents render their anchors with nested DocumentViews so we just need to render the directLinks here - const filtered = DocUtils.FilterDocs(this.rootDoc.type === DocumentType.RTF ? this.allLinks : this.directLinks, this.props.docFilters?.() ?? [], []).filter(d => !d.hidden); + const filtered = DocUtils.FilterDocs(this.directLinks, this.props.docFilters?.() ?? [], []).filter(d => !d.hidden); return filtered.map((link, i) => -
+
{ } componentWillUnmount() { Object.values(this._disposers).forEach(disposer => disposer?.()); - !this.props.dontRegisterView && DocumentManager.Instance.RemoveView(this); + !BoolCast(this.props.Document.dontRegisterView, this.props.dontRegisterView) && DocumentManager.Instance.RemoveView(this); } render() { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 3a399bfdb..2bafb3b7f 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -79,9 +79,9 @@ export class PDFBox extends ViewBoxAnnotatableComponent
- +
; } diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 1f85219d6..eaedd48c7 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -187,8 +187,8 @@ export class WebBox extends ViewBoxAnnotatableComponent
- +
); } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 59d43f8d7..bc578f95d 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -713,7 +713,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const splitter = state.schema.marks.splitter.create({ id: Utils.GenerateGuid() }); let tr = state.tr.addMark(sel.from, sel.to, splitter); if (sel.from !== sel.to) { - const anchor = anchorDoc ?? Docs.Create.TextanchorDocument({ title: this._editorView?.state.doc.textBetween(sel.from, sel.to) }); + const anchor = anchorDoc ?? Docs.Create.TextanchorDocument({ title: this._editorView?.state.doc.textBetween(sel.from, sel.to), unrendered: true }); const href = targetHref ?? Doc.localServerPath(anchor); if (anchor !== anchorDoc) this.addDocument(anchor); tr.doc.nodesBetween(sel.from, sel.to, (node: any, pos: number, parent: any) => { -- cgit v1.2.3-70-g09d2 From 64ff849d21273f7440917ef15a4b1c7f1909687c Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 3 Sep 2021 13:16:48 -0400 Subject: fixed warnings. cleaned up link lines a bit more - simplified, and allowed multiple aliases to share a link. fixed link lines to text anchors from flapping around wildly when camera pans --- src/client/documents/Documents.ts | 2 +- src/client/util/CurrentUserUtils.ts | 12 +++---- src/client/util/DocumentManager.ts | 38 +++++++++++++--------- src/client/views/PropertiesButtons.tsx | 2 +- .../CollectionFreeFormLinkView.tsx | 13 +++++--- .../CollectionFreeFormLinksView.tsx | 19 ++--------- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/LinkAnchorBox.tsx | 1 - src/client/views/nodes/PDFBox.tsx | 10 +++--- src/client/views/nodes/WebBox.tsx | 4 +-- .../views/nodes/button/textButton/TextButton.tsx | 2 +- src/client/views/nodes/button/textButton/index.ts | 2 +- .../views/nodes/button/toggleButton/index.ts | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 13 +++----- src/client/views/pdf/PDFViewer.tsx | 5 ++- 15 files changed, 60 insertions(+), 67 deletions(-) (limited to 'src/client/views/nodes/PDFBox.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 671e27408..9a45da440 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1217,7 +1217,7 @@ export namespace DocUtils { }), icon: Doc.toIcon(dragDoc), })) as ContextMenuProps[]; - documentList.push(math) + documentList.push(math); ContextMenu.Instance.addItem({ description: "Create document", subitems: documentList, diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 56807c63b..f9c55da29 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -832,7 +832,7 @@ export class CurrentUserUtils { await doc.myTrails; if (doc.myTrails === undefined) { const newTrail = ScriptField.MakeScript(`createNewPresentation()`); - const newTrailButton:Doc = Docs.Create.FontIconDocument({ onClick: newTrail, _forceActive: true, toolTip: "New trail", _stayInCollection: true, _hideContextMenu: true, title: "New trail", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New trail", icon: "plus", system: true }); + const newTrailButton: Doc = Docs.Create.FontIconDocument({ onClick: newTrail, _forceActive: true, toolTip: "New trail", _stayInCollection: true, _hideContextMenu: true, title: "New trail", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New trail", icon: "plus", system: true }); doc.myTrails = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Trails", _showTitle: "title", _height: 100, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _fitWidth: true, _gridGap: 5, _forceActive: true, childDropAction: "alias", @@ -852,16 +852,16 @@ export class CurrentUserUtils { doc.myFileOrphans = Docs.Create.TreeDocument([], { title: "Unfiled", _stayInCollection: true, system: true, isFolder: true }); // doc.myFileRoot = Docs.Create.TreeDocument([], { title: "file root", _stayInCollection: true, system: true, isFolder: true }); const newFolder = ScriptField.MakeFunction(`doc.makeFolder()`, { doc: doc.myFilesystem })!; - const newFolderButton:Doc = Docs.Create.FontIconDocument({ onClick: newFolder, _forceActive: true, toolTip: "New folder", _stayInCollection: true, _hideContextMenu: true, title: "New folder", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New folder", icon: "folder-plus", system: true }); + const newFolderButton: Doc = Docs.Create.FontIconDocument({ onClick: newFolder, _forceActive: true, toolTip: "New folder", _stayInCollection: true, _hideContextMenu: true, title: "New folder", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New folder", icon: "folder-plus", system: true }); doc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([doc.myFileOrphans as Doc], { - title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100, + title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true, explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard." })); - (doc.myTrails as any as Doc).contextMenuScripts = new List([newFolder!]); + (doc.myTrails as any as Doc).contextMenuScripts = new List([newFolder]); (doc.myTrails as any as Doc).contextMenuLabels = new List(["Create new folder"]); } return doc.myFilesystem as any as Doc; @@ -870,7 +870,7 @@ export class CurrentUserUtils { static setupRecentlyClosedDocs(doc: Doc) { if (doc.myRecentlyClosedDocs === undefined) { const clearAll = ScriptField.MakeScript(`getProto(self).data = new List([])`); - const clearDocsButton:Doc = Docs.Create.FontIconDocument({ onClick: clearAll, _forceActive: true, toolTip: "Empty recently closed", _stayInCollection: true, _hideContextMenu: true, title: "Empty", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "Empty", icon: "trash", system: true }); + const clearDocsButton: Doc = Docs.Create.FontIconDocument({ onClick: clearAll, _forceActive: true, toolTip: "Empty recently closed", _stayInCollection: true, _hideContextMenu: true, title: "Empty", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "Empty", icon: "trash", system: true }); doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Recently Closed", _showTitle: "title", buttonMenu: true, buttonMenuDoc: clearDocsButton, childHideLinkButton: true, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", @@ -1215,7 +1215,7 @@ export class CurrentUserUtils { // Import sidebar is where shared documents are contained static setupUploadSidebar(doc: Doc) { if (doc.myUploadDocs === undefined) { - const newUploadButton:Doc = Docs.Create.FontIconDocument({ onClick: ScriptField.MakeScript("importDocument()"), _forceActive: true, toolTip: "Upload from computer", _width: 30, _height: 30, _stayInCollection: true, _hideContextMenu: true, title: "Upload", btnType: ButtonType.ClickButton, buttonText: "Upload", icon: "upload", system: true }); + const newUploadButton: Doc = Docs.Create.FontIconDocument({ onClick: ScriptField.MakeScript("importDocument()"), _forceActive: true, toolTip: "Upload from computer", _width: 30, _height: 30, _stayInCollection: true, _hideContextMenu: true, title: "Upload", btnType: ButtonType.ClickButton, buttonText: "Upload", icon: "upload", system: true }); doc.myUploadDocs = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "My Uploads", _forceActive: true, buttonMenu: true, buttonMenuDoc: newUploadButton, ignoreClick: true, _showTitle: "title", _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0, childDropAction: "copy", _autoHeight: true, _yMargin: 50, _gridGap: 15, boxShadow: "0 0", _lockedPosition: true, system: true, _chromeHidden: true, diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index b72a3189d..9e190ad02 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,19 +1,21 @@ import { action, observable, runInAction } from 'mobx'; import { Doc, DocListCast, DocListCastAsync, Opt } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; -import { Cast, NumCast, StrCast } from '../../fields/Types'; +import { Cast } from '../../fields/Types'; import { returnFalse } from '../../Utils'; import { DocumentType } from '../documents/DocumentTypes'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; import { CollectionView } from '../views/collections/CollectionView'; import { LightboxView } from '../views/LightboxView'; import { DocumentView, ViewAdjustment } from '../views/nodes/DocumentView'; +import { LinkAnchorBox } from '../views/nodes/LinkAnchorBox'; import { Scripting } from './Scripting'; export class DocumentManager { //global holds all of the nodes (regardless of which collection they're in) @observable public DocumentViews: DocumentView[] = []; + @observable public LinkAnchorBoxViews: DocumentView[] = []; @observable public RecordingEvent = 0; @observable public LinkedDocumentViews: { a: DocumentView, b: DocumentView, l: Doc }[] = []; @@ -26,23 +28,24 @@ export class DocumentManager { @action public AddView = (view: DocumentView) => { //console.log("MOUNT " + view.props.Document.title + "/" + view.props.LayoutTemplateString); - if (view.props.LayoutTemplateString?.includes("LinkAnchorBox")) { + if (view.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) { const viewAnchorIndex = view.props.LayoutTemplateString.includes("anchor2") ? "anchor2" : "anchor1"; - view.props.LayoutTemplateString && DocListCast(view.rootDoc.links).forEach(link => { - DocumentManager.Instance.DocumentViews?.filter(dv => Doc.AreProtosEqual(dv.rootDoc, link) && !dv.props.LayoutTemplateString?.includes(viewAnchorIndex)). - forEach(otherView => { - this.LinkedDocumentViews.push( - { - a: viewAnchorIndex === "anchor2" ? otherView : view, - b: viewAnchorIndex === "anchor2" ? view : otherView, - l: link - }); - }); + DocListCast(view.rootDoc.links).forEach(link => { + this.LinkAnchorBoxViews?.filter(dv => Doc.AreProtosEqual(dv.rootDoc, link) && !dv.props.LayoutTemplateString?.includes(viewAnchorIndex)). + forEach(otherView => this.LinkedDocumentViews.push( + { + a: viewAnchorIndex === "anchor2" ? otherView : view, + b: viewAnchorIndex === "anchor2" ? view : otherView, + l: link + }) + ); }); + this.LinkAnchorBoxViews.push(view); // this.LinkedDocumentViews.forEach(view => console.log(" LV = " + view.a.props.Document.title + "/" + view.a.props.LayoutTemplateString + " --> " + // view.b.props.Document.title + "/" + view.b.props.LayoutTemplateString)); + } else { + this.DocumentViews.push(view); } - this.DocumentViews.push(view); } public RemoveView = action((view: DocumentView) => { this.LinkedDocumentViews.slice().forEach(action(pair => { @@ -52,8 +55,13 @@ export class DocumentManager { } })); - const index = this.DocumentViews.indexOf(view); - index !== -1 && this.DocumentViews.splice(index, 1); + if (view.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) { + const index = this.LinkAnchorBoxViews.indexOf(view); + this.LinkAnchorBoxViews.splice(index, 1); + } else { + const index = this.DocumentViews.indexOf(view); + index !== -1 && this.DocumentViews.splice(index, 1); + } }); //gets all views diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 9fe2122e6..dd737dc9d 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -156,7 +156,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { ["toggleDetail", "Toggle Detail"], ["linkInPlace", "Follow Link"], ["linkOnRight", "Open Link on Right"] - ] + ]; const currentSelection = this.selectedDoc.onClickBehavior; // Get items to place into the list diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 6fe46bbb2..3b3e069d8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -5,7 +5,6 @@ import { Id } from "../../../../fields/FieldSymbols"; import { List } from "../../../../fields/List"; import { NumCast, StrCast } from "../../../../fields/Types"; import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; -import { DocumentType } from "../../../documents/DocumentTypes"; import { LinkManager } from "../../../util/LinkManager"; import { SnappingManager } from "../../../util/SnappingManager"; import { DocumentView } from "../../nodes/DocumentView"; @@ -69,8 +68,10 @@ export class CollectionFreeFormLinkView extends React.Component= 0 && mpx <= 1) linkDoc.anchor1_x = mpx * 100; + if (mpy >= 0 && mpy <= 1) linkDoc.anchor1_y = mpy * 100; } if (!targetBhyperlink) { if (linkDoc.linkAutoMove) { @@ -80,8 +81,10 @@ export class CollectionFreeFormLinkView extends React.Component= 0 && mpx <= 1) linkDoc.anchor2_x = mpx * 100; + if (mpy >= 0 && mpy <= 1) linkDoc.anchor2_y = mpy * 100; } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index e812064b7..dacbb3508 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -1,30 +1,17 @@ import { computed } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../../../fields/Doc"; import { Id } from "../../../../fields/FieldSymbols"; -import { Utils } from "../../../../Utils"; import { DocumentManager } from "../../../util/DocumentManager"; -import { DocumentView } from "../../nodes/DocumentView"; import "./CollectionFreeFormLinksView.scss"; import { CollectionFreeFormLinkView } from "./CollectionFreeFormLinkView"; import React = require("react"); -import { DocumentType } from "../../../documents/DocumentTypes"; -import { LinkManager } from "../../../util/LinkManager"; @observer export class CollectionFreeFormLinksView extends React.Component { @computed get uniqueConnections() { - const connections = DocumentManager.Instance.LinkedDocumentViews - .filter(c => c.a.props.Document.type === DocumentType.LINK || c.b.props.Document.type === DocumentType.LINK) - .reduce((drawnPairs, connection) => { - const matchingPairs = drawnPairs.filter(pair => connection.a === pair.a && connection.b === pair.b); - matchingPairs.forEach(drawnPair => drawnPair.l.add(connection.l)); - if (!matchingPairs.length) drawnPairs.push({ a: connection.a, b: connection.b, l: new Set([connection.l]) }); - return drawnPairs; - }, [] as { a: DocumentView, b: DocumentView, l: Set }[]); - const set = new Map(); - connections.map(c => !set.has(Array.from(c.l)[0]) && set.set(Array.from(c.l)[0], { a: c.a, b: c.b, l: Array.from(c.l) })); - return Array.from(set.values()).map(c => ); + return Array.from(new Set(DocumentManager.Instance.LinkedDocumentViews)).map(c => + + ); } render() { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 2deaea823..018c2a895 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1457,7 +1457,7 @@ export class CollectionFreeFormView extends CollectionSubView
- {this.layoutDoc["_backgroundGridShow"] ? this.backgroundGrid : (null)} + {this.layoutDoc._backgroundGridShow ? this.backgroundGrid : (null)} ; const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema); diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index eaedd48c7..7e46d8433 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, trace } from "mobx"; +import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import * as WebRequest from 'web-request'; import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; @@ -24,6 +24,7 @@ import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from "../ContextMenuItem"; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from "../DocComponent"; import { DocumentDecorations } from "../DocumentDecorations"; +import { Colors } from "../global/globalEnums"; import { LightboxView } from "../LightboxView"; import { MarqueeAnnotator } from "../MarqueeAnnotator"; import { AnchorMenu } from "../pdf/AnchorMenu"; @@ -33,7 +34,6 @@ import { FieldView, FieldViewProps } from './FieldView'; import { LinkDocPreview } from "./LinkDocPreview"; import "./WebBox.scss"; import React = require("react"); -import { Colors } from "../global/globalEnums"; const _global = (window /* browser */ || global /* node */) as any; const htmlToText = require("html-to-text"); diff --git a/src/client/views/nodes/button/textButton/TextButton.tsx b/src/client/views/nodes/button/textButton/TextButton.tsx index 414b50dcb..e18590a95 100644 --- a/src/client/views/nodes/button/textButton/TextButton.tsx +++ b/src/client/views/nodes/button/textButton/TextButton.tsx @@ -12,6 +12,6 @@ export class TextButton extends Component { return (
{this.props.label} -
) +
); } } \ No newline at end of file diff --git a/src/client/views/nodes/button/textButton/index.ts b/src/client/views/nodes/button/textButton/index.ts index 01fcde54f..01d62eb7e 100644 --- a/src/client/views/nodes/button/textButton/index.ts +++ b/src/client/views/nodes/button/textButton/index.ts @@ -1 +1 @@ -export * from './TextButton' \ No newline at end of file +export * from './TextButton'; \ No newline at end of file diff --git a/src/client/views/nodes/button/toggleButton/index.ts b/src/client/views/nodes/button/toggleButton/index.ts index 48b28fb4c..cdb9c527c 100644 --- a/src/client/views/nodes/button/toggleButton/index.ts +++ b/src/client/views/nodes/button/toggleButton/index.ts @@ -1 +1 @@ -export * from './ToggleButton' \ No newline at end of file +export * from './ToggleButton'; \ No newline at end of file diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index bc578f95d..cad9af2b0 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1448,18 +1448,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const margins = 2 * NumCast(this.layoutDoc._yMargin, this.props.yPadding || 0); const children = this.ProseRef?.children.length ? Array.from(this.ProseRef.children[0].children) : undefined; if (children) { - var proseHeight = !this.ProseRef ? 0 : children.reduce((p, child) => p + Number(getComputedStyle(child).height.replace("px", "")), margins); - var scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.docMaxAutoHeight, proseHeight), proseHeight); + const proseHeight = !this.ProseRef ? 0 : children.reduce((p, child) => p + Number(getComputedStyle(child).height.replace("px", "")), margins); + const scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.docMaxAutoHeight, proseHeight), proseHeight); if (scrollHeight && this.props.renderDepth && !this.props.dontRegisterView) { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation const setScrollHeight = () => this.rootDoc[this.fieldKey + "-scrollHeight"] = scrollHeight; if (this.rootDoc === this.layoutDoc.doc || this.layoutDoc.resolvedDataDoc) { setScrollHeight(); - // setTimeout(() => { - // proseHeight = !this.ProseRef ? 0 : children.reduce((p, child) => p + Number(getComputedStyle(child).height.replace("px", "")), margins); - // scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.docMaxAutoHeight, proseHeight), proseHeight); - // scrollHeight && setScrollHeight(); - // }, 10); - } else setTimeout(setScrollHeight, 10); // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template. So set a timeout and hope its arrived... + } else { + setTimeout(setScrollHeight, 10); // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template. So set a timeout and hope its arrived... + } } } } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 02010e123..d953c6b6c 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -2,14 +2,13 @@ import { action, computed, IReactionDisposer, observable, ObservableMap, reactio import { observer } from "mobx-react"; import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; -import { DataSym, Doc, DocListCast, Field, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; +import { Doc, DocListCast, Field, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; import { Id } from "../../../fields/FieldSymbols"; import { InkTool } from "../../../fields/InkField"; -import { createSchema } from "../../../fields/Schema"; import { Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types"; import { PdfField } from "../../../fields/URLField"; import { TraceMobx } from "../../../fields/util"; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, OmitKeys, smoothScroll, Utils, returnFalse, returnEmptyString, returnEmptyFilter } from "../../../Utils"; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, OmitKeys, smoothScroll, Utils } from "../../../Utils"; import { DocUtils } from "../../documents/Documents"; import { Networking } from "../../Network"; import { CurrentUserUtils } from "../../util/CurrentUserUtils"; -- cgit v1.2.3-70-g09d2 From 8e5357cd2ebfaad88c82ffde2415426fa9d130c0 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 13 Sep 2021 13:34:05 -0400 Subject: auto-select regions on audio timelines after they are created. --- src/client/views/collections/CollectionStackedTimeline.tsx | 4 +++- src/client/views/nodes/PDFBox.tsx | 1 - src/client/views/nodes/WebBox.tsx | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/client/views/nodes/PDFBox.tsx') diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index d98d966d8..0fc66445a 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -43,6 +43,7 @@ import { import { LabelBox } from "../nodes/LabelBox"; import "./CollectionStackedTimeline.scss"; import { Colors } from "../global/globalEnums"; +import { DocumentManager } from "../../util/DocumentManager"; type PanZoomDocument = makeInterface<[]>; const PanZoomDocument = makeInterface(); @@ -246,7 +247,7 @@ export class CollectionStackedTimeline extends CollectionSubView< Math.abs(movement[0]) > 15 && !this.props.trimming ) { - CollectionStackedTimeline.createAnchor( + const anchor = CollectionStackedTimeline.createAnchor( this.rootDoc, this.dataDoc, this.props.fieldKey, @@ -255,6 +256,7 @@ export class CollectionStackedTimeline extends CollectionSubView< this._markerStart, this._markerEnd ); + setTimeout(() => DocumentManager.Instance.getDocumentView(anchor)?.select(false)); } (!isClick || !wasSelecting) && (CollectionStackedTimeline.SelectingRegion = undefined); diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 9706d73c7..88fb2ed13 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -228,7 +228,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent this.pdfUrl && Utils.CopyText(this.pdfUrl.url.pathname), icon: "expand-arrows-alt" }); funcs.push({ description: "Toggle Fit Width " + (this.Document._fitWidth ? "Off" : "On"), event: () => this.Document._fitWidth = !this.Document._fitWidth, icon: "expand-arrows-alt" }); - funcs.push({ description: "Toggle Annotation View ", event: () => this.Document._showSidebar = !this.Document._showSidebar, icon: "expand-arrows-alt" }); funcs.push({ description: "Toggle Sidebar ", event: () => this.toggleSidebar(), icon: "expand-arrows-alt" }); ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" }); } diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index adf84d810..19135b6dd 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -404,7 +404,6 @@ export class WebBox extends ViewBoxAnnotatableComponent this.Document._showSidebar = !this.Document._showSidebar, icon: "expand-arrows-alt" }); cm.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" }); } -- cgit v1.2.3-70-g09d2 From af246480e97554233293ab1dfb08b5af5e1f9d7c Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 13 Sep 2021 19:38:53 -0400 Subject: fixed copyPath menu item for images/pdfs. fixed contextmenu right-clicking to not require preselection of doc. --- src/Utils.ts | 10 +--------- src/client/views/ContextMenu.tsx | 15 +++++++++++---- src/client/views/nodes/DocumentView.tsx | 15 +++++++++++++-- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/PDFBox.tsx | 5 ++--- 5 files changed, 28 insertions(+), 19 deletions(-) (limited to 'src/client/views/nodes/PDFBox.tsx') diff --git a/src/Utils.ts b/src/Utils.ts index 3fffadb6d..ddc16dceb 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -82,15 +82,7 @@ export namespace Utils { } export function CopyText(text: string) { - const textArea = document.createElement("textarea"); - textArea.value = text; - document.body.appendChild(textArea); - textArea.focus(); - textArea.select(); - - try { document.execCommand('copy'); } catch (err) { } - - document.body.removeChild(textArea); + navigator.clipboard.writeText(text); } export function decimalToHexString(number: number) { diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index c4fabbf99..78564a11b 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -47,11 +47,17 @@ export class ContextMenu extends React.Component { this._mouseDown = false; const curX = e.clientX; const curY = e.clientY; - if (this._mouseX !== curX || this._mouseY !== curY) { + if (Math.abs(this._mouseX - curX) > 1 || Math.abs(this._mouseY - curY) > 1) { this._shouldDisplay = false; } - this._shouldDisplay && (this._display = true); + if (this._shouldDisplay) { + if (this._onDisplay) { + this._onDisplay(); + } else { + this._display = true; + } + } } componentWillUnmount() { document.removeEventListener("pointerdown", this.onPointerDown); @@ -138,9 +144,9 @@ export class ContextMenu extends React.Component { return y; } - + _onDisplay?: () => void = undefined; @action - displayMenu = (x: number, y: number, initSearch = "", showSearch = false) => { + displayMenu = (x: number, y: number, initSearch = "", showSearch = false, onDisplay?: () => void) => { //maxX and maxY will change if the UI/font size changes, but will work for any amount //of items added to the menu @@ -149,6 +155,7 @@ export class ContextMenu extends React.Component { this._pageY = y; this._searchString = initSearch; this._shouldDisplay = true; + this._onDisplay = onDisplay; } @action diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 1fcbffadd..193befa5d 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -13,7 +13,7 @@ import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Ty import { AudioField } from "../../../fields/URLField"; import { GetEffectiveAcl, SharingPermissions, TraceMobx } from '../../../fields/util'; import { MobileInterface } from '../../../mobile/MobileInterface'; -import { emptyFunction, hasDescendantTarget, OmitKeys, returnTrue, returnVal, Utils, lightOrDark } from "../../../Utils"; +import { emptyFunction, hasDescendantTarget, OmitKeys, returnTrue, returnVal, Utils, lightOrDark, simulateMouseClick } from "../../../Utils"; import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from '../../documents/DocumentTypes'; @@ -671,6 +671,18 @@ export class DocumentViewInternal extends DocComponent setTimeout(() => { + DocumentViewInternal.SelectAfterContextMenu && !this.props.isSelected(true) && SelectionManager.SelectView(this.props.DocumentView(), false); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. + setTimeout(() => { + const ele = document.elementFromPoint(e.clientX, e.clientY); + simulateMouseClick(ele, e.clientX, e.clientY, e.screenX, e.screenY); + }); + }); + cm.displayMenu((e?.pageX || pageX || 0) - 15, (e?.pageY || pageY || 0) - 15, undefined, undefined, onDisplay); + return; + } + const customScripts = Cast(this.props.Document.contextMenuScripts, listSpec(ScriptField), []); StrListCast(this.Document.contextMenuLabels).forEach((label, i) => cm.addItem({ description: label, event: () => customScripts[i]?.script.run({ documentView: this, this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: "sticky-note" })); @@ -777,7 +789,6 @@ export class DocumentViewInternal extends DocComponent SelectionManager.SelectView(this.props.DocumentView(), false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. } rootSelected = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 38deb4a73..b41bfd3ea 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -144,9 +144,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent Utils.CopyText(this.choosePath(field.url)), icon: "expand-arrows-alt" }); if (!Doc.UserDoc().noviceMode) { funcs.push({ description: "Export to Google Photos", event: () => GooglePhotos.Transactions.UploadImages([this.props.Document]), icon: "caret-square-right" }); - funcs.push({ description: "Copy path", event: () => Utils.CopyText(field.url.href), icon: "expand-arrows-alt" }); const existingAnalyze = ContextMenu.Instance?.findByDescription("Analyzers..."); const modes: ContextMenuProps[] = existingAnalyze && "subitems" in existingAnalyze ? existingAnalyze.subitems : []; diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 88fb2ed13..ce851b830 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -226,9 +226,8 @@ export class PDFBox extends ViewBoxAnnotatableComponent { const funcs: ContextMenuProps[] = []; - funcs.push({ description: "Copy path", event: () => this.pdfUrl && Utils.CopyText(this.pdfUrl.url.pathname), icon: "expand-arrows-alt" }); - funcs.push({ description: "Toggle Fit Width " + (this.Document._fitWidth ? "Off" : "On"), event: () => this.Document._fitWidth = !this.Document._fitWidth, icon: "expand-arrows-alt" }); - funcs.push({ description: "Toggle Sidebar ", event: () => this.toggleSidebar(), icon: "expand-arrows-alt" }); + funcs.push({ description: "Copy path", event: () => this.pdfUrl && Utils.CopyText(Utils.prepend("") + this.pdfUrl.url.pathname), icon: "expand-arrows-alt" }); + //funcs.push({ description: "Toggle Sidebar ", event: () => this.toggleSidebar(), icon: "expand-arrows-alt" }); ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" }); } -- cgit v1.2.3-70-g09d2 From 64119b5d8766725025b8b2bfda72f2401bba0f00 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 16 Sep 2021 21:04:57 -0400 Subject: added search() component method. changed search menu to call search on documents that match search string. added seach bar for web pages. --- src/client/views/GlobalKeyHandler.ts | 16 ++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 1 + src/client/views/nodes/PDFBox.tsx | 18 ++++- src/client/views/nodes/WebBox.scss | 86 ++++++++++++++++++++++ src/client/views/nodes/WebBox.tsx | 65 +++++++++++----- src/client/views/pdf/PDFViewer.tsx | 13 +--- src/client/views/search/SearchBox.tsx | 15 ++-- 8 files changed, 172 insertions(+), 46 deletions(-) (limited to 'src/client/views/nodes/PDFBox.tsx') diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index f66c9c788..de6f4ae8b 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -10,10 +10,11 @@ import { Cast, PromiseValue } from "../../fields/Types"; import { GoogleAuthenticationManager } from "../apis/GoogleAuthenticationManager"; import { DocServer } from "../DocServer"; import { DocumentType } from "../documents/DocumentTypes"; -import { DictationManager } from "../util/DictationManager"; +import { CurrentUserUtils } from "../util/CurrentUserUtils"; import { DragManager } from "../util/DragManager"; import { GroupManager } from "../util/GroupManager"; import { SelectionManager } from "../util/SelectionManager"; +import { SettingsManager } from "../util/SettingsManager"; import { SharingManager } from "../util/SharingManager"; import { SnappingManager } from "../util/SnappingManager"; import { undoBatch, UndoManager } from "../util/UndoManager"; @@ -27,8 +28,6 @@ import { LightboxView } from "./LightboxView"; import { MainView } from "./MainView"; import { DocumentLinksButton } from "./nodes/DocumentLinksButton"; import { AnchorMenu } from "./pdf/AnchorMenu"; -import { CurrentUserUtils } from "../util/CurrentUserUtils"; -import { SettingsManager } from "../util/SettingsManager"; const modifiers = ["control", "meta", "shift", "alt"]; type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise; @@ -222,10 +221,13 @@ export class KeyManager { PromiseValue(Cast(Doc.UserDoc()["tabs-button-tools"], Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); break; case "f": - const searchBtn = Doc.UserDoc().searchBtn as Doc; - - if (searchBtn) { - MainView.Instance.selectMenu(searchBtn); + if (SelectionManager.Views().length === 1 && SelectionManager.Views()[0].ComponentView?.search) { + SelectionManager.Views()[0].ComponentView?.search?.("", false, false); + } else { + const searchBtn = Doc.UserDoc().searchBtn as Doc; + if (searchBtn) { + MainView.Instance.selectMenu(searchBtn); + } } break; case "o": diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index be0b078ec..94cf1c5a6 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -902,7 +902,9 @@ export class CollectionFreeFormView extends CollectionSubView string; getScrollHeight?: () => number; + search?: (str:string, bwd?:boolean, clear?:boolean) => boolean; } export interface DocumentViewSharedProps { renderDepth: number; diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index ce851b830..274d166f1 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -96,7 +96,17 @@ export class PDFBox extends ViewBoxAnnotatableComponent this._pdfViewer?.search(string, fwd); + public search = action((searchString: string, bwd?: boolean, clear: boolean = false) => { + if (!this._searching && !clear) { + this._searching = true; + setTimeout(() => { + this._searchRef.current?.focus(); + this._searchRef.current?.select(); + this._searchRef.current?.setRangeText(searchString); + }); + } + return this._pdfViewer?.search(searchString, bwd, clear) || false; + }); public prevAnnotation = () => this._pdfViewer?.prevAnnotation(); public nextAnnotation = () => this._pdfViewer?.nextAnnotation(); public backPage = () => { this.Document._curPage = (this.Document._curPage || 1) - 1; return true; }; @@ -184,8 +194,8 @@ export class PDFBox extends ViewBoxAnnotatableComponent e.stopPropagation()} style={{ left: `${this._searching ? 0 : 100}%` }}> + + + ; + } + searchStringChanged = (e: React.ChangeEvent) => this._searchString = e.currentTarget.value; showInfo = action((anno: Opt) => this._overlayAnnoInfo = anno); setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean) => void) => this._setPreviewCursor = func; panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1) - this.sidebarWidth(); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0); @@ -623,25 +666,7 @@ export class WebBox extends ViewBoxAnnotatableComponent - {/*
- { - if (e.key === "Enter") { - (this._iframe?.contentWindow as any)?.find(e.target.value); - } - }} onChange={e => { - this._iframe?.contentWindow?.getSelection()?.empty(); - (this._iframe?.contentWindow as any)?.find(e.target.value) - }}> -
*/} + {!this.props.isContentActive() ? (null) : this.searchUI} ); } } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index d953c6b6c..7aa18e46f 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -125,12 +125,6 @@ export class PDFViewer extends React.Component { } }); - this._disposers.searchMatch = reaction(() => Doc.IsSearchMatch(this.props.rootDoc), - m => { - if (m) (this._lastSearch = true) && this.search(Doc.SearchQuery(), m.searchMatch > 0); - else !(this._lastSearch = false) && setTimeout(() => !this._lastSearch && this.search("", false, true), 200); - }, { fireImmediately: true }); - this._disposers.selected = reaction(() => this.props.isSelected(), selected => { // if (!selected) { @@ -337,10 +331,10 @@ export class PDFViewer extends React.Component { } @action - search = (searchString: string, fwd: boolean, clear: boolean = false) => { + search = (searchString: string, bwd?: boolean, clear: boolean = false) => { const findOpts = { caseSensitive: false, - findPrevious: !fwd, + findPrevious: bwd, highlightAll: true, phraseSearch: true, query: searchString @@ -348,7 +342,7 @@ export class PDFViewer extends React.Component { if (clear) { this._pdfViewer?.findController.executeCommand('reset', { query: "" }); } else if (!searchString) { - fwd ? this.nextAnnotation() : this.prevAnnotation(); + bwd ? this.prevAnnotation() : this.nextAnnotation(); } else if (this._pdfViewer?.pageViewsReady) { this._pdfViewer.findController.executeCommand('findagain', findOpts); } @@ -357,6 +351,7 @@ export class PDFViewer extends React.Component { this._mainCont.current.addEventListener("pagesloaded", executeFind); this._mainCont.current.addEventListener("pagerendered", executeFind); } + return true; } @action diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 9c353e9d0..3612bd7c4 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -104,9 +104,9 @@ export class SearchBox extends ViewBoxBaseComponent { - this.selectElement(doc); + onResultClick = action(async (doc: Doc) => { this._selectedResult = doc; + this.selectElement(doc, () => DocumentManager.Instance.getFirstDocumentView(doc)?.ComponentView?.search?.(this._searchString, undefined, false)); }); makeLink = action((linkTo: Doc) => { @@ -269,8 +269,8 @@ export class SearchBox extends ViewBoxBaseComponent { - await DocumentManager.Instance.jumpToDocument(doc, true); + selectElement = async (doc: Doc, finishFunc: () => void) => { + await DocumentManager.Instance.jumpToDocument(doc, true, undefined, undefined, undefined, undefined, undefined, finishFunc); } /** @@ -307,7 +307,12 @@ export class SearchBox extends ViewBoxBaseComponent
{title}
}> -
this.makeLink(result[0]) : () => this.onResultClick(result[0])} className={className}> +
this.makeLink(result[0]) : + e => { + this.onResultClick(result[0]); + e.stopPropagation(); + }} className={className}>
{title}
-- cgit v1.2.3-70-g09d2 From 03c0caa35fa4ac63ac3efeb73de145ebd848cc54 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 16 Sep 2021 21:07:46 -0400 Subject: from last --- src/client/views/nodes/PDFBox.tsx | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/client/views/nodes/PDFBox.tsx') diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 274d166f1..f0a502e31 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -117,11 +117,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent { let processed = false; switch (e.key) { - case "f": if (e.ctrlKey) { - setTimeout(() => this._searchRef.current?.focus(), 100); - this._searching = processed = true; - } - break; case "PageDown": processed = this.forwardPage(); break; case "PageUp": processed = this.backPage(); break; } -- cgit v1.2.3-70-g09d2 From f097eefd91614d4efa2a89b3d8c7d1071d6c0b6f Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 17 Sep 2021 14:07:09 -0400 Subject: added 'unset' docFilters. changed link doc views to use comparison box with title/caption. fixed linkEditor to write to data doc. generalized comparisonBox rendering to use parameterized fields. fixed pdf/web to honor pointerEvents none prop and fixed textAnnotations to get rendered once as an Annotation. moved filterIcon stuff into DocumentView --- src/Utils.ts | 4 +++- src/client/DocServer.ts | 2 ++ src/client/documents/Documents.ts | 17 +++++++++++------ src/client/views/collections/CollectionView.tsx | 12 ------------ .../collectionFreeForm/CollectionFreeFormLinkView.tsx | 6 +++--- src/client/views/linking/LinkEditor.tsx | 11 ++++++----- src/client/views/nodes/ComparisonBox.tsx | 8 +++++--- src/client/views/nodes/DocumentView.tsx | 19 +++++++++++++++++-- src/client/views/nodes/LinkBox.tsx | 19 ++++++------------- src/client/views/nodes/LinkDescriptionPopup.tsx | 7 ++++--- src/client/views/nodes/PDFBox.tsx | 9 ++++----- src/client/views/nodes/WebBox.tsx | 14 ++++++++------ src/client/views/pdf/Annotation.scss | 3 +++ src/client/views/pdf/PDFViewer.tsx | 13 +++++++------ src/fields/Doc.ts | 2 +- 15 files changed, 80 insertions(+), 66 deletions(-) (limited to 'src/client/views/nodes/PDFBox.tsx') diff --git a/src/Utils.ts b/src/Utils.ts index 6eacd8296..e11f1154e 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -125,7 +125,9 @@ export namespace Utils { // bcz: isTransparent(__value__) is a hack. it would be nice to have acual functions be parsed, but now Doc.matchFieldValue is hardwired to recognize just this one return `backgroundColor:${isTransparentFunctionHack},${noRecursionHack}:x`;// bcz: hack. noRecursion should probably be either another ':' delimited field, or it should be a modifier to the comparision (eg., check, x, etc) field } - + export function PropUnsetFilter(prop: string) { + return `${prop}:any,${noRecursionHack}:unset`; + } export function toRGBAstr(col: { r: number, g: number, b: number, a?: number }) { return "rgba(" + col.r + "," + col.g + "," + col.b + (col.a !== undefined ? "," + col.a : "") + ")"; diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index e498a7cca..3b376a0e7 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -241,6 +241,7 @@ export namespace DocServer { // the field has been returned from the server const getSerializedField = Utils.EmitCallback(_socket, MessageStore.GetRefField, id); + console.log(id) // when the serialized RefField has been received, go head and begin deserializing it into an object. // Here, once deserialized, we also invoke .proto to 'load' the document's prototype, which ensures that all // future .proto calls on the Doc won't have to go farther than the cache to get their actual value. @@ -264,6 +265,7 @@ export namespace DocServer { } else { delete _cache[id]; } + console.log(id, field); return field; // either way, overwrite or delete any promises cached at this id (that we inserted as flags // to indicate that the field was in the process of being fetched). Now everything diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index f50f306a3..e8185400e 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -962,13 +962,17 @@ export namespace DocUtils { // metadata facets that exist const exists = Object.keys(facet).filter(value => facet[value] === "exists"); + // metadata facets that exist + const unsets = Object.keys(facet).filter(value => facet[value] === "unset"); + // facets that have an x next to them const xs = Object.keys(facet).filter(value => facet[value] === "x"); - if (!exists.length && !xs.length && !checks.length && !matches.length) return true; + if (!unsets.length && !exists.length && !xs.length && !checks.length && !matches.length) return true; const failsNotEqualFacets = !xs.length ? false : xs.some(value => Doc.matchFieldValue(d, facetKey, value)); const satisfiesCheckFacets = !checks.length ? true : checks.some(value => Doc.matchFieldValue(d, facetKey, value)); const satisfiesExistsFacets = !exists.length ? true : exists.some(value => d[facetKey] !== undefined); + const satisfiesUnsetsFacets = !unsets.length ? true : unsets.some(value => d[facetKey] === undefined); const satisfiesMatchFacets = !matches.length ? true : matches.some(value => { if (facetKey.startsWith("*")) { // fields starting with a '*' are used to match families of related fields. ie, *lastModified will match text-lastModified, data-lastModified, etc const allKeys = Array.from(Object.keys(d)); @@ -980,11 +984,11 @@ export namespace DocUtils { }); // if we're ORing them together, the default return is false, and we return true for a doc if it satisfies any one set of criteria if ((parentCollection?.currentFilter as Doc)?.filterBoolean === "OR") { - if (satisfiesExistsFacets && satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true; + if (satisfiesUnsetsFacets && satisfiesExistsFacets && satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true; } // if we're ANDing them together, the default return is true, and we return false for a doc if it doesn't satisfy any set of criteria else { - if (!satisfiesExistsFacets || !satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false; + if (!satisfiesUnsetsFacets || !satisfiesExistsFacets || !satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false; } } @@ -1088,10 +1092,11 @@ export namespace DocUtils { "anchor2-useLinkSmallAnchor": target.doc.useLinkSmallAnchor ? true : undefined, "acl-Public": SharingPermissions.Augment, "_acl-Public": SharingPermissions.Augment, - layout_linkView: Cast(Cast(Doc.UserDoc()["template-button-link"], Doc, null).dragFactory, Doc, null), - linkDisplay: true, hidden: true, + linkDisplay: true, + hidden: true, linkRelationship, - _layoutKey: "layout_linkView", + _showCaption: "description", + _showTitle: "linkRelationship", description }, id), showPopup); } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 5c9c8063b..38e027fb3 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -246,12 +246,6 @@ export class CollectionView extends ViewBoxAnnotatableComponent this.props.childLayoutTemplate?.() || Cast(this.rootDoc.childLayoutTemplate, Doc, null); @computed get childLayoutString() { return StrCast(this.rootDoc.childLayoutString); } - /** - * Shows the filter icon if it's a user-created collection which isn't a dashboard and has some docFilters applied on it or on the current dashboard. - */ - @computed get showFilterIcon() { - return this.props.Document.viewType !== CollectionViewType.Docking && !Doc.IsSystem(this.props.Document) && this._subView?.IsFiltered(); - } @observable _subView: any = undefined; @@ -280,12 +274,6 @@ export class CollectionView extends ViewBoxAnnotatableComponent {this.showIsTagged()} {this.collectionViewType !== undefined ? this.SubView(this.collectionViewType, props) : (null)} - {this.showFilterIcon ? - { this.props.select(false); CurrentUserUtils.propertiesWidth = 250; e.stopPropagation(); })} - /> - : (null)}
); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 3b3e069d8..2cb487588 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -1,6 +1,6 @@ import { action, computed, IReactionDisposer, observable, reaction } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../../../fields/Doc"; +import { Doc, Field } from "../../../../fields/Doc"; import { Id } from "../../../../fields/FieldSymbols"; import { List } from "../../../../fields/List"; import { NumCast, StrCast } from "../../../../fields/Types"; @@ -180,7 +180,7 @@ export class CollectionFreeFormLinkView extends React.Component; const linkColorList = Doc.UserDoc().linkColorList as List; //access stroke color using index of the relationship in the color list (default black) @@ -189,7 +189,7 @@ export class CollectionFreeFormLinkView extends React.Component {textX === undefined ? (null) : - {StrCast(this.props.LinkDocs[0].description)} + {Field.toString(this.props.LinkDocs[0].description as any as Field)} } ); } diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index 240a71c3e..219f7d3a2 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -2,13 +2,14 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from "@material-ui/core"; import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; -import { Doc, StrListCast } from "../../../fields/Doc"; -import { DateCast, StrCast } from "../../../fields/Types"; +import { Doc, StrListCast, Field } from "../../../fields/Doc"; +import { DateCast, StrCast, Cast } from "../../../fields/Types"; import { LinkManager } from "../../util/LinkManager"; import { undoBatch } from "../../util/UndoManager"; import './LinkEditor.scss'; import { LinkRelationshipSearch } from "./LinkRelationshipSearch"; import React = require("react"); +import { ToString } from "../../../fields/FieldSymbols"; interface LinkEditorProps { @@ -20,7 +21,7 @@ interface LinkEditorProps { @observer export class LinkEditor extends React.Component { - @observable description = StrCast(LinkManager.currentLink?.description); + @observable description = Field.toString(LinkManager.currentLink?.description as any as Field); @observable relationship = StrCast(LinkManager.currentLink?.linkRelationship); @observable openDropdown: boolean = false; @observable showInfo: boolean = false; @@ -41,7 +42,7 @@ export class LinkEditor extends React.Component { @undoBatch setRelationshipValue = action((value: string) => { if (LinkManager.currentLink) { - LinkManager.currentLink.linkRelationship = value; + Doc.GetProto(LinkManager.currentLink).linkRelationship = value; const linkRelationshipList = StrListCast(Doc.UserDoc().linkRelationshipList); const linkColorList = StrListCast(Doc.UserDoc().linkColorList); // if the relationship does not exist in the list, add it and a corresponding unique randomly generated color @@ -79,7 +80,7 @@ export class LinkEditor extends React.Component { @undoBatch setDescripValue = action((value: string) => { if (LinkManager.currentLink) { - LinkManager.currentLink.description = value; + Doc.GetProto(LinkManager.currentLink).description = value; this.buttonColor = "rgb(62, 133, 55)"; setTimeout(action(() => this.buttonColor = ""), 750); return true; diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index 6708a08ee..72c7e4f45 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -15,6 +15,7 @@ import "./ComparisonBox.scss"; import { DocumentView, DocumentViewProps } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import React = require("react"); +import { DocumentType } from '../../documents/DocumentTypes'; export const comparisonSchema = createSchema({}); @@ -87,7 +88,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent; }; const displayDoc = (which: string) => { - const whichDoc = Cast(this.dataDoc[`compareBox-${which}`], Doc, null); + var whichDoc = Cast(this.dataDoc[which], Doc, null); + if (whichDoc.type === DocumentType.MARKER) whichDoc = Cast(whichDoc.annotationOn, Doc, null); return whichDoc ? <> - {displayBox("after", 1, this.props.PanelWidth() - 3)} + {displayBox(this.fieldKey === "data" ? "compareBox-after" : `${this.fieldKey}2`, 1, this.props.PanelWidth() - 3)}
- {displayBox("before", 0, 0)} + {displayBox(this.fieldKey === "data" ? "compareBox-before" : `${this.fieldKey}1`, 0, 0)}
(this.props.PanelWidth() - 5) / this.props.PanelWidth() ? "w-resize" : undefined }} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 46a8b6629..35249c7f4 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -13,7 +13,7 @@ import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Ty import { AudioField } from "../../../fields/URLField"; import { GetEffectiveAcl, SharingPermissions, TraceMobx } from '../../../fields/util'; import { MobileInterface } from '../../../mobile/MobileInterface'; -import { emptyFunction, hasDescendantTarget, OmitKeys, returnTrue, returnVal, Utils, lightOrDark, simulateMouseClick } from "../../../Utils"; +import { emptyFunction, hasDescendantTarget, OmitKeys, returnTrue, returnVal, Utils, lightOrDark, simulateMouseClick, returnEmptyString } from "../../../Utils"; import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from '../../documents/DocumentTypes'; @@ -802,6 +802,12 @@ export class DocumentViewInternal extends DocComponent StrListCast(this.props.Document._docFilters); + collectionRangeDocFilters = () => StrListCast(this.props.Document._docRangeFilters); + @computed get showFilterIcon() { + return this.collectionFilters().length || this.collectionRangeDocFilters().length ? "hasFilter" : + this.props.docFilters?.().filter(f => Utils.IsRecursiveFilter(f)).length || this.props.docRangeFilters().length ? "inheritsFilter" : undefined + } rootSelected = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false; panelHeight = () => this.props.PanelHeight() - this.headerMargin; screenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -this.headerMargin); @@ -832,7 +838,7 @@ export class DocumentViewInternal extends DocComponent; return
this.props.PanelHeight() || 1; anchorStyleProvider = (doc: Opt, props: Opt, property: string): any => { switch (property) { + case StyleProp.ShowTitle: return ""; case StyleProp.PointerEvents: return "none"; case StyleProp.LinkSource: return this.props.Document;// pass the LinkSource to the LinkAnchorBox default: return this.props.styleProvider?.(doc, props, property); @@ -901,6 +908,8 @@ export class DocumentViewInternal extends DocComponent } + {this.showFilterIcon ? + { this.props.select(false); CurrentUserUtils.propertiesWidth = 250; e.stopPropagation(); })} + /> + : (null)}
; } } diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 55ea45bb8..b82d16677 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -2,10 +2,10 @@ import React = require("react"); import { observer } from "mobx-react"; import { documentSchema } from "../../../fields/documentSchemas"; import { makeInterface } from "../../../fields/Schema"; -import { returnFalse } from "../../../Utils"; -import { CollectionTreeView } from "../collections/CollectionTreeView"; +import { emptyFunction, returnFalse } from "../../../Utils"; import { ViewBoxBaseComponent } from "../DocComponent"; import { StyleProp } from "../StyleProvider"; +import { ComparisonBox } from "./ComparisonBox"; import { FieldView, FieldViewProps } from './FieldView'; import "./LinkBox.scss"; @@ -20,22 +20,15 @@ export class LinkBox extends ViewBoxBaseComponent( if (this.dataDoc.treeViewOpen === undefined) setTimeout(() => this.dataDoc.treeViewOpen = true); return
- - + moveDocument={returnFalse} />
; } } \ No newline at end of file diff --git a/src/client/views/nodes/LinkDescriptionPopup.tsx b/src/client/views/nodes/LinkDescriptionPopup.tsx index b62a4dd56..a9d33f161 100644 --- a/src/client/views/nodes/LinkDescriptionPopup.tsx +++ b/src/client/views/nodes/LinkDescriptionPopup.tsx @@ -1,8 +1,9 @@ import React = require("react"); +import { action, observable } from "mobx"; import { observer } from "mobx-react"; -import "./LinkDescriptionPopup.scss"; -import { observable, action } from "mobx"; +import { Doc } from "../../../fields/Doc"; import { LinkManager } from "../../util/LinkManager"; +import "./LinkDescriptionPopup.scss"; import { TaskCompletionBox } from "./TaskCompletedBox"; @@ -25,7 +26,7 @@ export class LinkDescriptionPopup extends React.Component<{}> { onDismiss = (add: boolean) => { LinkDescriptionPopup.descriptionPopup = false; if (add) { - LinkManager.currentLink && (LinkManager.currentLink.description = this.description); + LinkManager.currentLink && (Doc.GetProto(LinkManager.currentLink).description = this.description); } } diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index f0a502e31..30b4dc92a 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -3,9 +3,9 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction import { observer } from "mobx-react"; import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; -import { Doc, DocListCast, Opt, WidthSym } from "../../../fields/Doc"; +import { Doc, DocListCast, Opt, WidthSym, StrListCast } from "../../../fields/Doc"; import { documentSchema } from '../../../fields/documentSchemas'; -import { makeInterface } from "../../../fields/Schema"; +import { makeInterface, listSpec } from "../../../fields/Schema"; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { PdfField } from "../../../fields/URLField"; import { TraceMobx } from '../../../fields/util'; @@ -25,6 +25,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import { pageSchema } from "./ImageBox"; import "./PDFBox.scss"; import React = require("react"); +import { CurrentUserUtils } from '../../util/CurrentUserUtils'; type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>; const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema); @@ -249,9 +250,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent { - return 1; - } + contentScaling = () => 1; @computed get renderPdfView() { TraceMobx(); const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1; diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 6a20ca14a..60a83d612 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -532,7 +532,8 @@ export class WebBox extends ViewBoxAnnotatableComponent {this.urlContent}
; @@ -575,10 +576,11 @@ export class WebBox extends ViewBoxAnnotatableComponent this.props.PanelHeight() / (this.props.scaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document); scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop)); anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; - transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()]; - opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()]; + basicFilter = () => [...this.props.docFilters(), Utils.PropUnsetFilter("textInlineAnnotations")]; + transparentFilter = () => [Utils.IsTransparentFilter(), ...this.basicFilter()]; + opaqueFilter = () => [Utils.IsOpaqueFilter(), ...this.basicFilter()]; render() { - const pointerEvents = this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined; + const pointerEvents = this.props.layerProvider?.(this.layoutDoc) === false ? "none" : this.props.pointerEvents ? this.props.pointerEvents as any : undefined; const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1; const scale = previewScale * (this.props.scaling?.() || 1); const renderAnnotations = (docFilters?: () => string[]) => @@ -593,7 +595,7 @@ export class WebBox extends ViewBoxAnnotatableComponent; return (
+ style={{ pointerEvents: this.props.isContentActive() && this.props.pointerEvents !== "none" && !MarqueeOptionsMenu.Instance.isShown() ? "all" : SnappingManager.GetIsDragging() ? undefined : "none" }} >
{ let focusSpeed: Opt; if (doc !== this.props.rootDoc && mainCont) { const windowHeight = this.props.PanelHeight() / (this.props.scaling?.() || 1); - const scrollTo = Utils.scrollIntoView(NumCast(doc.y), doc[HeightSym](), NumCast(this.props.layoutDoc._scrollTop), windowHeight, .1 * windowHeight); + const scrollTo = doc.unrendered ? NumCast(doc.y) : Utils.scrollIntoView(NumCast(doc.y), doc[HeightSym](), NumCast(this.props.layoutDoc._scrollTop), windowHeight, .1 * windowHeight); if (scrollTo !== undefined) { focusSpeed = 500; @@ -502,8 +502,9 @@ export class PDFViewer extends React.Component { overlayTransform = () => this.scrollXf().scale(1 / this._zoomed); panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0); panelHeight = () => this.props.PanelHeight() / (this.props.scaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document); - transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()]; - opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()]; + basicFilter = () => [...this.props.docFilters(), Utils.PropUnsetFilter("textInlineAnnotations")]; + transparentFilter = () => [Utils.IsTransparentFilter(), ...this.basicFilter()]; + opaqueFilter = () => [Utils.IsOpaqueFilter(), ...this.basicFilter()]; @computed get overlayLayer() { const renderAnnotations = (docFilters?: () => string[]) => { select={emptyFunction} ContentScaling={this.contentZoom} bringToFront={emptyFunction} - docFilters={docFilters || this.props.docFilters} + docFilters={docFilters || this.basicFilter} dontRenderDocuments={docFilters ? false : true} CollectionView={undefined} ScreenToLocalTransform={this.overlayTransform} @@ -543,7 +544,7 @@ export class PDFViewer extends React.Component {
; } @computed get pdfViewerDiv() { - return
; + return
; } @computed get contentScaling() { return this.props.ContentScaling?.() || 1; } @computed get standinViews() { @@ -556,7 +557,7 @@ export class PDFViewer extends React.Component { render() { TraceMobx(); return
-
, key: string, value: any, modifiers: "remove" | "match" | "check" | "x" | "exists", toggle?: boolean, fieldSuffix?: string, append: boolean = true) { + export function setDocFilter(container: Opt, key: string, value: any, modifiers: "remove" | "match" | "check" | "x" | "exists" | "unset", toggle?: boolean, fieldSuffix?: string, append: boolean = true) { if (!container) return; const filterField = "_" + (fieldSuffix ? fieldSuffix + "-" : "") + "docFilters"; const docFilters = Cast(container[filterField], listSpec("string"), []); -- cgit v1.2.3-70-g09d2