From eacb4733e85ada91520fe401f5c1351f7bbc38d4 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 3 Nov 2020 14:26:19 -0500 Subject: added undo's for icon/deiconifying pile docs and icon docs. added a zoom hack to focus on stacking documents. stopped autoscroll on nested collections. --- src/client/views/collections/CollectionPileView.tsx | 14 ++++++++------ src/client/views/collections/CollectionStackingView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx index 5b4730848..2636b98e5 100644 --- a/src/client/views/collections/CollectionPileView.tsx +++ b/src/client/views/collections/CollectionPileView.tsx @@ -6,7 +6,7 @@ import { emptyFunction, setupMoveUpEvents } from "../../../Utils"; import { DocUtils } from "../../documents/Documents"; import { SelectionManager } from "../../util/SelectionManager"; import { SnappingManager } from "../../util/SnappingManager"; -import { UndoManager } from "../../util/UndoManager"; +import { UndoManager, undoBatch } from "../../util/UndoManager"; import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView"; import "./CollectionPileView.scss"; import { CollectionSubView } from "./CollectionSubView"; @@ -34,14 +34,14 @@ export class CollectionPileView extends CollectionSubView(doc => doc) { const draggingSelf = this.props.isSelected(); return
{ + addDocument={undoBatch((doc: Doc | Doc[]) => { (doc instanceof Doc ? [doc] : doc).map((d) => DocUtils.iconify(d)); return this.props.addDocument(doc); - }} - moveDocument={(doc: Doc | Doc[], targetCollection: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { - (doc instanceof Doc ? [doc] : doc).map((d) => Doc.deiconifyView(d)); + })} + moveDocument={undoBatch((doc: Doc | Doc[], targetCollection: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { + (doc instanceof Doc ? [doc] : doc).map(undoBatch((d) => Doc.deiconifyView(d))); return this.props.moveDocument(doc, targetCollection, addDoc); - }} /> + })} />
; } @@ -107,6 +107,8 @@ export class CollectionPileView extends CollectionSubView(doc => doc) { } // onClick for toggling the pileup view + @undoBatch + @action onClick = (e: React.MouseEvent) => { if (e.button === 0) { SelectionManager.DeselectAll(); diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 4880d342c..7a3257525 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -172,7 +172,7 @@ export class CollectionStackingView extends CollectionSubView boolean) => { Doc.BrushDoc(doc); - this.props.focus(doc); + this.props.focus(this.props.Document, true); // bcz: HACK ARgh.. need to update all focus() functions to take parameters about how to focus. in this case, we want to zoom so we pass true and hope an ancestor is a collection view Doc.linkFollowHighlight(doc); const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName("documentView-node")).find((node: any) => node.id === doc[Id]); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 58a9c4974..703776e72 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1218,7 +1218,7 @@ export class CollectionFreeFormView extends CollectionSubView(Docu thisContainer: this.props.ContainingCollectionDoc, shiftKey: e.shiftKey }, console.log); - func(); + undoBatch(func)(); } else if (!Doc.IsSystem(this.props.Document)) { if (this.props.Document.type === DocumentType.INK) { InkStrokeProperties.Instance && (InkStrokeProperties.Instance._controlBtn = true); -- cgit v1.2.3-70-g09d2 From a43c3c014c3e7bbdfbee8bf234a5812d1601b945 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 3 Nov 2020 17:28:37 -0500 Subject: fixed masonry view to not create empty documents --- src/client/views/collections/CollectionMasonryViewFieldRow.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index 7014966c7..b35644c6b 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -138,7 +138,8 @@ export class CollectionMasonryViewFieldRow extends React.Component { + addDocument = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => { + if (!value && !forceEmptyNote) return false; this._createAliasSelected = false; const key = StrCast(this.props.parent.props.Document._pivotField); const newDoc = Docs.Create.TextDocument(value, { _autoHeight: true, _width: 200, title: value }); @@ -239,6 +240,10 @@ export class CollectionMasonryViewFieldRow extends React.Component ); } + @action + textCallback = (char: string) => { + return this.addDocument("", false); + } @computed get contentLayout() { const rows = Math.max(1, Math.min(this.props.docList.length, Math.floor((this.props.parent.props.PanelWidth() - 2 * this.props.parent.xMargin) / (this.props.parent.columnWidth + this.props.parent.gridGap)))); @@ -247,6 +252,7 @@ export class CollectionMasonryViewFieldRow extends React.Component "", SetValue: this.addDocument, + textCallback: this.textCallback, contents: "+ NEW", HeadingObject: this.props.headingObject, toggle: this.toggleVisibility, -- cgit v1.2.3-70-g09d2 From f23e2f2bcb6ab7fb1895a87a34f8eafcbab90a8d Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 3 Nov 2020 21:40:53 -0500 Subject: fixed LinkManager to cache links correctly. fixes issue with linkButton not showing the correct number. --- src/client/util/LinkManager.ts | 28 +++---- src/client/views/nodes/DocumentLinksButton.tsx | 109 ++++++++++--------------- src/client/views/nodes/DocumentView.tsx | 2 +- 3 files changed, 57 insertions(+), 82 deletions(-) (limited to 'src') diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index c3ab7c6e7..3a0c0e3eb 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -22,47 +22,41 @@ import { computedFn } from "mobx-utils"; export class LinkManager { private static _instance: LinkManager; - public static currentLink: Opt; - public static get Instance(): LinkManager { return this._instance || (this._instance = new this()); } public addLink(linkDoc: Doc) { return Doc.AddDocToList(Doc.LinkDBDoc(), "data", linkDoc); } - public deleteLink(linkDoc: Doc) { return Doc.RemoveDocFromList(Doc.LinkDBDoc(), "data", linkDoc); } - - public deleteAllLinksOnAnchor(anchor: Doc) { LinkManager.Instance.getAllRelatedLinks(anchor).forEach(linkDoc => LinkManager.Instance.deleteLink(linkDoc)); } + public deleteAllLinksOnAnchor(anchor: Doc) { LinkManager.Instance.relatedLinker(anchor).forEach(linkDoc => LinkManager.Instance.deleteLink(linkDoc)); } public getAllRelatedLinks(anchor: Doc) { return this.relatedLinker(anchor); } // finds all links that contain the given anchor - public getAllDirectLinks(anchor: Doc): Doc[] { return this.directLinker(anchor); } // finds all links that contain the given anchor - public getAllLinks(): Doc[] { return this.allLinks(); } - allLinks = computedFn(function allLinks(this: any) { + allLinks = computedFn(function allLinks(this: any): Doc[] { const lset = new Set(DocListCast(Doc.LinkDBDoc().data)); SharingManager.Instance.users.forEach(user => DocListCast(user.linkDatabase?.data).map(doc => lset.add(doc))); return Array.from(lset); }, true); - directLinker = computedFn(function directLinker(this: any, anchor: Doc) { - return LinkManager.Instance.getAllLinks().filter(link => { + directLinker = computedFn(function directLinker(this: any, anchor: Doc): Doc[] { + return LinkManager.Instance.allLinks().filter(link => { const a1 = Cast(link?.anchor1, Doc, null); const a2 = Cast(link?.anchor2, Doc, null); return link && ((a1?.author !== undefined && a2?.author !== undefined) || link.author === Doc.CurrentUserEmail) && (Doc.AreProtosEqual(anchor, a1) || Doc.AreProtosEqual(anchor, a2) || Doc.AreProtosEqual(link, anchor)); }); }, true); - relatedLinker = computedFn(function relatedLinker(this: any, anchor: Doc) { - const related = LinkManager.Instance.directLinker(anchor); - DocListCast(anchor[Doc.LayoutFieldKey(anchor) + "-annotations"]).map(anno => related.push(...LinkManager.Instance.getAllRelatedLinks(anno))); - return related; + relatedLinker = computedFn(function relatedLinker(this: any, anchor: Doc): Doc[] { + return DocListCast(anchor[Doc.LayoutFieldKey(anchor) + "-annotations"]).reduce((list, anno) => + [...list, ...LinkManager.Instance.relatedLinker(anno)], + LinkManager.Instance.directLinker(anchor).slice()); }, true); // returns map of group type to anchor's links in that group type public getRelatedGroupedLinks(anchor: Doc): Map> { const anchorGroups = new Map>(); - this.getAllRelatedLinks(anchor).forEach(link => { + this.relatedLinker(anchor).forEach(link => { if (!link.linkRelationship || link?.linkRelationship !== "-ungrouped-") { const group = anchorGroups.get(StrCast(link.linkRelationship)); anchorGroups.set(StrCast(link.linkRelationship), group ? [...group, link] : [link]); @@ -78,13 +72,13 @@ export class LinkManager { // returns a list of all metadata docs associated with the given group type public getAllMetadataDocsInGroup(groupType: string): Array { const md: Doc[] = []; - LinkManager.Instance.getAllLinks().forEach(linkDoc => StrCast(linkDoc.linkRelationship).toUpperCase() === groupType.toUpperCase() && md.push(linkDoc)); + LinkManager.Instance.allLinks().forEach(linkDoc => StrCast(linkDoc.linkRelationship).toUpperCase() === groupType.toUpperCase() && md.push(linkDoc)); return md; } // checks if a link with the given anchors exists public doesLinkExist(anchor1: Doc, anchor2: Doc): boolean { - return -1 !== LinkManager.Instance.getAllLinks().findIndex(linkDoc => + return -1 !== LinkManager.Instance.allLinks().findIndex(linkDoc => (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, null), anchor1) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, null), anchor2)) || (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, null), anchor2) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, null), anchor1))); } diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index a167f2a23..95c007175 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -3,7 +3,6 @@ import { Tooltip } from "@material-ui/core"; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, Opt } from "../../../fields/Doc"; -import { DocumentType } from "../../documents/DocumentTypes"; import { emptyFunction, setupMoveUpEvents, returnFalse, Utils, emptyPath } from "../../../Utils"; import { TraceMobx } from "../../../fields/util"; import { DocUtils, Docs } from "../../documents/Documents"; @@ -39,6 +38,7 @@ export class DocumentLinksButton extends React.Component; public static invisibleWebRef = React.createRef(); @@ -209,94 +209,75 @@ export class DocumentLinksButton extends React.Component(this.props.links)), this.props.View.props.docFilters(), []); - - const menuTitle = this.props.StartLink ? "Drag or tap to start link" : "Tap to complete link"; - const buttonTitle = "Tap to view links"; - const title = this.props.InMenu ? menuTitle : buttonTitle; - - - const startLink = ; - - const endLink = ; + @computed get filteredLinks() { + return DocUtils.FilterDocs(Array.from(new Set(this.props.links)), this.props.View.props.docFilters(), []); + } - const link = ; + @computed get linkButtonInner() { + const btnDim = this.props.InMenu ? "20px" : "30px"; + const link = ; - const linkButton =
-
+
LinkDocPreview.LinkInfo = undefined)} - // onPointerEnter={action(e => links.length && (LinkDocPreview.LinkInfo = { - // addDocTab: this.props.View.props.addDocTab, - // linkSrc: this.props.View.props.Document, - // linkDoc: links[0], - // Location: [e.clientX, e.clientY + 20] - // }))} - > - - {/* {this.props.InMenu ? this.props.StartLink ? : - : links.length} */} - - {this.props.InMenu ? this.props.StartLink ? : - link : Array.from(links).length} - + style={{ + backgroundColor: this.props.InMenu ? "" : "#add8e6", + color: this.props.InMenu ? "white" : "black", + width: btnDim, + height: btnDim, + }} > + {this.props.InMenu ? + this.props.StartLink ? + + : link + : Array.from(this.filteredLinks).length}
{this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ?
DocumentLinksButton.StartLink ? DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View) : emptyFunction} /> : (null) + onPointerDown={DocumentLinksButton.StartLink && this.completeLink} + onClick={e => DocumentLinksButton.StartLink && DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View)} /> + : (null) } - { - DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.InMenu && this.props.StartLink ?
: (null) + {DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.InMenu && this.props.StartLink ? +
+ : (null) }
; + } + + @computed get linkButton() { + TraceMobx(); + + const menuTitle = this.props.StartLink ? "Drag or tap to start link" : "Tap to complete link"; + const buttonTitle = "Tap to view links"; + const title = this.props.InMenu ? menuTitle : buttonTitle; - return (!Array.from(links).length) && !this.props.AlwaysOn ? (null) : + return !Array.from(this.filteredLinks).length && !this.props.AlwaysOn ? (null) : this.props.InMenu && (DocumentLinksButton.StartLink || this.props.StartLink) ?
{title}
}> - {linkButton} -
: !!!DocumentLinksButton.EditLink && !this.props.InMenu ? + {this.linkButtonInner} + + : + !DocumentLinksButton.EditLink && !this.props.InMenu ?
{title}
}> - {linkButton} -
: - linkButton; + {this.linkButtonInner} + + : this.linkButtonInner; } render() { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index f6a147c50..3ebaad0a3 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -990,7 +990,7 @@ export class DocumentView extends DocComponent(Docu anchorPanelHeight = () => this.props.PanelHeight() || 1; @computed get directLinks() { TraceMobx(); return LinkManager.Instance.getAllDirectLinks(this.rootDoc); } - @computed get allLinks() { TraceMobx(); return DocListCast(this.Document.links); } + @computed get allLinks() { TraceMobx(); return LinkManager.Instance.getAllRelatedLinks(this.rootDoc); } @computed get allAnchors() { TraceMobx(); if (this.props.LayoutTemplateString?.includes("LinkAnchorBox")) return null; -- cgit v1.2.3-70-g09d2 From 7ec8db4f2ebdd0ce9e829becf9b3cca289eed7c5 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 4 Nov 2020 11:49:10 -0500 Subject: made linkMenuItems trigger on mouseUp to prevent dragging a link when clicking to follow one. --- src/client/views/linking/LinkMenuItem.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 1ba724889..5c9123876 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -109,6 +109,7 @@ export class LinkMenuItem extends React.Component { onLinkButtonUp = (e: PointerEvent): void => { document.removeEventListener("pointermove", this.onLinkButtonMoved); document.removeEventListener("pointerup", this.onLinkButtonUp); + DocumentView.followLinkClick(this.props.linkDoc, this.props.sourceDoc, this.props.docView.props, false, false); e.stopPropagation(); } @@ -228,18 +229,17 @@ export class LinkMenuItem extends React.Component { onPointerDown={this.onLinkButtonDown}>
- {source ?

- Source: {source}

: null} + {source ?

Source: {source}

: null}
-
-

DocumentView.followLinkClick(this.props.linkDoc, this.props.sourceDoc, this.props.docView.props, false, false)}> + +

+

{this.props.linkDoc.linksToAnnotation && Cast(this.props.destinationDoc.data, WebField)?.url.href === this.props.linkDoc.annotationUri ? "Annotation in" : ""} {title}

- {this.props.linkDoc.description !== "" ?

- {StrCast(this.props.linkDoc.description)}

: null}
+ {!this.props.linkDoc.description ? (null) :

{StrCast(this.props.linkDoc.description)}

} +
-- cgit v1.2.3-70-g09d2 From 4becefec2200632b482b7660bd3bb0792a4ba1d8 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 4 Nov 2020 15:41:12 -0500 Subject: made font size of tree view ignore font size of document --- src/client/views/nodes/DocumentView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 3ebaad0a3..4efa5d67f 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1157,7 +1157,7 @@ export class DocumentView extends DocComponent(Docu background: finalColor, opacity: finalOpacity, fontFamily: StrCast(this.Document._fontFamily, "inherit"), - fontSize: Cast(this.Document._fontSize, "string", null), + fontSize: !this.props.treeViewDoc ? Cast(this.Document._fontSize, "string", null) : undefined, }}> {this.onClickHandler && this.props.ContainingCollectionView?.props.Document._viewType === CollectionViewType.Time ? <> {this.innards} -- cgit v1.2.3-70-g09d2 From 38912acdfe5d52ab068bb11d05e1767ecc5d56ac Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 5 Nov 2020 09:53:38 -0500 Subject: fixed layer ordering of annotaitons and overlays on PDFs so that overlays are always on top. made textLayer on PDFs display:none when not-selected to try to improve rendering. --- src/client/views/nodes/PDFBox.scss | 2 ++ src/client/views/pdf/PDFViewer.tsx | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index e2bdd98cc..16cc9d27e 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -208,6 +208,7 @@ pointer-events: none; .pdfViewerDash-text { .textLayer { + display: none; span { user-select: none; } @@ -228,6 +229,7 @@ z-index: -1; .pdfViewerDash-text { .textLayer { + display: contents; span { user-select: text; } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 76b218972..48c7b1762 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -792,8 +792,8 @@ export class PDFViewer extends ViewBoxAnnotatableComponent {this.pdfViewerDiv} - {this.overlayLayer} {this.annotationLayer} + {this.overlayLayer} {this.overlayInfo} {this.standinViews} -- cgit v1.2.3-70-g09d2 From 5910435416fea88d81d1868977a421c28ef05b2a Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 5 Nov 2020 11:27:43 -0500 Subject: fixed color of libraryHandle. changed opening a prensetation that is alrady open and minimzed to do nothing. --- src/client/views/MainView.scss | 3 +++ src/client/views/collections/CollectionDockingView.tsx | 2 ++ 2 files changed, 5 insertions(+) (limited to 'src') diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss index b49990433..33bd7e77e 100644 --- a/src/client/views/MainView.scss +++ b/src/client/views/MainView.scss @@ -181,6 +181,9 @@ } } +.mainView-libraryHandle { + background-color: lightgrey; +} .mainView-innerContent-dark { .propertiesView { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index d2c065417..e43f188e7 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -22,6 +22,7 @@ import { CollectionViewType } from './CollectionView'; import { TabDocView } from './TabDocView'; import React = require("react"); import { stat } from 'fs'; +import { DocumentType } from '../../documents/DocumentTypes'; const _global = (window /* browser */ || global /* node */) as any; @observer @@ -143,6 +144,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { @undoBatch @action public static AddSplit(document: Doc, pullSide: string, stack?: any, panelName?: string) { + if (document.type === DocumentType.PRES && DocListCast(Cast(Doc.UserDoc().myOverlayDocs, Doc, null).data).includes(document)) return false; if (document._viewType === CollectionViewType.Docking) return CurrentUserUtils.openDashboard(Doc.UserDoc(), document); const tab = Array.from(CollectionDockingView.Instance.tabMap).find(tab => tab.DashDoc === document); -- cgit v1.2.3-70-g09d2