aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/formattedText/FormattedTextBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/formattedText/FormattedTextBox.tsx')
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx155
1 files changed, 81 insertions, 74 deletions
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index e6cf2da07..a5a40a31f 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -58,7 +58,6 @@ import { FieldView, FieldViewProps } from "../FieldView";
import "./FormattedTextBox.scss";
import { FormattedTextBoxComment, formattedTextBoxCommentPlugin } from './FormattedTextBoxComment';
import React = require("react");
-import requestPromise = require('request-promise');
library.add(faEdit);
library.add(faSmile, faTextHeight, faUpload);
@@ -424,42 +423,66 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
specificContextMenu = (e: React.MouseEvent): void => {
const cm = ContextMenu.Instance;
- const funcs: ContextMenuProps[] = [];
- this.rootDoc.isTemplateDoc && funcs.push({ description: "Make Default Layout", event: async () => Doc.UserDoc().defaultTextLayout = new PrefetchProxy(this.rootDoc), icon: "eye" });
- !this.layoutDoc.isTemplateDoc && funcs.push({
- description: "Convert to use as a style", event: () => {
- this.rootDoc.isTemplateDoc = makeTemplate(this.rootDoc);
- Doc.AddDocToList(Cast(Doc.UserDoc()["template-notes"], Doc, null), "data", this.rootDoc);
- }, icon: "eye"
+ const appearance = ContextMenu.Instance.findByDescription("Appearance...");
+ const appearanceItems = appearance && "subitems" in appearance ? appearance.subitems : [];
+
+ const changeItems: ContextMenuProps[] = [];
+ const noteTypesDoc = Cast(Doc.UserDoc()["template-notes"], Doc, null);
+ DocListCast(noteTypesDoc?.data).forEach(note => {
+ changeItems.push({
+ description: StrCast(note.title), event: undoBatch(() => {
+ Doc.setNativeView(this.rootDoc);
+ DocUtils.makeCustomViewClicked(this.rootDoc, Docs.Create.TreeDocument, StrCast(note.title), note);
+ }), icon: "eye"
+ });
});
- this.layoutDoc.isTemplateDoc && funcs.push({
- description: "Make New Template", event: () => {
- const title = this.rootDoc.title as string;
- this.rootDoc.layout = (this.layoutDoc as Doc).layout as string;
- this.rootDoc.title = this.layoutDoc.isTemplateForField as string;
- this.rootDoc.isTemplateDoc = false;
- this.rootDoc.isTemplateForField = "";
- this.rootDoc.layoutKey = "layout";
- this.rootDoc.isTemplateDoc = makeTemplate(this.rootDoc, true, title);
- setTimeout(() => {
- this.rootDoc._width = this.layoutDoc._width || 300; // the width and height are stored on the template, since we're getting rid of the old template
- this.rootDoc._height = this.layoutDoc._height || 200; // we need to copy them over to the root. This should probably apply to all '_' fields
- this.rootDoc._backgroundColor = Cast(this.layoutDoc._backgroundColor, "string", null);
- }, 10);
+ changeItems.push({ description: "FreeForm", event: () => DocUtils.makeCustomViewClicked(this.rootDoc, Docs.Create.FreeformDocument, "freeform"), icon: "eye" });
+ appearanceItems.push({ description: "Change Perspective...", subitems: changeItems, icon: "external-link-alt" });
+ const uicontrols: ContextMenuProps[] = [];
+ uicontrols.push({ description: "Toggle Sidebar", event: () => this.layoutDoc._showSidebar = !this.layoutDoc._showSidebar, icon: "expand-arrows-alt" });
+ uicontrols.push({ description: "Toggle Dictation Icon", event: () => this.layoutDoc._showAudio = !this.layoutDoc._showAudio, icon: "expand-arrows-alt" });
+ uicontrols.push({ description: "Toggle Menubar", event: () => this.toggleMenubar(), icon: "expand-arrows-alt" });
+ !Doc.UserDoc().noviceMode && uicontrols.push({
+ description: "Broadcast Message", event: () => DocServer.GetRefField("rtfProto").then(proto =>
+ proto instanceof Doc && (proto.BROADCAST_MESSAGE = Cast(this.rootDoc[this.fieldKey], RichTextField)?.Text)), icon: "expand-arrows-alt"
+ });
+
+ appearanceItems.push({ description: "UI Controls...", subitems: uicontrols, icon: "asterisk" });
+ this.rootDoc.isTemplateDoc && appearanceItems.push({ description: "Make Default Layout", event: async () => Doc.UserDoc().defaultTextLayout = new PrefetchProxy(this.rootDoc), icon: "eye" });
+ Doc.UserDoc().defaultTextLayout && appearanceItems.push({ description: "Reset default note style", event: () => Doc.UserDoc().defaultTextLayout = undefined, icon: "eye" });
+ appearanceItems.push({
+ description: "Convert to be a template style", event: () => {
+ if (!this.layoutDoc.isTemplateDoc) {
+ const title = StrCast(this.rootDoc.title);
+ this.rootDoc.title = "text";
+ this.rootDoc.isTemplateDoc = makeTemplate(this.rootDoc, true, title);
+ } else {
+ const title = StrCast(this.rootDoc.title);
+ this.rootDoc.title = "text";
+ this.rootDoc.layout = (this.layoutDoc as Doc).layout as string;
+ this.rootDoc.title = this.layoutDoc.isTemplateForField as string;
+ this.rootDoc.isTemplateDoc = false;
+ this.rootDoc.isTemplateForField = "";
+ this.rootDoc.layoutKey = "layout";
+ this.rootDoc.isTemplateDoc = makeTemplate(this.rootDoc, true, title);
+ setTimeout(() => {
+ this.rootDoc._autoHeight = this.layoutDoc._autoHeight; // autoHeight, width and height
+ this.rootDoc._width = this.layoutDoc._width || 300; // are stored on the template, since we're getting rid of the old template
+ this.rootDoc._height = this.layoutDoc._height || 200; // we need to copy them over to the root. This should probably apply to all '_' fields
+ this.rootDoc._backgroundColor = Cast(this.layoutDoc._backgroundColor, "string", null);
+ }, 10);
+ }
Doc.AddDocToList(Cast(Doc.UserDoc()["template-notes"], Doc, null), "data", this.rootDoc);
}, icon: "eye"
});
+ !appearance && ContextMenu.Instance.addItem({ description: "Appearance...", subitems: appearanceItems, icon: "eye" });
+
+ const funcs: ContextMenuProps[] = [];
+
//funcs.push({ description: `${this.Document._autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight, icon: "plus" });
funcs.push({ description: (!this.layoutDoc._nativeWidth || !this.layoutDoc._nativeHeight ? "Freeze" : "Unfreeze") + " Aspect", event: this.toggleNativeDimensions, icon: "snowflake" });
funcs.push({ description: "Toggle Single Line", event: () => this.layoutDoc._singleLine = !this.layoutDoc._singleLine, icon: "expand-arrows-alt" });
- const uicontrols: ContextMenuProps[] = [];
- uicontrols.push({ description: "Toggle Sidebar", event: () => this.layoutDoc._showSidebar = !this.layoutDoc._showSidebar, icon: "expand-arrows-alt" });
- uicontrols.push({ description: "Toggle Dictation Icon", event: () => this.layoutDoc._showAudio = !this.layoutDoc._showAudio, icon: "expand-arrows-alt" });
- uicontrols.push({ description: "Toggle Menubar", event: () => this.toggleMenubar(), icon: "expand-arrows-alt" });
-
- funcs.push({ description: "UI Controls...", subitems: uicontrols, icon: "asterisk" });
-
const highlighting: ContextMenuProps[] = [];
["My Text", "Text from Others", "Todo Items", "Important Items", "Ignore Items", "Disagree Items", "By Recent Minute", "By Recent Hour"].forEach(option =>
highlighting.push({
@@ -476,21 +499,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
funcs.push({ description: "highlighting...", subitems: highlighting, icon: "hand-point-right" });
ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" });
-
- const change = cm.findByDescription("Change Perspective...");
- const changeItems: ContextMenuProps[] = change && "subitems" in change ? change.subitems : [];
-
- const noteTypesDoc = Cast(Doc.UserDoc()["template-notes"], Doc, null);
- DocListCast(noteTypesDoc?.data).forEach(note => {
- changeItems.push({
- description: StrCast(note.title), event: undoBatch(() => {
- Doc.setNativeView(this.rootDoc);
- DocUtils.makeCustomViewClicked(this.rootDoc, Docs.Create.TreeDocument, StrCast(note.title), note);
- }), icon: "eye"
- });
- });
- changeItems.push({ description: "FreeForm", event: () => DocUtils.makeCustomViewClicked(this.rootDoc, Docs.Create.FreeformDocument, "freeform"), icon: "eye" });
- !change && cm.addItem({ description: "Change Perspective...", subitems: changeItems, icon: "external-link-alt" });
this._downX = this._downY = Number.NaN;
}
@@ -592,10 +600,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
};
}
- makeLinkToSelection(linkId: string, title: string, location: string, targetId: string) {
+ makeLinkToSelection(linkId: string, title: string, location: string, targetId: string, targetHref?: string) {
const state = this._editorView?.state;
if (state) {
- const href = Utils.prepend("/doc/" + linkId);
+ const href = targetHref ?? Utils.prepend("/doc/" + linkId);
const sel = state.selection;
const splitter = state.schema.marks.splitter.create({ id: Utils.GenerateGuid() });
let tr = state.tr.addMark(sel.from, sel.to, splitter);
@@ -603,7 +611,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
if (node.firstChild === null && node.marks.find((m: Mark) => m.type.name === schema.marks.splitter.name)) {
const allHrefs = [{ href, title, targetId, linkId }];
allHrefs.push(...(node.marks.find((m: Mark) => m.type.name === schema.marks.link.name)?.attrs.allHrefs ?? []));
- const link = state.schema.marks.link.create({ href, allHrefs, title, location, linkId, targetId });
+ const link = state.schema.marks.link.create({ allHrefs, title, location, linkId });
tr = tr.addMark(pos, pos + node.nodeSize, link);
}
});
@@ -930,6 +938,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const { state: { tr }, dispatch } = this._editorView;
dispatch(tr.insertText(startupText));
}
+ (this._editorView as any).TextView = this;
}
const selectOnLoad = this.rootDoc[Id] === FormattedTextBox.SelectOnLoad;
@@ -1033,6 +1042,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
if (bounds && this.layoutDoc._chromeStatus !== "disabled") {
const x = Math.min(Math.max(bounds.left, 0), window.innerWidth - RichTextMenu.Instance.width);
let y = Math.min(Math.max(0, bounds.top - RichTextMenu.Instance.height - 50), window.innerHeight - RichTextMenu.Instance.height);
+ console.log("y = " + y + " hgt = " + RichTextMenu.Instance.height + " cords = " + coords.top);
if (coords && coords.left > x && coords.left < x + RichTextMenu.Instance.width && coords.top > y && coords.top < y + RichTextMenu.Instance.height + 50) {
y = Math.min(bounds.bottom, window.innerHeight - RichTextMenu.Instance.height);
}
@@ -1067,12 +1077,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
if ((e.nativeEvent as any).formattedHandled) { e.stopPropagation(); return; }
(e.nativeEvent as any).formattedHandled = true;
- if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientX - this._downX) < 4) {
- this.props.select(e.ctrlKey);
- this.hitBulletTargets(e.clientX, e.clientY, e.shiftKey, false);
- }
if (this.props.isSelected(true)) { // if text box is selected, then it consumes all click events
e.stopPropagation();
+ this.hitBulletTargets(e.clientX, e.clientY, e.shiftKey, false);
}
}
@@ -1083,7 +1090,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
let olistPos = clickPos?.pos;
if (clickPos && olistPos && this.props.isSelected(true)) {
const clickNode = this._editorView?.state.doc.nodeAt(olistPos);
- let nodeBef = this._editorView?.state.doc.nodeAt(Math.max(0, olistPos - 1));
+ const nodeBef = this._editorView?.state.doc.nodeAt(Math.max(0, olistPos - 1));
olistPos = nodeBef?.type === this._editorView?.state.schema.nodes.ordered_list ? olistPos - 1 : olistPos;
let $olistPos = this._editorView?.state.doc.resolve(olistPos);
let olistNode = (nodeBef !== null || clickNode?.type === this._editorView?.state.schema.nodes.list_item) && olistPos === clickPos?.pos ? clickNode : nodeBef;
@@ -1093,17 +1100,17 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
$olistPos = this._editorView?.state.doc.resolve(($olistPos as any).path[($olistPos as any).path.length - 4]);
}
}
- const listNode = this._editorView?.state.doc.nodeAt(clickPos.pos!);
+ const listNode = this._editorView?.state.doc.nodeAt(clickPos.pos);
if (olistNode && olistNode.type === this._editorView?.state.schema.nodes.ordered_list) {
if (!collapse) {
if (!highlightOnly) {
- this._editorView!.dispatch(this._editorView!.state.tr.setSelection(new NodeSelection($olistPos!)));
+ this._editorView.dispatch(this._editorView.state.tr.setSelection(new NodeSelection($olistPos!)));
}
addStyleSheetRule(FormattedTextBox._bulletStyleSheet, olistNode.attrs.mapStyle + olistNode.attrs.bulletStyle + ":hover:before", { background: "lightgray" });
} else if (listNode && listNode.type === this._editorView.state.schema.nodes.list_item) {
if (!highlightOnly) {
- this._editorView!.dispatch(this._editorView!.state.tr.setNodeMarkup(clickPos.pos!, listNode.type, { ...listNode.attrs, visibility: !listNode.attrs.visibility }));
- this._editorView!.dispatch(this._editorView!.state.tr.setSelection(TextSelection.create(this._editorView!.state.doc, clickPos.pos!)));
+ this._editorView.dispatch(this._editorView.state.tr.setNodeMarkup(clickPos.pos, listNode.type, { ...listNode.attrs, visibility: !listNode.attrs.visibility }));
+ this._editorView.dispatch(this._editorView.state.tr.setSelection(TextSelection.create(this._editorView.state.doc, clickPos.pos)));
}
addStyleSheetRule(FormattedTextBox._bulletStyleSheet, olistNode.attrs.mapStyle + olistNode.attrs.bulletStyle + ":hover:before", { background: "lightgray" });
}
@@ -1202,18 +1209,16 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const nh = this.layoutDoc.isTemplateForField ? 0 : NumCast(this.dataDoc._nativeHeight, 0);
const dh = NumCast(this.rootDoc._height, 0);
const newHeight = Math.max(10, (nh ? dh / nh * scrollHeight : scrollHeight) + (this.props.ChromeHeight ? this.props.ChromeHeight() : 0));
- if (Math.abs(newHeight - dh) > 1) { // bcz: Argh! without this, we get into a React crash if the same document is opened in a freeform view and in the treeview. no idea why, but after dragging the freeform document, selecting it, and selecting text, it will compute to 1 pixel higher than the treeview which causes a cycle
- if (this.rootDoc !== this.layoutDoc.doc && !this.layoutDoc.resolvedDataDoc) {
- // 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...
- console.log("Delayed height adjustment...");
- setTimeout(() => {
- this.rootDoc._height = newHeight;
- this.dataDoc._nativeHeight = nh ? scrollHeight : undefined;
- }, 10);
- } else {
+ if (this.rootDoc !== this.layoutDoc.doc && !this.layoutDoc.resolvedDataDoc) {
+ // 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...
+ console.log("Delayed height adjustment...");
+ setTimeout(() => {
this.rootDoc._height = newHeight;
this.dataDoc._nativeHeight = nh ? scrollHeight : undefined;
- }
+ }, 10);
+ } else {
+ this.rootDoc._height = newHeight;
+ this.dataDoc._nativeHeight = nh ? scrollHeight : undefined;
}
}
}
@@ -1233,17 +1238,19 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
setTimeout(() => FormattedTextBoxComment.Hide(), 0);
}
const selPad = this.props.isSelected() ? -10 : 0;
- const selclass = this.props.isSelected() ? "-selected" : ""
+ const selclass = this.props.isSelected() ? "-selected" : "";
return (
- <div className={"formattedTextBox-cont"} style={{
- transform: `scale(${scale})`,
- transformOrigin: "top left",
- width: `${100 / scale}%`,
- height: `calc(${100 / scale}% - ${this.props.ChromeHeight?.() || 0}px)`,
- ...this.styleFromLayoutString(scale)
- }}>
+ <div className={"formattedTextBox-cont"}
+ style={{
+ transform: `scale(${scale})`,
+ transformOrigin: "top left",
+ width: `${100 / scale}%`,
+ height: `calc(${100 / scale}% - ${this.props.ChromeHeight?.() || 0}px)`,
+ ...this.styleFromLayoutString(scale)
+ }}>
<div className={`formattedTextBox-cont`} ref={this._ref}
style={{
+ overflow: this.layoutDoc._autoHeight ? "hidden" : undefined,
width: "100%",
height: this.props.height ? this.props.height : this.layoutDoc._autoHeight && this.props.renderDepth ? "max-content" : undefined,
background: Doc.UserDoc().renderStyle === "comic" ? "transparent" : this.props.background ? this.props.background : StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], this.props.hideOnLeave ? "rgba(0,0,0 ,0.4)" : ""),