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/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 +- 4 files changed, 29 insertions(+), 17 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b2629200d..2c9daa370 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -847,16 +847,28 @@ export class DocumentViewInternal extends DocComponent + 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') 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 a11cbed94999a437d3b51dbf8632441acdb8b5be Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 8 Sep 2021 09:33:16 -0400 Subject: tried adjusting text annotation button so text would be more readable in corner. --- .../views/nodes/formattedText/FormattedTextBox.scss | 17 +++++++---------- .../views/nodes/formattedText/FormattedTextBox.tsx | 6 ++++-- 2 files changed, 11 insertions(+), 12 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss index 56f5c5631..4134e3c67 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.scss +++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss @@ -66,11 +66,12 @@ audiotag:hover { .formattedTextBox-sidebar-handle { position: absolute; - top: 5px; + top: 0; + left: 17px; //top: calc(50% - 17.5px); // use this to center vertically -- make sure it looks okay for slide views - width: 25px; - height: 100%; - max-height: 25px; + width: 17px; + height: 17px; + border-radius: 3px; color: white; background: $medium-gray; border-radius: 5px; @@ -80,8 +81,9 @@ audiotag:hover { cursor:grabbing; box-shadow: $standard-box-shadow; // transition: 0.2s; - + opacity: 0.3; &:hover{ + opacity: 1 !important; filter: brightness(0.85); } @@ -425,12 +427,7 @@ footnote::after { .formattedTextBox-sidebar-handle { position: absolute; - top: 0; - //top: calc(50% - 17.5px); // use this to center vertically -- make sure it looks okay for slide views - width: 10px; - height: 35px; background: lightgray; - border-radius: 20px; cursor: grabbing; } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index cad9af2b0..bc19320e9 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1360,6 +1360,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this._undoTyping = undefined; return wasUndoing; } + @action onBlur = (e: any) => { FormattedTextBox.Focused === this && (FormattedTextBox.Focused = undefined); @@ -1485,9 +1486,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const backgroundColor = !annotated ? this.sidebarWidth() ? Colors.MEDIUM_BLUE : Colors.BLACK : this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.WidgetColor + (annotated ? ":annotated" : "")); return (!annotated && !this.props.isContentActive()) ? (null) :
; -- cgit v1.2.3-70-g09d2 From 058cf10e63fe784ba97f288e24fc58d41e0d46f3 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 8 Sep 2021 10:56:05 -0400 Subject: made setting background undoable. added setting header color/visibility from main toolbar. made changing header contents possible using #(; ; + const targetDoc = (showTitle?.startsWith("_") ? this.layoutDoc : this.rootDoc); const titleView = !showTitle ? (null) :
field + ":" + (this.dataDoc || this.props.Document)[field]?.toString()).join(" ")} + contents={showTitle.split(";").map(field => field.trim()).map(field => targetDoc[field]?.toString()).join("\\")} display={"block"} fontSize={10} - GetValue={() => Field.toString((this.dataDoc || this.props.Document)[showTitle.split(";")[0]] as any as Field)} - SetValue={undoBatch((value) => showTitle.includes("Date") ? true : (Doc.GetProto(this.dataDoc || this.props.Document)[showTitle] = value) ? true : true)} + GetValue={() => showTitle.split(";").length === 1 ? showTitle + "=" + Field.toString(targetDoc[showTitle.split(";")[0]] as any as Field) : "#" + showTitle} + SetValue={undoBatch(value => { + if (value?.startsWith(showTitle + "=")) { + value = value.substring((showTitle + "=").length); + if (showTitle !== "title" && Number(value).toString() === value) value = Number(value); + if (showTitle.includes("Date") || showTitle === "author") return true; + return Doc.SetInPlace(targetDoc, showTitle, value, true) ? true : true; + } else if (value?.startsWith("#")) { + Doc.UserDoc().showTitle = value?.substring(1) ? value.substring(1) : "creationDate"; + return true; + } + return true; + })} />
; return this.props.hideTitle || (!showTitle && !showCaption) ? diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index b72f31ef8..4475cf347 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -15,7 +15,7 @@ import { DocumentType } from '../../../documents/DocumentTypes'; import { Scripting } from "../../../util/Scripting"; import { SelectionManager } from '../../../util/SelectionManager'; import { ColorScheme } from '../../../util/SettingsManager'; -import { UndoManager } from '../../../util/UndoManager'; +import { UndoManager, undoBatch } from '../../../util/UndoManager'; import { CollectionViewType } from '../../collections/CollectionView'; import { ContextMenu } from '../../ContextMenu'; import { DocComponent } from '../../DocComponent'; @@ -31,6 +31,7 @@ import { ToggleButton } from './toggleButton'; import { IButtonProps } from './ButtonInterface'; import { FontIconBadge } from './FontIconBadge'; import './FontIconBox.scss'; +import { undo } from 'prosemirror-history'; const FontIconSchema = createSchema({ icon: "string", }); @@ -303,7 +304,7 @@ export class FontIconBox extends DocComponent(Fon
this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen : undefined}> - {dropdown || noneSelected ? (null) : } + {dropdown || noneSelected ? (null) : }
{text && text[0].toUpperCase() + text.slice(1)}
@@ -348,7 +349,7 @@ export class FontIconBox extends DocComponent(Fon const colorOptions: string[] = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', - '#FFFFFF', '#f1efeb']; + '#FFFFFF', '#f1efeb', "transparent"]; const colorBox = (func: (color: ColorState) => void) => (Fon const hex: string = value.hex; const s = ScriptField.MakeScript(script + '("' + hex + '", false)'); if (s) { - s.script.run().result; + undoBatch(() => s.script.run().result)(); } }; return ( @@ -493,7 +494,7 @@ export class FontIconBox extends DocComponent(Fon {this.label}
; - const buttonProps:IButtonProps = { + const buttonProps: IButtonProps = { type: this.type, rootDoc: this.rootDoc, label: label, @@ -512,9 +513,9 @@ export class FontIconBox extends DocComponent(Fon button = (
- {buttonText ? + {buttonText ?
- {buttonText} + {buttonText}
: null} {label} @@ -598,11 +599,18 @@ Scripting.addGlobal(function setBackgroundColor(color?: string, checkResult?: bo return "#FFFFFF"; } } - if (selected && selected.type === DocumentType.INK) selected.fillColor = color; + if (selected?.type === DocumentType.INK) selected.fillColor = color; if (selected) selected._backgroundColor = color; Doc.UserDoc()._fontColor = color; }); +// toggle: Set overlay status of selected document +Scripting.addGlobal(function setHeaderColor(color?: string, checkResult?: boolean) { + Doc.SharingDoc().userColor = undefined; + Doc.GetProto(Doc.SharingDoc()).userColor = color; + Doc.UserDoc().showTitle = color === "transparent" ? undefined : StrCast(Doc.UserDoc().showTitle, "creationDate"); +}); + // toggle: Set overlay status of selected document Scripting.addGlobal(function toggleOverlay(checkResult?: boolean) { const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index bc19320e9..fbb291858 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1484,15 +1484,16 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length; const color = !annotated ? Colors.WHITE : Colors.BLACK; const backgroundColor = !annotated ? this.sidebarWidth() ? Colors.MEDIUM_BLUE : Colors.BLACK : this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.WidgetColor + (annotated ? ":annotated" : "")); - return (!annotated && !this.props.isContentActive()) ? (null) :
- -
; + return (!annotated && (!this.props.isContentActive() || SnappingManager.GetIsDragging())) ? (null) : +
+ +
; } @computed get sidebarCollection() { const renderComponent = (tag: string) => { -- cgit v1.2.3-70-g09d2 From ca8cc74157adb339c15161cacf567c726dd15d1a Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 8 Sep 2021 14:00:10 -0400 Subject: from last (fixed text color for headers) --- src/client/views/nodes/DocumentView.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 384d2e456..07e0e2d52 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 } from "../../../Utils"; +import { emptyFunction, hasDescendantTarget, OmitKeys, returnTrue, returnVal, Utils, lightOrDark } from "../../../Utils"; import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from '../../documents/DocumentTypes'; @@ -953,11 +953,13 @@ export class DocumentViewInternal extends DocComponent
; const targetDoc = (showTitle?.startsWith("_") ? this.layoutDoc : this.rootDoc); + const background = StrCast(SharingManager.Instance.users.find(users => users.user.email === this.dataDoc.author)?.sharingDoc.userColor, this.rootDoc.type === DocumentType.RTF ? StrCast(Doc.SharingDoc().userColor) : "rgba(0,0,0,0.4)"); const titleView = !showTitle ? (null) :
users.user.email === this.dataDoc.author)?.sharingDoc.userColor, this.rootDoc.type === DocumentType.RTF ? StrCast(Doc.SharingDoc().userColor) : "rgba(0,0,0,0.4)"), + color: lightOrDark(background), + background, pointerEvents: this.onClickHandler || this.Document.ignoreClick ? "none" : undefined, }}> Date: Wed, 8 Sep 2021 18:55:32 -0400 Subject: added showTitle prop to allow sidebarAnnos to have a custom title --- src/client/views/SidebarAnnos.tsx | 10 ++-------- src/client/views/StyleProvider.tsx | 9 ++++++--- src/client/views/collections/CollectionStackingView.tsx | 15 ++++++++------- .../collections/CollectionStackingViewFieldColumn.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 1 + .../collectionFreeForm/CollectionFreeFormView.tsx | 1 + src/client/views/nodes/DocumentView.tsx | 15 +++++++++++---- 7 files changed, 30 insertions(+), 23 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index 01b79ffd2..dd851c764 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -83,13 +83,7 @@ export class SidebarAnnos extends React.Component { moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument(doc, targetCollection, addDocument, this.sidebarKey); removeDocument = (doc: Doc | Doc[]) => this.props.removeDocument(doc, this.sidebarKey); docFilters = () => [...StrListCast(this.props.layoutDoc._docFilters), ...StrListCast(this.props.layoutDoc[this.filtersKey])]; - - sidebarStyleProvider = (doc: Opt, props: Opt, property: string) => { - if (property === StyleProp.ShowTitle) { - return doc === this.props.rootDoc ? undefined : StrCast(this.props.layoutDoc["sidebar-childShowTitle"], "title"); - } - return this.props.styleProvider?.(doc, props, property); - } + showTitle = () => "title"; setHeightCallback = (height: number) => this.props.setHeight(height + this.filtersHeight()); render() { const renderTag = (tag: string) => { @@ -125,13 +119,13 @@ export class SidebarAnnos extends React.Component { NativeHeight={returnZero} PanelHeight={this.panelHeight} PanelWidth={this.panelWidth} - styleProvider={this.sidebarStyleProvider} docFilters={this.docFilters} scaleField={this.sidebarKey + "-scale"} setHeight={this.setHeightCallback} isAnnotationOverlay={false} select={emptyFunction} scaling={returnOne} + childShowTitle={this.showTitle} whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged} childHideDecorationTitle={returnTrue} removeDocument={this.removeDocument} diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index e528e84e3..3413179ed 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -93,9 +93,12 @@ export function DefaultStyleProvider(doc: Opt, props: Opt = StrCast(doc?.[fieldKey + "color"], StrCast(doc?._color)); diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index c92b259d0..540bfd1ef 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -236,6 +236,7 @@ export class CollectionStackingView extends CollectionSubView + style={{ width: width, height: height }}>
); @@ -579,7 +580,7 @@ export class CollectionStackingView extends CollectionSubView {buttonMenu || noviceExplainer ?
{buttonMenu ? this.buttonMenu : null} - {Doc.UserDoc().noviceMode && noviceExplainer ? + {Doc.UserDoc().noviceMode && noviceExplainer ?
{noviceExplainer}
@@ -612,10 +613,10 @@ export class CollectionStackingView extends CollectionSubView} */} -
+ - + ); } } diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 47733994b..58289a161 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -111,7 +111,7 @@ export class CollectionStackingViewFieldColumn extends React.Component SnappingManager.GetIsDragging() && (this._background = "#b4b4b4"); @action pointerLeave = () => this._background = "inherit"; - textCallback = (char: string) => this.addNewTextDoc("", false, true); + textCallback = (char: string) => this.addNewTextDoc("-typed text-", false, true); @action addNewTextDoc = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 81375e557..bc02c44f0 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -71,6 +71,7 @@ export interface CollectionViewProps extends FieldViewProps { childDocuments?: Doc[]; // used to override the documents shown by the sub collection to an explicit list (see LinkBox) childDocumentsActive?: () => boolean;// whether child documents can be dragged if collection can be dragged (eg., in a when a Pile document is in startburst mode) childFitWidth?: () => boolean; + childShowTitle?: () => string; childOpacity?: () => number; childContextMenuItems?: () => { script: ScriptField, label: string }[]; childHideTitle?: () => boolean; // whether to hide the documentdecorations title for children diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 018c2a895..c8561d901 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1052,6 +1052,7 @@ export class CollectionFreeFormView extends CollectionSubView string[]; docRangeFilters: () => string[]; searchFilterDocs: () => Doc[]; + showTitle?: () => string; whenChildContentsActiveChanged: (isActive: boolean) => void; rootSelected: (outsideReaction?: boolean) => boolean; // whether the root of a template has been selected addDocTab: (doc: Doc, where: string) => boolean; @@ -703,9 +704,11 @@ export class DocumentViewInternal extends DocComponent SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: "expand-arrows-alt" }); - zorderItems.push({ description: "Send to Back", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: "expand-arrows-alt" }); - zorderItems.push({ description: this.rootDoc._raiseWhenDragged !== false ? "Keep ZIndex when dragged" : "Allow ZIndex to change when dragged", event: undoBatch(action(() => this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined)), icon: "expand-arrows-alt" }); + if (this.props.bringToFront !== emptyFunction) { + zorderItems.push({ description: "Bring to Front", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: "expand-arrows-alt" }); + zorderItems.push({ description: "Send to Back", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: "expand-arrows-alt" }); + zorderItems.push({ description: this.rootDoc._raiseWhenDragged !== false ? "Keep ZIndex when dragged" : "Allow ZIndex to change when dragged", event: undoBatch(action(() => this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined)), icon: "expand-arrows-alt" }); + } !zorders && cm.addItem({ description: "ZOrder...", subitems: zorderItems, icon: "compass" }); onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" }); @@ -974,7 +977,11 @@ export class DocumentViewInternal extends DocComponent Date: Thu, 9 Sep 2021 14:46:06 -0400 Subject: fixed anchor menu highlighter button's dropdown location. fixed metadata view for formattedText. added menu item for metadata view. fixed formattedTextbox initialization. --- src/client/util/CurrentUserUtils.ts | 15 ++++++----- src/client/util/Scripting.ts | 8 +++--- src/client/views/DocComponent.tsx | 2 +- src/client/views/nodes/DocumentContentsView.tsx | 3 ++- src/client/views/nodes/DocumentView.tsx | 20 +++++++------- .../views/nodes/formattedText/DashFieldView.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 31 +++++++++++++++------- .../views/nodes/formattedText/RichTextMenu.scss | 1 + src/client/views/pdf/AnchorMenu.scss | 29 ++++++++++++++++++++ src/client/views/pdf/AnchorMenu.tsx | 13 +++++---- 10 files changed, 86 insertions(+), 38 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index eb9184e88..816503b37 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -22,6 +22,7 @@ import { DimUnit } from "../views/collections/collectionMulticolumn/CollectionMu import { CollectionView, CollectionViewType } from "../views/collections/CollectionView"; import { Colors } from "../views/global/globalEnums"; import { MainView } from "../views/MainView"; +import { ButtonType, NumButtonType } from "../views/nodes/button/FontIconBox"; import { FormattedTextBox } from "../views/nodes/formattedText/FormattedTextBox"; import { LabelBox } from "../views/nodes/LabelBox"; import { OverlayView } from "../views/OverlayView"; @@ -37,8 +38,6 @@ import { ColorScheme } from "./SettingsManager"; import { SharingManager } from "./SharingManager"; import { SnappingManager } from "./SnappingManager"; import { UndoManager } from "./UndoManager"; -import { ButtonType, NumButtonType } from "../views/nodes/button/FontIconBox"; -import { IconName } from "@fortawesome/fontawesome-svg-core"; interface Button { title?: string; @@ -447,16 +446,16 @@ export class CurrentUserUtils { storedMarks: [] }; const headerTemplate = Docs.Create.RTFDocument(new RichTextField(JSON.stringify(json), ""), { - title: "text", version: headerViewVersion, target: doc, _height: 70, _headerPointerEvents: "all", + title: "text", version: headerViewVersion, _height: 70, _headerPointerEvents: "all", _headerHeight: 12, _headerFontSize: 9, _autoHeight: true, system: true, _fitWidth: true, cloneFieldFilter: new List(["system"]) }, "header"); const headerBtnHgt = 10; headerTemplate[DataSym].layout = "" + - ` ` + - " " + - ` Metadata` + + ` ` + + " " + + ` Metadata` + ""; // "
" + @@ -562,7 +561,7 @@ export class CurrentUserUtils { if (dragCreatorSet === undefined) { doc.myItemCreators = new PrefetchProxy(Docs.Create.MasonryDocument(creatorBtns, { title: "Basic Item Creators", _showTitle: "title", _xMargin: 0, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true, - _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 40, ignoreClick: true, _lockedPosition: true, + _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 40, ignoreClick: true, _lockedPosition: true, _forceActive: true, dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), system: true })); } else { @@ -1554,6 +1553,8 @@ Scripting.addGlobal(function openDragFactory(dragFactory: Doc) { view && SelectionManager.SelectView(view, false); } }); +Scripting.addGlobal(function MySharedDocs() { return Doc.SharingDoc(); }, + "document containing all shared Docs"); Scripting.addGlobal(function IsNoviceMode() { return Doc.UserDoc().noviceMode; }, "is Dash in novice mode"); Scripting.addGlobal(function snapshotDashboard() { CurrentUserUtils.snapshotDashboard(Doc.UserDoc()); }, diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index efee37419..40b94024e 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -171,7 +171,7 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an if (!options.editable) { batch = Doc.MakeReadOnly(); } - + const result = compiledFunction.apply(thisParam, params).apply(thisParam, argsArray); if (batch) { batch.end(); @@ -316,9 +316,9 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp paramList.push(`${key}: ${typeof val === "object" ? Object.getPrototypeOf(val).constructor.name : typeof val}`); } const paramString = paramList.join(", "); - const funcScript = `(function(${paramString})${requiredType ? `: ${requiredType}` : ''} { - ${addReturn ? `return ${script};` : `return ${script};`} - })`; + const body = addReturn ? `return ${script};` : `return ${script};`; + const reqTypes = requiredType ? `: ${requiredType}` : ''; + const funcScript = `(function(${paramString})${reqTypes} { ${body} })`; host.writeFile("file.ts", funcScript); if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib); diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 33dff9da5..cb36f4270 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -115,7 +115,7 @@ export function ViewBoxAnnotatableComponent

{ // bcz: this executes a script to convert a property expression string: { script } into a value - return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name, scale: "number" })?.script.run({ self: this.rootDoc, this: this.layoutDoc, scale }).result as string || ""; + return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name, scale: "number" })?.script.run({ self: this.rootDoc, this: this.layoutDoc, scale }).result?.toString() ?? ""; }; divKeys.map((prop: string) => { const p = (this.props as any)[prop]; diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 544125ede..fad905d6d 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -201,7 +201,8 @@ export class DocumentContentsView extends React.Component 1) { const code = XRegExp.matchRecursive(splits[1], "{", "}", "", { valueNames: ["between", "left", "match", "right", "between"] }); layoutFrame = splits[0] + ` ${func}={props.${func}} ` + splits[1].substring(code[1].end + 1); - return ScriptField.MakeScript(code[1].value, { this: Doc.name, self: Doc.name, scale: "number", value: "string" }); + const script = code[1].value.replace(/^‘/, "").replace(/’$/, ""); // ‘’ are not valid quotes in javascript so get rid of them -- they may be present to make it easier to write complex scripts - see headerTemplate in currentUserUtils.ts + return ScriptField.MakeScript(script, { this: Doc.name, self: Doc.name, scale: "number", value: "string" }); } return undefined; // add input function to props diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 6eeb51ffe..6f97cdbd8 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -712,7 +712,7 @@ export class DocumentViewInternal extends DocComponent this.Document.followLinkZoom = !this.Document.followLinkZoom, icon: this.Document.ignoreClick ? "unlock" : "lock" }); if (!this.Document.annotationOn) { @@ -970,19 +970,19 @@ export class DocumentViewInternal extends DocComponent showTitle.split(";").length === 1 ? showTitle + "=" + Field.toString(targetDoc[showTitle.split(";")[0]] as any as Field) : "#" + showTitle} - SetValue={undoBatch(value => { - if (value?.startsWith(showTitle + "=")) { - value = value.substring((showTitle + "=").length); - if (showTitle !== "title" && Number(value).toString() === value) value = Number(value); - if (showTitle.includes("Date") || showTitle === "author") return true; - return Doc.SetInPlace(targetDoc, showTitle, value, true) ? true : true; - } else if (value?.startsWith("#")) { + SetValue={undoBatch(input => { + if (input?.startsWith("#")) { if (this.props.showTitle) { - this.rootDoc._showTitle = value?.substring(1) ? value.substring(1) : undefined; + this.rootDoc._showTitle = input?.substring(1) ? input.substring(1) : undefined; } else { - Doc.UserDoc().showTitle = value?.substring(1) ? value.substring(1) : "creationDate"; + Doc.UserDoc().showTitle = input?.substring(1) ? input.substring(1) : "creationDate"; } return true; + } else { + var value = input.replace(new RegExp(showTitle + "="), ""); + if (showTitle !== "title" && Number(value).toString() === value) value = Number(value); + if (showTitle.includes("Date") || showTitle === "author") return true; + return Doc.SetInPlace(targetDoc, showTitle, value, true) ? true : true; } return true; })} diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index 62f65cdae..34908e54b 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -82,7 +82,7 @@ export class DashFieldViewInternal extends React.Component { this.ProseRef = ele; + this.setupEditor(this.config, this.props.fieldKey); this._dropDisposer?.(); ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.layoutDoc)); // if (this.autoHeight) this.tryUpdateScrollHeight(); @@ -573,12 +574,25 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const cm = ContextMenu.Instance; const changeItems: ContextMenuProps[] = []; - changeItems.push({ description: "plain", event: undoBatch(() => Doc.setNativeView(this.rootDoc)), icon: "eye" }); + changeItems.push({ + description: "plain", event: undoBatch(() => { + Doc.setNativeView(this.rootDoc); + this.layoutDoc.autoHeightMargins = undefined; + }), icon: "eye" + }); + changeItems.push({ + description: "metadata", event: undoBatch(() => { + this.dataDoc.layout_meta = Cast(Doc.UserDoc().emptyHeader, Doc, null)?.layout; + this.rootDoc.layoutKey = "layout_meta"; + setTimeout(() => this.rootDoc._headerHeight = this.rootDoc._autoHeightMargins = 50, 50); + }), icon: "eye" + }); const noteTypesDoc = Cast(Doc.UserDoc()["template-notes"], Doc, null); DocListCast(noteTypesDoc?.data).forEach(note => { const icon: IconProp = StrCast(note.icon) as IconProp; changeItems.push({ description: StrCast(note.title), event: undoBatch(() => { + this.layoutDoc.autoHeightMargins = undefined; Doc.setNativeView(this.rootDoc); DocUtils.makeCustomViewClicked(this.rootDoc, Docs.Create.TreeDocument, StrCast(note.title), note); }), icon: icon @@ -864,8 +878,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } ); - this.setupEditor(this.config, this.props.fieldKey); - this._disposers.search = reaction(() => Doc.IsSearchMatch(this.rootDoc), search => search ? this.highlightSearchTerms([Doc.SearchQuery()], search.searchMatch < 0) : this.unhighlightSearchTerms(), { fireImmediately: Doc.IsSearchMatchUnmemoized(this.rootDoc) ? true : false }); @@ -1144,8 +1156,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } selectOnLoad && this._editorView!.focus(); // add user mark for any first character that was typed since the user mark that gets set in KeyPress won't have been called yet. - if (!this._editorView!.state.storedMarks?.some(mark => mark.type === schema.marks.user_mark)) { - this._editorView!.state.storedMarks = [...(this._editorView!.state.storedMarks ?? []), schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })]; + if (this._editorView && !this._editorView.state.storedMarks?.some(mark => mark.type === schema.marks.user_mark)) { + this._editorView.state.storedMarks = [...(this._editorView!.state.storedMarks ?? []), schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })]; } } @@ -1487,7 +1499,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp return (!annotated && (!this.props.isContentActive() || SnappingManager.GetIsDragging())) ? (null) :

= 10 ? "-selected" : ""; - return ( + const styleFromString = this.styleFromLayoutString(scale); // this converts any expressions in the format string to style props. e.g., + return (styleFromString?.height === "0px" ? (null) :
this.props.isContentActive() && e.stopPropagation()} style={{ @@ -1564,7 +1577,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp width: this.props.dontScale ? undefined : `${100 / scale}%`, height: this.props.dontScale ? undefined : `${100 / scale}%`, // overflowY: this.layoutDoc._autoHeight ? "hidden" : undefined, - ...this.styleFromLayoutString(scale) // this converts any expressions in the format string to style props. e.g., + ...styleFromString }}>
{ @observable private highlightColor: string = "rgba(245, 230, 95, 0.616)"; @observable private _showLinkPopup: boolean = false; - @observable public _colorBtn = false; @observable public Highlighting: boolean = false; @observable public Status: "marquee" | "annotation" | "" = ""; @@ -97,9 +96,11 @@ export class AnchorMenu extends AntimodeMenu { @computed get highlighter() { const button = - ; const dropdownContent = @@ -117,7 +118,9 @@ export class AnchorMenu extends AntimodeMenu {
; return ( {"Click to Highlight"}
}> - +
+ +
); } -- cgit v1.2.3-70-g09d2 From 9d177851ecaaea1a89ac9b7de1cec16368603eaa Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 9 Sep 2021 22:49:13 -0400 Subject: added SelectionManager.Docs() to avoid having to dereference props to get at the seelcted Doc. this was causing a cycle in menu items when selected. fixed sizing of filterBox. enabled showing titles for VID,COL,and IMG in addition to RTF. --- src/client/util/CurrentUserUtils.ts | 2 +- src/client/util/HypothesisUtils.ts | 2 +- src/client/util/SelectionManager.ts | 12 ++-- src/client/views/GlobalKeyHandler.ts | 4 +- src/client/views/PropertiesView.tsx | 2 +- src/client/views/StyleProvider.tsx | 2 +- src/client/views/collections/CollectionMenu.tsx | 21 +++---- src/client/views/collections/CollectionSubView.tsx | 8 +-- .../collectionLinear/CollectionLinearView.tsx | 19 +++--- src/client/views/nodes/DocumentView.tsx | 5 +- src/client/views/nodes/FilterBox.tsx | 11 ++-- src/client/views/nodes/button/FontIconBox.tsx | 68 ++++++++++------------ .../views/nodes/formattedText/RichTextMenu.tsx | 20 +++---- 13 files changed, 81 insertions(+), 95 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 8435825c9..60bb375c8 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -1616,7 +1616,7 @@ Scripting.addGlobal(function dynamicOffScreenDocs(dashboard: Doc) { return []; }); Scripting.addGlobal(function selectedDocumentType(docType?: DocumentType, colType?: CollectionViewType, checkParent?: boolean) { - let selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined; + let selected = SelectionManager.Docs().length ? SelectionManager.Docs()[0] : undefined; if (selected && checkParent) { const parentDoc: Doc = Cast(selected.context, Doc, null); selected = parentDoc; diff --git a/src/client/util/HypothesisUtils.ts b/src/client/util/HypothesisUtils.ts index 635673025..e910a9118 100644 --- a/src/client/util/HypothesisUtils.ts +++ b/src/client/util/HypothesisUtils.ts @@ -29,7 +29,7 @@ export namespace Hypothesis { * Search for a WebDocument whose url field matches the given uri, return undefined if not found */ export const findWebDoc = async (uri: string) => { - const currentDoc = SelectionManager.Views().length && SelectionManager.Views()[0].props.Document; + const currentDoc = SelectionManager.Docs().lastElement(); if (currentDoc && Cast(currentDoc.data, WebField)?.url.href === uri) return currentDoc; // always check first whether the currently selected doc is the annotation's source, only use Search otherwise const results: Doc[] = []; diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 0cfaebbf2..bac13373c 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -11,7 +11,7 @@ export namespace SelectionManager { class Manager { @observable IsDragging: boolean = false; - SelectedViews: ObservableMap = new ObservableMap(); + SelectedViews: ObservableMap = new ObservableMap(); @observable SelectedSchemaDocument: Doc | undefined; @observable SelectedSchemaCollection: CollectionSchemaView | undefined; @@ -28,19 +28,18 @@ export namespace SelectionManager { this.DeselectAll(); } - manager.SelectedViews.set(docView, true); + manager.SelectedViews.set(docView, docView.rootDoc); docView.props.whenChildContentsActiveChanged(true); } else if (!ctrlPressed && Array.from(manager.SelectedViews.entries()).length > 1) { Array.from(manager.SelectedViews.keys()).map(dv => dv !== docView && dv.props.whenChildContentsActiveChanged(false)); manager.SelectedSchemaDocument = undefined; manager.SelectedSchemaCollection = undefined; manager.SelectedViews.clear(); - manager.SelectedViews.set(docView, true); + manager.SelectedViews.set(docView, docView.rootDoc); } } @action DeselectView(docView: DocumentView): void { - if (manager.SelectedViews.get(docView)) { manager.SelectedViews.delete(docView); docView.props.whenChildContentsActiveChanged(false); @@ -92,7 +91,7 @@ export namespace SelectionManager { } export function Views(): Array { - return Array.from(manager.SelectedViews.keys()).filter(dv => dv.props.Document._viewType !== CollectionViewType.Docking); + return Array.from(manager.SelectedViews.keys()).filter(dv => manager.SelectedViews.get(dv)?._viewType !== CollectionViewType.Docking); } export function SelectedSchemaDoc(): Doc | undefined { return manager.SelectedSchemaDocument; @@ -100,4 +99,7 @@ export namespace SelectionManager { export function SelectedSchemaCollection(): CollectionSchemaView | undefined { return manager.SelectedSchemaCollection; } + export function Docs(): Doc[] { + return Array.from(manager.SelectedViews.values()).filter(doc => doc?._viewType !== CollectionViewType.Docking); + } } \ No newline at end of file diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 0127d3080..f66c9c788 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -229,8 +229,8 @@ export class KeyManager { } break; case "o": - const target = SelectionManager.Views()[0]; - target && CollectionDockingView.OpenFullScreen(target.props.Document); + const target = SelectionManager.Docs().lastElement(); + target && CollectionDockingView.OpenFullScreen(target); break; case "r": preventDefault = false; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 09e12443b..ab9022a84 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -366,7 +366,7 @@ export class PropertiesView extends React.Component { return {"Show more permissions"}
}>
{ if (this.selectedDocumentView || this.selectedDoc) { - SharingManager.Instance.open(this.selectedDocumentView?.props.Document === this.selectedDocumentView ? this.selectedDocumentView : undefined, this.selectedDoc); + SharingManager.Instance.open(this.selectedDocumentView?.props.Document === this.selectedDoc ? this.selectedDocumentView : undefined, this.selectedDoc); } }}> diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 3413179ed..3c88a4830 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -96,7 +96,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt { componentDidMount() { reaction(() => SelectionManager.Views().length && SelectionManager.Views()[0], - (doc) => doc && this.SetSelection(doc)); + view => view && this.SetSelection(view)); } @action @@ -441,10 +441,8 @@ export class CollectionViewBaseChrome extends React.Component); } - @computed get selectedDocumentView() { - return SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; - } - @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; } + @computed get selectedDocumentView() { return SelectionManager.Views().lastElement(); } + @computed get selectedDoc() { return SelectionManager.Docs().lastElement(); } @computed get notACollection() { if (this.selectedDoc) { const layoutField = Doc.LayoutField(this.selectedDoc); @@ -552,8 +550,8 @@ export class CollectionViewBaseChrome extends React.Component { const contentDiv = this.selectedDocumentView?.ContentDiv; - if (contentDiv) { - const dragData = new DragManager.DocumentDragData([this.selectedDocumentView!.props.Document]); + if (contentDiv && this.selectedDoc) { + const dragData = new DragManager.DocumentDragData([this.selectedDoc]); const offset = [e.clientX - contentDiv.getBoundingClientRect().x, e.clientY - contentDiv.getBoundingClientRect().y]; dragData.defaultDropAction = "alias"; dragData.canEmbed = true; @@ -648,11 +646,9 @@ export class CollectionFreeFormViewChrome extends React.Component; } - @observable viewType = this.selectedDoc?._viewType; render() { return !this.props.docView.layoutDoc ? (null) : diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index b70df93da..06d20f015 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -321,12 +321,8 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: } }); } else { - let srcUrl: string | undefined; - let srcWeb: Doc | undefined; - if (SelectionManager.Views().length) { - srcWeb = SelectionManager.Views()[0].props.Document; - srcUrl = (srcWeb.data as WebField).url?.href?.match(/http[s]?:\/\/[^/]*/)?.[0]; - } + const srcWeb = SelectionManager.Docs().lastElement(); + const srcUrl = (srcWeb?.data as WebField).url?.href?.match(/http[s]?:\/\/[^/]*/)?.[0]; const reg = new RegExp(Utils.prepend(""), "g"); const modHtml = srcUrl ? html.replace(reg, srcUrl) : html; const htmlDoc = Docs.Create.HtmlDocument(modHtml, { ...options, title: "-web page-", _width: 300, _height: 300 }); diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx index fae92e076..7fe95fef0 100644 --- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx +++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx @@ -1,24 +1,24 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@material-ui/core'; -import { action, IReactionDisposer, observable, reaction, runInAction, trace } from 'mobx'; +import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Doc, HeightSym, WidthSym, Opt } from '../../../../fields/Doc'; +import { Doc, HeightSym, Opt, WidthSym } from '../../../../fields/Doc'; import { documentSchema } from '../../../../fields/documentSchemas'; import { Id } from '../../../../fields/FieldSymbols'; import { makeInterface } from '../../../../fields/Schema'; import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, Utils } from '../../../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnTrue, Utils } from '../../../../Utils'; import { DragManager } from '../../../util/DragManager'; import { Transform } from '../../../util/Transform'; +import { Colors, Shadows } from '../../global/globalEnums'; import { DocumentLinksButton } from '../../nodes/DocumentLinksButton'; import { DocumentView } from '../../nodes/DocumentView'; import { LinkDescriptionPopup } from '../../nodes/LinkDescriptionPopup'; import { StyleProp } from '../../StyleProvider'; -import "./CollectionLinearView.scss"; import { CollectionSubView } from '../CollectionSubView'; import { CollectionViewType } from '../CollectionView'; -import { Colors, Shadows } from '../../global/globalEnums'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import "./CollectionLinearView.scss"; type LinearDocument = makeInterface<[typeof documentSchema,]>; @@ -115,9 +115,9 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { } - getDisplayDoc(doc: Doc) { + getDisplayDoc = (doc: Doc) => { const nested = doc._viewType === CollectionViewType.Linear; - const hidden = doc.hidden === true;; + const hidden = doc.hidden === true; let dref: Opt; const docXf = () => this.getTransform(dref); @@ -142,8 +142,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { pinToPres={emptyFunction} rootSelected={this.props.isSelected} removeDocument={this.props.removeDocument} - // ScreenToLocalTransform={docXf} // bcz: Ugh -- this is what we want, but it breaks things when right-clicking on linear view item since docXf is not a constant value across invalidations - ScreenToLocalTransform={this.props.ScreenToLocalTransform} + ScreenToLocalTransform={docXf} PanelWidth={nested ? doc[WidthSym] : this.dimension} PanelHeight={nested ? doc[HeightSym] : this.dimension} renderDepth={this.props.renderDepth + 1} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 6f97cdbd8..8b19fb204 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -649,7 +649,7 @@ export class DocumentViewInternal extends DocComponent
; const targetDoc = (showTitle?.startsWith("_") ? this.layoutDoc : this.rootDoc); - const background = StrCast(SharingManager.Instance.users.find(users => users.user.email === this.dataDoc.author)?.sharingDoc.userColor, this.rootDoc.type === DocumentType.RTF ? StrCast(Doc.SharingDoc().userColor) : "rgba(0,0,0,0.4)"); + const background = StrCast(SharingManager.Instance.users.find(users => users.user.email === this.dataDoc.author)?.sharingDoc.userColor, [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().userColor) : "rgba(0,0,0,0.4)"); const titleView = !showTitle ? (null) :
{ - this.layoutDoc._height = hgt + 140; // 50? need to add all the border sizes together. + this.layoutDoc._height = NumCast(this.layoutDoc._autoHeightMargins) + 150; // need to add all the border sizes together. } /** diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index 4475cf347..df7c54f67 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -248,14 +248,15 @@ export class FontIconBox extends DocComponent(Fon let noneSelected: boolean = false; if (script === 'setView') { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; - if (selected && StrCast(selected.Document.type) === DocumentType.COL) { - text = StrCast(selected.Document._viewType); - } else if (selected) { - dropdown = false; - text = StrCast(selected.Document.type); - if (text === DocumentType.RTF) text = "Text"; - icon = Doc.toIcon(selected.Document); + const selected = SelectionManager.Docs().lastElement(); + if (selected) { + if (StrCast(selected.type) === DocumentType.COL) { + text = StrCast(selected._viewType); + } else { + dropdown = false; + text = selected.type === DocumentType.RTF ? "Text" : StrCast(selected.type); + icon = Doc.toIcon(selected); + } } else { dropdown = false; icon = "globe-asia"; @@ -263,13 +264,8 @@ export class FontIconBox extends DocComponent(Fon } noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking]; } else if (script === 'setFont') { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; - if (selected && StrCast(selected.Document.type) === DocumentType.RTF) { - text = StrCast(selected.Document._fontFamily); - } else { - const fontFamily = StrCast(Doc.UserDoc()._fontFamily); - text = fontFamily; - } + const selected = SelectionManager.Docs().lastElement(); + text = StrCast((selected?.type === DocumentType.RTF ? selected : Doc.UserDoc())._fontFamily); noviceList = ["Roboto", "Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]; } @@ -584,13 +580,13 @@ export class FontIconBox extends DocComponent(Fon // toggle: Set overlay status of selected document Scripting.addGlobal(function setView(view: string) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; - selected ? selected.Document._viewType = view : console.log("[FontIconBox.tsx] changeView failed"); + const selected = SelectionManager.Docs().lastElement(); + selected ? selected._viewType = view : console.log("[FontIconBox.tsx] changeView failed"); }); // toggle: Set overlay status of selected document Scripting.addGlobal(function setBackgroundColor(color?: string, checkResult?: boolean) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined; + const selected = SelectionManager.Docs().lastElement(); if (checkResult) { if (selected) { console.log("[Background] (selected): " + StrCast(selected._backgroundColor)); @@ -635,7 +631,7 @@ Scripting.addGlobal(function toggleOverlay(checkResult?: boolean) { // toggle: Set overlay status of selected document Scripting.addGlobal(function setFont(font: string, checkResult?: boolean) { - SelectionManager.Views().map(dv => dv.props.Document._fontFamily = font); + SelectionManager.Docs().map(doc => doc._fontFamily = font); const editorView = RichTextMenu.Instance.TextView?.EditorView; editorView?.state && RichTextMenu.Instance.setFontFamily(font, editorView); Doc.UserDoc()._fontFamily = font; @@ -665,7 +661,7 @@ Scripting.addGlobal(function setAlignment(align: "left" | "right" | "center", ch if (active === align) return Colors.MEDIUM_BLUE; else return "transparent"; } - SelectionManager.Views().map(dv => dv.props.Document.textAlign = align); + SelectionManager.Docs().map(doc => doc.textAlign = align); switch (align) { case "left": editorView?.state && RichTextMenu.Instance.alignLeft(editorView, editorView.dispatch); @@ -703,13 +699,13 @@ Scripting.addGlobal(function setBulletList(mapStyle: "bullet" | "decimal", check // toggle: Set overlay status of selected document Scripting.addGlobal(function setFontColor(color?: string, checkResult?: boolean) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; + const selected = SelectionManager.Docs().lastElement(); const editorView = RichTextMenu.Instance.TextView?.EditorView; if (checkResult) { if (selected) { - console.log("[Font color] (selected): " + StrCast(selected.rootDoc._fontColor)); - return selected.rootDoc._fontColor; + console.log("[Font color] (selected): " + StrCast(selected._fontColor)); + return selected._fontColor; } else { console.log("[Font color] (global): " + StrCast(Doc.UserDoc()._fontColor)); return Doc.UserDoc()._fontColor; @@ -717,7 +713,7 @@ Scripting.addGlobal(function setFontColor(color?: string, checkResult?: boolean) } if (selected) { - selected.rootDoc._fontColor = color; + selected._fontColor = color; if (color) { editorView?.state && RichTextMenu.Instance.setColor(color, editorView, editorView?.dispatch); } @@ -727,18 +723,18 @@ Scripting.addGlobal(function setFontColor(color?: string, checkResult?: boolean) // toggle: Set overlay status of selected document Scripting.addGlobal(function setFontHighlight(color?: string, checkResult?: boolean) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; + const selected = SelectionManager.Docs().lastElement(); const editorView = RichTextMenu.Instance.TextView?.EditorView; if (checkResult) { if (selected) { - return selected.Document._fontHighlight; + return selected._fontHighlight; } else { return Doc.UserDoc()._fontHighlight; } } if (selected) { - selected.rootDoc._fontColor = color; + selected._fontColor = color; if (color) { editorView?.state && RichTextMenu.Instance.setHighlight(color, editorView, editorView?.dispatch); } @@ -769,7 +765,7 @@ Scripting.addGlobal(function toggleBold(checkResult?: boolean) { console.log("editorView"); editorView?.state && RichTextMenu.Instance.toggleBold(editorView, true); } - SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.RTF).map(dv => dv.props.Document.bold = !dv.props.Document.bold); + SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.RTF).map(doc => doc.bold = !doc.bold); Doc.UserDoc().bold = !Doc.UserDoc().bold; return Doc.UserDoc().bold; }); @@ -784,7 +780,7 @@ Scripting.addGlobal(function toggleUnderline(checkResult?: boolean) { console.log("editorView"); editorView?.state && RichTextMenu.Instance.toggleUnderline(editorView, true); } - SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.RTF).map(dv => dv.props.Document.underline = !dv.props.Document.underline); + SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.RTF).map(doc => doc.underline = !doc.underline); Doc.UserDoc().underline = !Doc.UserDoc().underline; return Doc.UserDoc().underline; }); @@ -799,7 +795,7 @@ Scripting.addGlobal(function toggleItalic(checkResult?: boolean) { console.log("editorView"); editorView?.state && RichTextMenu.Instance.toggleItalic(editorView, true); } - SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.RTF).map(dv => dv.props.Document.italic = !dv.props.Document.italic); + SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.RTF).map(doc => doc.italic = !doc.italic); Doc.UserDoc().italic = !Doc.UserDoc().italic; return Doc.UserDoc().italic; }); @@ -841,7 +837,7 @@ Scripting.addGlobal(function setActiveInkTool(tool: string, checkResult?: boolea Scripting.addGlobal(function setStrokeWidth(width: number, checkResult?: boolean) { if (checkResult) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined; + const selected = SelectionManager.Docs().lastElement(); if (selected && selected.type === DocumentType.INK) { return Number(selected.strokeWidth); } else { @@ -850,13 +846,13 @@ Scripting.addGlobal(function setStrokeWidth(width: number, checkResult?: boolean } } Doc.UserDoc().activeInkWidth = width; - SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.strokeWidth = Number(width)); + SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.INK).map(doc => doc.strokeWidth = Number(width)); }); // toggle: Set overlay status of selected document Scripting.addGlobal(function setStrokeColor(color?: string, checkResult?: boolean) { if (checkResult) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined; + const selected = SelectionManager.Docs().lastElement(); if (selected && selected.type === DocumentType.INK) { return selected.color; } else { @@ -865,7 +861,7 @@ Scripting.addGlobal(function setStrokeColor(color?: string, checkResult?: boolea } } SetActiveInkColor(StrCast(color)); - SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.color = String(color)); + SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.INK).map(doc => doc.color = String(color)); }); @@ -873,7 +869,7 @@ Scripting.addGlobal(function setStrokeColor(color?: string, checkResult?: boolea * webSetURL **/ Scripting.addGlobal(function webSetURL(url: string, checkResult?: boolean) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined; + const selected = SelectionManager.Docs().lastElement(); console.log("URL: ", url); if (checkResult && selected && selected.type === DocumentType.WEB) { return Cast(selected.data, WebField, null).url; @@ -888,7 +884,7 @@ Scripting.addGlobal(function webSetURL(url: string, checkResult?: boolean) { * toggleSchemaPreview **/ Scripting.addGlobal(function toggleSchemaPreview(checkResult?: boolean) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined; + const selected = SelectionManager.Docs().lastElement(); console.log(selected && selected.title); if (checkResult && selected) { const result: boolean = NumCast(selected.schemaPreviewWidth) > 0; diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 3d9d9543d..3919fbf94 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -279,33 +279,33 @@ export class RichTextMenu extends AntimodeMenu { }); } - toggleBold = (view: EditorView, forceBool?:boolean) => { - const mark = view.state.schema.mark(view.state.schema.marks.strong, {strong: forceBool}); + toggleBold = (view: EditorView, forceBool?: boolean) => { + const mark = view.state.schema.mark(view.state.schema.marks.strong, { strong: forceBool }); this.setMark(mark, view.state, view.dispatch, false); view.focus(); } - toggleUnderline = (view: EditorView, forceBool?:boolean) => { - const mark = view.state.schema.mark(view.state.schema.marks.underline, {underline: forceBool}); + toggleUnderline = (view: EditorView, forceBool?: boolean) => { + const mark = view.state.schema.mark(view.state.schema.marks.underline, { underline: forceBool }); this.setMark(mark, view.state, view.dispatch, false); view.focus(); } - toggleItalic = (view: EditorView, forceBool?:boolean) => { - const mark = view.state.schema.mark(view.state.schema.marks.em, {em: forceBool}); + toggleItalic = (view: EditorView, forceBool?: boolean) => { + const mark = view.state.schema.mark(view.state.schema.marks.em, { em: forceBool }); this.setMark(mark, view.state, view.dispatch, false); view.focus(); } - setFontSize = (size:number, view: EditorView) => { + setFontSize = (size: number, view: EditorView) => { const fmark = view.state.schema.marks.pFontSize.create({ fontSize: size }); this.setMark(fmark, view.state, (tx: any) => view.dispatch(tx.addStoredMark(fmark)), true); view.focus(); this.updateMenu(view, undefined, this.props); } - setFontFamily = (family:string, view: EditorView) => { + setFontFamily = (family: string, view: EditorView) => { const fmark = view.state.schema.marks.pFontFamily.create({ family: family }); this.setMark(fmark, view.state, (tx: any) => view.dispatch(tx.addStoredMark(fmark)), true); view.focus(); @@ -516,7 +516,7 @@ export class RichTextMenu extends AntimodeMenu { get TextView() { return (this.view as any)?.TextView as FormattedTextBox; } get TextViewFieldKey() { return this.TextView?.props.fieldKey; } - + @action setActiveHighlight(color: string) { this.activeHighlightColor = color; } @@ -566,7 +566,7 @@ export class RichTextMenu extends AntimodeMenu { if (linkDoc instanceof Doc) { const anchor1 = await Cast(linkDoc.anchor1, Doc); const anchor2 = await Cast(linkDoc.anchor2, Doc); - const currentDoc = SelectionManager.Views().length && SelectionManager.Views()[0].props.Document; + const currentDoc = SelectionManager.Docs().lastElement(); if (currentDoc && anchor1 && anchor2) { if (Doc.AreProtosEqual(currentDoc, anchor1)) { return StrCast(anchor2.title); -- cgit v1.2.3-70-g09d2