aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes')
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx3
-rw-r--r--src/client/views/nodes/DocumentView.tsx66
-rw-r--r--src/client/views/nodes/FilterBox.tsx11
-rw-r--r--src/client/views/nodes/LinkAnchorBox.tsx1
-rw-r--r--src/client/views/nodes/PDFBox.tsx20
-rw-r--r--src/client/views/nodes/WebBox.tsx14
-rw-r--r--src/client/views/nodes/button/FontIconBox.tsx92
-rw-r--r--src/client/views/nodes/button/textButton/TextButton.tsx2
-rw-r--r--src/client/views/nodes/button/textButton/index.ts2
-rw-r--r--src/client/views/nodes/button/toggleButton/index.ts2
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx2
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.scss17
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx63
-rw-r--r--src/client/views/nodes/formattedText/RichTextMenu.scss1
-rw-r--r--src/client/views/nodes/formattedText/RichTextMenu.tsx20
15 files changed, 181 insertions, 135 deletions
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<DocumentViewProps & Fo
if (splits.length > 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 ebd0211e2..d88f1b9a4 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';
@@ -115,6 +115,7 @@ export interface DocumentViewSharedProps {
docFilters: () => 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;
@@ -649,7 +650,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
if (e && this.rootDoc._hideContextMenu && Doc.UserDoc().noviceMode) {
e.preventDefault();
e.stopPropagation();
- !this.props.isSelected(true) && SelectionManager.SelectView(this.props.DocumentView(), false);
+ //!this.props.isSelected(true) && SelectionManager.SelectView(this.props.DocumentView(), false);
}
// the touch onContextMenu is button 0, the pointer onContextMenu is button 2
if (e) {
@@ -704,13 +705,15 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
const zorders = cm.findByDescription("ZOrder...");
const zorderItems: ContextMenuProps[] = zorders && "subitems" in zorders ? zorders.subitems : [];
- 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" });
+ 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" });
- onClicks.push({ description: "Toggle Detail", event: this.setToggleDetail, icon: "concierge-bell" });
+ !Doc.UserDoc().noviceMode && onClicks.push({ description: "Toggle Detail", event: this.setToggleDetail, icon: "concierge-bell" });
onClicks.push({ description: (this.Document.followLinkZoom ? "Don't" : "") + " zoom following link", event: () => this.Document.followLinkZoom = !this.Document.followLinkZoom, icon: this.Document.ignoreClick ? "unlock" : "lock" });
if (!this.Document.annotationOn) {
@@ -848,16 +851,28 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
default: return this.props.styleProvider?.(doc, props, property);
}
}
- @computed get directLinks() { TraceMobx(); return LinkManager.Instance.getAllDirectLinks(this.rootDoc); }
+ // We need to use allrelatedLinks to get not just links to the document as a whole, but links to
+ // anchors that are not rendered as DocumentViews (marked as 'unrendered' with their 'annotationOn' set to this document). e.g.,
+ // - PDF text regions are rendered as an Annotations without generating a DocumentView, '
+ // - RTF selections are rendered via Prosemirror and have a mark which contains the Document ID for the annotation link
+ // - and links to PDF/Web docs at a certain scroll location never create an explicit view.
+ // For each of these, we create LinkAnchorBox's on the border of the DocumentView.
+ @computed get directLinks() {
+ TraceMobx(); return LinkManager.Instance.getAllRelatedLinks(this.rootDoc).filter(link =>
+ 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) =>
- <div className="documentView-anchorCont" key={i + 1}>
+ <div className="documentView-anchorCont" key={link[Id]}>
<DocumentView {...this.props}
Document={link}
PanelWidth={this.anchorPanelWidth}
@@ -938,22 +953,41 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
hideOnLeave={true}
styleProvider={this.captionStyleProvider}
dontRegisterView={true}
+ isContentActive={this.isContentActive}
onClick={this.onClickFunc}
/>
</div>;
+ const targetDoc = (showTitle?.startsWith("_") ? this.layoutDoc : this.rootDoc);
+ 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) :
<div className={`documentView-titleWrapper${showTitleHover ? "-hover" : ""}`} key="title" style={{
position: this.headerMargin ? "relative" : "absolute",
height: this.titleHeight,
- 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)"),
+ color: lightOrDark(background),
+ background,
pointerEvents: this.onClickHandler || this.Document.ignoreClick ? "none" : undefined,
}}>
<EditableView ref={this._titleRef}
- contents={showTitle === "title" ? StrCast((this.dataDoc || this.props.Document).title) : showTitle.split(";").map(field => 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(input => {
+ if (input?.startsWith("#")) {
+ if (this.props.showTitle) {
+ this.rootDoc._showTitle = input?.substring(1) ? input.substring(1) : undefined;
+ } else {
+ 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;
+ })}
/>
</div>;
return this.props.hideTitle || (!showTitle && !showCaption) ?
@@ -1155,7 +1189,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
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/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index 7ad03e055..e9f19bf9e 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -9,7 +9,7 @@ import { List } from "../../../fields/List";
import { RichTextField } from "../../../fields/RichTextField";
import { listSpec, makeInterface } from "../../../fields/Schema";
import { ComputedField, ScriptField } from "../../../fields/ScriptField";
-import { Cast, StrCast } from "../../../fields/Types";
+import { Cast, StrCast, NumCast } from "../../../fields/Types";
import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from "../../../Utils";
import { Docs } from "../../documents/Documents";
import { DocumentType } from "../../documents/DocumentTypes";
@@ -79,7 +79,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
* @returns the relevant doc according to the value of FilterBox._filterScope i.e. either the Current Dashboard or the Current Collection
*/
@computed static get targetDoc() {
- return SelectionManager.Views().length ? SelectionManager.Views()[0].Document : CurrentUserUtils.ActiveDashboard;
+ return SelectionManager.Docs().length ? SelectionManager.Docs()[0] : CurrentUserUtils.ActiveDashboard;
}
@computed static get targetDocChildKey() {
if (SelectionManager.Views().length) {
@@ -88,10 +88,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
return "data";
}
@computed static get targetDocChildren() {
- if (SelectionManager.Views().length) {
- return DocListCast(FilterBox.targetDoc[FilterBox.targetDocChildKey]);
- }
- return DocListCast(CurrentUserUtils.ActiveDashboard.data);
+ return DocListCast(FilterBox.targetDoc?.[FilterBox.targetDocChildKey] || CurrentUserUtils.ActiveDashboard.data);
}
@observable _loaded = false;
@@ -347,7 +344,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
);
}
setTreeHeight = (hgt: number) => {
- 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/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index 8f9959693..1e0172d24 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -3,7 +3,6 @@ import { action, observable } from "mobx";
import { observer } from "mobx-react";
import { Doc } from "../../../fields/Doc";
import { documentSchema } from "../../../fields/documentSchemas";
-import { Id } from "../../../fields/FieldSymbols";
import { makeInterface } from "../../../fields/Schema";
import { Cast, NumCast, StrCast } from "../../../fields/Types";
import { TraceMobx } from "../../../fields/util";
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 3a399bfdb..9706d73c7 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -3,13 +3,13 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction
import { observer } from "mobx-react";
import * as Pdfjs from "pdfjs-dist";
import "pdfjs-dist/web/pdf_viewer.css";
-import { Doc, Opt, WidthSym, DocListCast } from "../../../fields/Doc";
+import { Doc, DocListCast, Opt, WidthSym } from "../../../fields/Doc";
import { documentSchema } from '../../../fields/documentSchemas';
import { makeInterface } from "../../../fields/Schema";
-import { Cast, NumCast, StrCast, BoolCast } from '../../../fields/Types';
+import { Cast, NumCast, StrCast } from '../../../fields/Types';
import { PdfField } from "../../../fields/URLField";
import { TraceMobx } from '../../../fields/util';
-import { Utils, setupMoveUpEvents, emptyFunction, returnOne } from '../../../Utils';
+import { emptyFunction, returnOne, setupMoveUpEvents, Utils } from '../../../Utils';
import { Docs } from '../../documents/Documents';
import { KeyCodes } from '../../util/KeyCodes';
import { undoBatch } from '../../util/UndoManager';
@@ -17,14 +17,14 @@ import { panZoomSchema } from '../collections/collectionFreeForm/CollectionFreeF
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from "../DocComponent";
+import { Colors } from '../global/globalEnums';
+import { AnchorMenu } from '../pdf/AnchorMenu';
import { PDFViewer } from "../pdf/PDFViewer";
import { SidebarAnnos } from '../SidebarAnnos';
import { FieldView, FieldViewProps } from './FieldView';
import { pageSchema } from "./ImageBox";
import "./PDFBox.scss";
import React = require("react");
-import { AnchorMenu } from '../pdf/AnchorMenu';
-import { Colors } from '../global/globalEnums';
type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>;
const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema);
@@ -79,9 +79,9 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
const anchor =
AnchorMenu.Instance?.GetAnchor() ??
Docs.Create.TextanchorDocument({
- title: StrCast(this.rootDoc.title + " " + this.layoutDoc._scrollTop),
- annotationOn: this.rootDoc,
+ title: StrCast(this.rootDoc.title + "@" + this.layoutDoc._scrollTop?.toFixed(0)),
y: NumCast(this.layoutDoc._scrollTop),
+ unrendered: true
});
this.addDocument(anchor);
return anchor;
@@ -210,13 +210,13 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
{this._pageControls ? pageBtns : (null)}
</div>
<div className="pdfBox-sidebarBtn" key="sidebar" title="Toggle Sidebar"
- style={{
- display: !this.props.isContentActive() ? "none" : undefined,
+ style={{
+ display: !this.props.isContentActive() ? "none" : undefined,
top: StrCast(this.rootDoc._showTitle) === "title" ? 20 : 5,
backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK
}}
onPointerDown={this.sidebarBtnDown} >
- <FontAwesomeIcon style={{ color: Colors.WHITE }} icon={"comment-alt"} size="sm" />
+ <FontAwesomeIcon style={{ color: Colors.WHITE }} icon={"comment-alt"} size="sm" />
</div>
</div>;
}
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 1f85219d6..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");
@@ -187,8 +187,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
AnchorMenu.Instance?.GetAnchor(this._savedAnnotations) ??
Docs.Create.WebanchorDocument(this._url, {
title: StrCast(this.rootDoc.title + " " + this.layoutDoc._scrollTop),
- annotationOn: this.rootDoc,
- y: NumCast(this.layoutDoc._scrollTop)
+ y: NumCast(this.layoutDoc._scrollTop),
+ unrendered: true
});
this.addDocumentWrapper(anchor);
return anchor;
@@ -592,13 +592,13 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
removeDocument={this.removeDocument}
/>
<div className="webBox-overlayButton-sidebar" key="sidebar" title="Toggle Sidebar"
- style={{
- display: !this.props.isContentActive() ? "none" : undefined,
+ style={{
+ display: !this.props.isContentActive() ? "none" : undefined,
top: StrCast(this.rootDoc._showTitle) === "title" ? 20 : 5,
backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK
}}
onPointerDown={this.sidebarBtnDown} >
- <FontAwesomeIcon style={{ color: Colors.WHITE }} icon={"comment-alt"} size="sm" />
+ <FontAwesomeIcon style={{ color: Colors.WHITE }} icon={"comment-alt"} size="sm" />
</div>
</div>);
}
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index b72f31ef8..df7c54f67 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",
});
@@ -247,14 +248,15 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(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";
@@ -262,13 +264,8 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(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"];
}
@@ -303,7 +300,7 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
<div className={`menuButton ${this.type} ${active}`}
style={{ backgroundColor: this.rootDoc.dropDownOpen ? Colors.MEDIUM_BLUE : backgroundColor, color: color, display: dropdown ? undefined : "flex" }}
onClick={dropdown ? () => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen : undefined}>
- {dropdown || noneSelected ? (null) : <FontAwesomeIcon style={{marginLeft: 5}} className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />}
+ {dropdown || noneSelected ? (null) : <FontAwesomeIcon style={{ marginLeft: 5 }} className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />}
<div className="menuButton-dropdown-header">
{text && text[0].toUpperCase() + text.slice(1)}
</div>
@@ -348,7 +345,7 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(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) => <SketchPicker
disableAlpha={!stroke}
@@ -369,7 +366,7 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(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 +490,7 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
{this.label}
</div>;
- const buttonProps:IButtonProps = {
+ const buttonProps: IButtonProps = {
type: this.type,
rootDoc: this.rootDoc,
label: label,
@@ -512,9 +509,9 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
button = (
<div className={`menuButton ${this.type}`} style={{ color: color, backgroundColor: backgroundColor, opacity: 1, gridAutoColumns: `${NumCast(this.rootDoc._height)} auto` }}>
<FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
- {buttonText ?
+ {buttonText ?
<div className="button-text">
- {buttonText}
+ {buttonText}
</div>
: null}
{label}
@@ -583,13 +580,13 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(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));
@@ -598,12 +595,19 @@ 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;
if (checkResult && selected) {
@@ -627,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;
@@ -657,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);
@@ -695,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;
@@ -709,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);
}
@@ -719,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);
}
@@ -761,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;
});
@@ -776,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;
});
@@ -791,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;
});
@@ -833,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 {
@@ -842,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 {
@@ -857,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));
});
@@ -865,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;
@@ -880,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/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<IButtonProps> {
return (<div className={`menuButton ${this.props.type}`} style={{ opacity: 1, backgroundColor: this.props.backgroundColor, color: this.props.color }}>
<FontAwesomeIcon className={`fontIconBox-icon-${this.props.type}`} icon={this.props.icon} color={this.props.color} />
{this.props.label}
- </div>)
+ </div>);
}
} \ 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/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<IDashFieldViewInterna
// set the display of the field's value (checkbox for booleans, span of text for strings)
@computed get fieldValueContent() {
if (this._dashDoc) {
- const dashVal = this._dashDoc[DataSym][this._fieldKey] ?? this._dashDoc[this._fieldKey] ?? (this._fieldKey === "PARAMS" ? this._textBoxDoc[this._fieldKey] : "");
+ const dashVal = this._dashDoc[this._fieldKey] ?? this._dashDoc[DataSym][this._fieldKey] ?? (this._fieldKey === "PARAMS" ? this._textBoxDoc[this._fieldKey] : "");
const fval = dashVal instanceof List ? dashVal.join(this.multiValueDelimeter) : StrCast(dashVal).startsWith(":=") || dashVal === "" ? Doc.Layout(this._textBoxDoc)[this._fieldKey] : dashVal;
const boolVal = Cast(fval, "boolean", null);
const strVal = Field.toString(fval as Field) || "";
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 59d43f8d7..78de1fd89 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1,6 +1,6 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { isEqual } from "lodash";
-import { action, computed, IReactionDisposer, reaction, runInAction, observable } from "mobx";
+import { action, computed, IReactionDisposer, reaction, runInAction, observable, trace } from "mobx";
import { observer } from "mobx-react";
import { baseKeymap, selectAll } from "prosemirror-commands";
import { history } from "prosemirror-history";
@@ -432,6 +432,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
protected createDropTarget = (ele: HTMLDivElement) => {
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
@@ -713,7 +727,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) => {
@@ -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) })];
}
}
@@ -1360,6 +1372,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
this._undoTyping = undefined;
return wasUndoing;
}
+
@action
onBlur = (e: any) => {
FormattedTextBox.Focused === this && (FormattedTextBox.Focused = undefined);
@@ -1448,18 +1461,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...
+ }
}
}
}
@@ -1486,14 +1496,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) : <div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown}
- style={{
- left: `max(0px, calc(100% - ${this.sidebarWidthPercent} ${"- 30px"}))`,
- backgroundColor: backgroundColor,
- color: color
- }} >
- <FontAwesomeIcon icon={"comment-alt"} />
- </div>;
+ return (!annotated && (!this.props.isContentActive() || SnappingManager.GetIsDragging())) ? (null) :
+ <div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown}
+ style={{
+ left: `max(0px, calc(100% - ${this.sidebarWidthPercent} - 17px))`,
+ backgroundColor: backgroundColor,
+ color: color,
+ opacity: annotated ? 1 : undefined
+ }} >
+ <FontAwesomeIcon icon={"comment-alt"} />
+ </div>;
}
@computed get sidebarCollection() {
const renderComponent = (tag: string) => {
@@ -1555,7 +1567,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const selPad = Math.min(margins, 10);
const padding = Math.max(margins + ((selected && !this.layoutDoc._singleLine) || minimal ? -selPad : 0), 0);
const selPaddingClass = selected && !this.layoutDoc._singleLine && margins >= 10 ? "-selected" : "";
- return (
+ const styleFromString = this.styleFromLayoutString(scale); // this converts any expressions in the format string to style props. e.g., <FormattedTextBox height='{this._headerHeight}px' >
+ return (styleFromString?.height === "0px" ? (null) :
<div className="formattedTextBox-cont"
onWheel={e => 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., <FormattedTextBox height='{this._headerHeight}px' >
+ ...styleFromString
}}>
<div className={`formattedTextBox-cont`} ref={this._ref}
style={{
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.scss b/src/client/views/nodes/formattedText/RichTextMenu.scss
index c94e93541..8afa0f6b5 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.scss
+++ b/src/client/views/nodes/formattedText/RichTextMenu.scss
@@ -2,6 +2,7 @@
.button-dropdown-wrapper {
position: relative;
+ display: flex;
.dropdown-button {
width: 15px;
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<AntimodeMenuProps> {
});
}
- 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<AntimodeMenuProps> {
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<AntimodeMenuProps> {
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);