aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes
diff options
context:
space:
mode:
authorGeireann Lindfield Roberts <60007097+geireann@users.noreply.github.com>2020-11-01 22:58:45 +0800
committerGeireann Lindfield Roberts <60007097+geireann@users.noreply.github.com>2020-11-01 22:58:45 +0800
commitfa65753233e17d90a3306432bba9d212307e5b68 (patch)
tree005123322c4a65b558e7ece45edcffe20b8dca1d /src/client/views/nodes
parent3def219d20179486fe3427c957f680e5d1d705df (diff)
parent7b96bc4770bd275db0ddd664bb6e8ff33bbbcb78 (diff)
Merge branch 'master' into presentation_v1
Diffstat (limited to 'src/client/views/nodes')
-rw-r--r--src/client/views/nodes/ColorBox.tsx4
-rw-r--r--src/client/views/nodes/ContentFittingDocumentView.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.tsx2
-rw-r--r--src/client/views/nodes/PresBox.tsx27
-rw-r--r--src/client/views/nodes/VideoBox.tsx15
-rw-r--r--src/client/views/nodes/WebBox.tsx98
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.scss2
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx6
-rw-r--r--src/client/views/nodes/formattedText/RichTextMenu.tsx8
9 files changed, 103 insertions, 61 deletions
diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx
index fcc9e50f5..4fb350b55 100644
--- a/src/client/views/nodes/ColorBox.tsx
+++ b/src/client/views/nodes/ColorBox.tsx
@@ -69,11 +69,11 @@ export class ColorBox extends ViewBoxBaseComponent<FieldViewProps, ColorDocument
SetActiveInkWidth(e.target.value);
SelectionManager.SelectedDocuments().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.strokeWidth = Number(e.target.value));
}} />
- <div> {ActiveInkBezierApprox() ?? 2}</div>
+ {/* <div> {ActiveInkBezierApprox() ?? 2}</div>
<input type="range" defaultValue={ActiveInkBezierApprox() ?? 2} min={0} max={300} onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
SetActiveBezierApprox(e.target.value);
SelectionManager.SelectedDocuments().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.strokeBezier = e.target.value);
- }} />
+ }} /> */}
<br />
<br />
</div>
diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx
index bc3ad5bce..0c52b9044 100644
--- a/src/client/views/nodes/ContentFittingDocumentView.tsx
+++ b/src/client/views/nodes/ContentFittingDocumentView.tsx
@@ -40,7 +40,7 @@ export class ContentFittingDocumentView extends React.Component<DocumentViewProp
@computed get panelWidth() { return this.nativeWidth() && !this.props.Document._fitWidth ? this.nativeWidth() * this.contentScaling() : this.props.PanelWidth(); }
@computed get panelHeight() {
if (this.nativeHeight()) {
- if (!this.props.Document._fitWidth) return this.nativeHeight() * this.contentScaling()
+ if (!this.props.Document._fitWidth) return this.nativeHeight() * this.contentScaling();
else return this.panelWidth / Doc.NativeAspect(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || 1;
}
return this.props.PanelHeight();
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 0b27cd03c..a4da00578 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -839,8 +839,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
onClicks.push({ description: "Select on Click", event: () => this.selectOnClick(), icon: "link" });
onClicks.push({ description: "Follow Link on Click", event: () => this.followLinkOnClick(undefined, false), icon: "link" });
onClicks.push({ description: "Toggle Link Target on Click", event: () => this.toggleTargetOnClick(), icon: "map-pin" });
+ !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, subitems: onClicks, icon: "mouse-pointer" });
}
- !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, subitems: onClicks, icon: "mouse-pointer" });
}
const funcs: ContextMenuProps[] = [];
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index a31e92807..518d365ed 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -91,7 +91,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
const tagDocs: Doc[] = [];
for (const doc of this.childDocs) {
const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
- tagDocs.push(tagDoc)
+ tagDocs.push(tagDoc);
}
return tagDocs;
}
@@ -486,7 +486,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
//stops the presentaton.
resetPresentation = () => {
this.rootDoc._itemIndex = 0;
- for (const doc of this.childDocs) Cast(doc.presentationTargetDoc, Doc, null).opacity = 1;
+ this.childDocs.map(doc => Cast(doc.presentationTargetDoc, Doc, null)).filter(doc => doc instanceof Doc).forEach(doc => {
+ try {
+ doc.opacity = 1;
+ } catch (e) {
+ console.log("REset presentation error: ", e);
+ }
+ });
+ ///for (const doc of this.childDocs) Cast(doc.presentationTargetDoc, Doc, null).opacity = 1;
}
@action togglePath = (srcContext: Doc, off?: boolean) => {
@@ -638,9 +645,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
const list = Array.from(this._selectedArray.keys()).map((doc: Doc, index: any) => {
const curDoc = Cast(doc, Doc, null);
const tagDoc = Cast(curDoc.presentationTargetDoc!, Doc, null);
- if (curDoc && curDoc === this.activeItem) return <div className="selectedList-items"><b>{index + 1}. {curDoc.title}</b></div>
- else if (tagDoc) return <div className="selectedList-items">{index + 1}. {curDoc.title}</div>;
- else if (curDoc) return <div className="selectedList-items">{index + 1}. {curDoc.title}</div>;
+ if (curDoc && curDoc === this.activeItem) return <div key={index} className="selectedList-items"><b>{index + 1}. {curDoc.title}</b></div>;
+ else if (tagDoc) return <div key={index} className="selectedList-items">{index + 1}. {curDoc.title}</div>;
+ else if (curDoc) return <div key={index} className="selectedList-items">{index + 1}. {curDoc.title}</div>;
});
return list;
}
@@ -799,10 +806,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
}
getAllIndexes = (arr: Doc[], val: Doc): number[] => {
- var indexes = [], i;
- for (i = 0; i < arr.length; i++)
- if (arr[i] === val)
- indexes.push(i);
+ const indexes = [];
+ for (let i = 0; i < arr.length; i++) {
+ arr[i] === val && indexes.push(i);
+ }
return indexes;
}
@@ -952,7 +959,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
doc.presMovement = PresMovement.None;
break;
}
- })
+ });
});
@undoBatch
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 250595db5..190193351 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -159,7 +159,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
@action
updateTimecode = () => {
this.player && (this.layoutDoc._currentTimecode = this.player.currentTime);
- this._youtubePlayer && (this.layoutDoc._currentTimecode = this._youtubePlayer.getCurrentTime());
+ this._youtubePlayer && (this.layoutDoc._currentTimecode = this._youtubePlayer.getCurrentTime?.());
}
componentDidMount() {
@@ -281,13 +281,14 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
() => !this.props.Document.isAnnotating && Doc.GetSelectedTool() === InkTool.None && this.props.isSelected(true) && !SnappingManager.GetIsDragging() && !DocumentDecorations.Instance.Interacting,
(interactive) => iframe.style.pointerEvents = interactive ? "all" : "none", { fireImmediately: true });
};
- this._youtubePlayer = new YT.Player(`${this.youtubeVideoId + this._youtubeIframeId}-player`, {
- events: {
- 'onReady': this.props.dontRegisterView ? undefined : onYoutubePlayerReady,
- 'onStateChange': this.props.dontRegisterView ? undefined : onYoutubePlayerStateChange,
- }
+ (YT as any)?.ready(() => {
+ this._youtubePlayer = new YT.Player(`${this.youtubeVideoId + this._youtubeIframeId}-player`, {
+ events: {
+ 'onReady': this.props.dontRegisterView ? undefined : onYoutubePlayerReady,
+ 'onStateChange': this.props.dontRegisterView ? undefined : onYoutubePlayerStateChange,
+ }
+ })
});
-
}
private get uIButtons() {
const curTime = (this.layoutDoc._currentTimecode || 0);
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index de5546fa9..8a8f46963 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -1,4 +1,3 @@
-import { faMousePointer, faPen, faStickyNote } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
import { observer } from "mobx-react";
@@ -47,6 +46,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
private _startX: number = 0;
private _startY: number = 0;
+ private _scrollTarget: any = undefined;
@observable private _marqueeX: number = 0;
@observable private _marqueeY: number = 0;
@observable private _marqueeWidth: number = 0;
@@ -61,8 +61,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
@observable private _savedAnnotations: Dictionary<number, HTMLDivElement[]> = new Dictionary<number, HTMLDivElement[]>();
private _selectionReactionDisposer?: IReactionDisposer;
private _scrollReactionDisposer?: IReactionDisposer;
+ private _scrollTopReactionDisposer?: IReactionDisposer;
private _moveReactionDisposer?: IReactionDisposer;
- private _keyInput = React.createRef<HTMLInputElement>();
private _longPressSecondsHack?: NodeJS.Timeout;
private _outerRef = React.createRef<HTMLDivElement>();
private _iframeRef = React.createRef<HTMLIFrameElement>();
@@ -83,14 +83,17 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
if (iframe && iframe.contentDocument) {
iframe.setAttribute("enable-annotation", "true");
iframe.contentDocument.addEventListener("click", undoBatch(action(e => {
- const href = e.target?.href;
+ let href = "";
+ for (let ele = e.target; ele; ele = ele.parentElement) {
+ href = (typeof (ele.href) === "string" ? ele.href : ele.href?.baseVal) || ele.parentElement?.href || href;
+ }
if (href) {
this._url = href.replace(Utils.prepend(""), Cast(this.dataDoc[this.fieldKey], WebField, null)?.url.origin);
this.submitURL();
}
})));
- iframe.contentDocument.addEventListener('pointerdown', this.iframedown, false);
- iframe.contentDocument.addEventListener('scroll', this.iframeScrolled, false);
+ iframe.contentDocument.addEventListener('wheel', this.iframeWheel, false);
+ iframe.contentDocument.addEventListener('scroll', this.iframeScroll, false);
this.layoutDoc.scrollHeight = iframe.contentDocument.children?.[0].scrollHeight || 1000;
iframe.contentDocument.children[0].scrollTop = NumCast(this.layoutDoc._scrollTop);
iframe.contentDocument.children[0].scrollLeft = NumCast(this.layoutDoc._scrollLeft);
@@ -102,17 +105,30 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
const durationStr = StrCast(this.Document._viewTransition).match(/([0-9]*)ms/);
const duration = durationStr ? Number(durationStr[1]) : 1000;
if (scrollY !== undefined) {
- setTimeout(() => this._outerRef.current && smoothScroll(duration, this._outerRef.current, Math.abs(scrollY || 0)), delay);
- setTimeout(() => { this.layoutDoc._scrollTop = scrollY; this.layoutDoc._scrollY = undefined; }, duration + delay);
+ this._forceSmoothScrollUpdate = true;
+ this.layoutDoc._scrollY = undefined;
+ setTimeout(() => this._outerRef.current && smoothScroll(duration, this._outerRef.current, Math.abs(scrollY || 0), () => this.layoutDoc._scrollTop = scrollY), delay);
}
if (scrollX !== undefined) {
- setTimeout(() => this._outerRef.current && smoothScroll(duration, this._outerRef.current, Math.abs(scrollX || 0)), delay);
- setTimeout(() => { this.layoutDoc._scrollLeft = scrollX; this.layoutDoc._scrollX = undefined; }, duration + delay);
+ this._forceSmoothScrollUpdate = true;
+ this.layoutDoc._scrollX = undefined;
+ setTimeout(() => this._outerRef.current && smoothScroll(duration, this._outerRef.current, Math.abs(scrollX || 0), () => this.layoutDoc._scrollLeft = scrollX), delay);
}
},
{ fireImmediately: true }
);
+ this._scrollTopReactionDisposer = reaction(() => this.layoutDoc._scrollTop,
+ scrollTop => {
+ const durationStr = StrCast(this.Document._viewTransition).match(/([0-9]*)ms/);
+ const duration = durationStr ? Number(durationStr[1]) : 1000;
+ if (scrollTop !== undefined && this._forceSmoothScrollUpdate) {
+ this._outerRef.current && smoothScroll(duration, this._outerRef.current, Math.abs(scrollTop || 0), () => this._forceSmoothScrollUpdate = true);
+ } else this._forceSmoothScrollUpdate = true;
+ },
+ { fireImmediately: true }
+ );
});
+ _forceSmoothScrollUpdate = true;
updateScroll = (x: Opt<number>, y: Opt<number>) => {
if (y !== undefined) {
@@ -126,18 +142,28 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
}
setPreviewCursor = (func?: (x: number, y: number, drag: boolean) => void) => this._setPreviewCursor = func;
- iframedown = (e: PointerEvent) => {
- this._setPreviewCursor?.(e.screenX, e.screenY, false);
- }
- iframeScrolled = (e: any) => {
- if (e.target?.children) {
- e.target.children[0].scrollLeft = 0;
- const scrollTop = e.target.children[0].scrollTop;
- const scrollLeft = e.target.children[0].scrollLeft;
- this.layoutDoc._scrollTop = this._outerRef.current!.scrollTop = scrollTop;
- this.layoutDoc._scrollLeft = this._outerRef.current!.scrollLeft = scrollLeft;
+ iframeWheel = (e: any) => {
+ if (this._forceSmoothScrollUpdate && e.target?.children) {
+ this._scrollTarget && setTimeout(action(() => {
+ this._scrollTarget.scrollLeft = 0;
+ const scrollTop = this._scrollTarget.scrollTop;
+ const scrollLeft = this._scrollTarget.scrollLeft;
+ this._outerRef.current!.scrollTop = scrollTop;
+ this._outerRef.current!.scrollLeft = scrollLeft;
+ if (this.layoutDoc._scrollTop !== scrollTop) {
+ this._forceSmoothScrollUpdate = false;
+ this.layoutDoc._scrollTop = scrollTop;
+ }
+ if (this.layoutDoc._scrollLeft !== scrollLeft) {
+ this._forceSmoothScrollUpdate = false;
+ this.layoutDoc._scrollLeft = scrollLeft;
+ }
+ }))
}
}
+ iframeScroll = (e: any) => {
+ this._scrollTarget = e.target.children[0];
+ }
async componentDidMount() {
const urlField = Cast(this.dataDoc[this.props.fieldKey], WebField);
runInAction(() => this._url = urlField?.url.toString() || "");
@@ -180,11 +206,12 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
componentWillUnmount() {
this._moveReactionDisposer?.();
this._selectionReactionDisposer?.();
+ this._scrollTopReactionDisposer?.();
this._scrollReactionDisposer?.();
document.removeEventListener("pointerup", this.onLongPressUp);
document.removeEventListener("pointermove", this.onLongPressMove);
- this._iframeRef.current?.contentDocument?.removeEventListener('pointerdown', this.iframedown);
- this._iframeRef.current?.contentDocument?.removeEventListener('scroll', this.iframeScrolled);
+ this._iframeRef.current?.contentDocument?.removeEventListener('wheel', this.iframeWheel);
+ this._iframeRef.current?.contentDocument?.removeEventListener('scroll', this.iframeScroll);
}
onUrlDragover = (e: React.DragEvent) => {
@@ -468,7 +495,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
}
@computed get annotationLayer() {
TraceMobx();
- return <div className="webBox-annotationLayer" style={{ height: Doc.NativeHeight(this.Document) }} ref={this._annotationLayer}>
+ return <div className="webBox-annotationLayer" style={{ height: Doc.NativeHeight(this.Document) || undefined }} ref={this._annotationLayer}>
{this.nonDocAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).map(anno =>
<Annotation {...this.props} showInfo={emptyFunction} focus={this.props.focus} dataDoc={this.dataDoc} fieldKey={this.props.fieldKey} anno={anno} key={`${anno[Id]}-annotation`} />)
}
@@ -542,10 +569,12 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
}
else if (this._mainCont.current) {
// set marquee x and y positions to the spatially transformed position
+ const nheight = Doc.NativeHeight(this.Document) || 1;
+ const nwidth = Doc.NativeWidth(this.Document) || 1;
const boundingRect = this._mainCont.current.getBoundingClientRect();
- const boundingHeight = (Doc.NativeHeight(this.Document) || 1) / (Doc.NativeWidth(this.Document) || 1) * boundingRect.width;
- this._startX = (e.clientX - boundingRect.left) / boundingRect.width * (Doc.NativeWidth(this.Document) || 1);
- this._startY = (e.clientY - boundingRect.top) / boundingHeight * (Doc.NativeHeight(this.Document) || 1);
+ const boundingHeight = nheight / nwidth * boundingRect.width;
+ this._startX = (e.clientX - boundingRect.left) / boundingRect.width * nwidth;
+ this._startY = (e.clientY - boundingRect.top) / boundingHeight * nheight;
this._marqueeHeight = this._marqueeWidth = 0;
this._marqueeing = true;
}
@@ -619,23 +648,24 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
marqueeX = () => this._marqueeX;
marqueeY = () => this._marqueeY;
marqueeing = () => this._marqueeing;
- visibleHeiht = () => {
+ visibleHeight = () => {
if (this._mainCont.current) {
const boundingRect = this._mainCont.current.getBoundingClientRect();
- const scalin = (Doc.NativeWidth(this.Document) || 0) / boundingRect.width;
- return Math.min(boundingRect.height * scalin, this.props.PanelHeight() * scalin);
+ const scaling = (Doc.NativeWidth(this.Document) || 0) / boundingRect.width;
+ return Math.min(boundingRect.height * scaling, this.props.PanelHeight() * scaling);
}
return this.props.PanelHeight();
}
scrollXf = () => this.props.ScreenToLocalTransform().translate(NumCast(this.layoutDoc._scrollLeft), NumCast(this.layoutDoc._scrollTop));
render() {
+ const scaling = Number.isFinite(this.props.ContentScaling()) ? this.props.ContentScaling() || 1 : 1;
return (<div className="webBox" ref={this._mainCont} >
<div className={`webBox-container`}
style={{
position: undefined,
- transform: `scale(${this.props.ContentScaling()})`,
- width: Number.isFinite(this.props.ContentScaling()) ? `${100 / this.props.ContentScaling()}% ` : "100%",
- height: Number.isFinite(this.props.ContentScaling()) ? `${100 / this.props.ContentScaling()}% ` : "100%",
+ transform: `scale(${scaling})`,
+ width: `${100 / scaling}% `,
+ height: `${100 / scaling}% `,
pointerEvents: this.layoutDoc._isBackground ? "none" : undefined
}}
onContextMenu={this.specificContextMenu}>
@@ -643,7 +673,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
{this.content}
<div className={"webBox-outerContent"} ref={this._outerRef}
style={{
- width: Number.isFinite(this.props.ContentScaling()) ? `${Math.max(100, 100 / this.props.ContentScaling())}% ` : "100%",
+ width: `${Math.max(100, 100 / scaling)}% `,
pointerEvents: this.layoutDoc.isAnnotating && !this.layoutDoc._isBackground ? "all" : "none"
}}
onWheel={e => e.stopPropagation()}
@@ -662,14 +692,14 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
//this._outerRef.current!.scrollTop !== this._scrollTop && (this._outerRef.current!.scrollTop = this._scrollTop)
}}>
<div className={"webBox-innerContent"} style={{
- height: NumCast(this.layoutDoc.scrollHeight),
+ height: NumCast(this.layoutDoc.scrollHeight, 50),
pointerEvents: this.layoutDoc._isBackground ? "none" : undefined
}}>
<CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
PanelHeight={this.props.PanelHeight}
PanelWidth={this.props.PanelWidth}
annotationsKey={this.annotationKey}
- VisibleHeight={this.visibleHeiht}
+ VisibleHeight={this.visibleHeight}
focus={this.props.focus}
setPreviewCursor={this.setPreviewCursor}
isSelected={this.props.isSelected}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss
index 9307f1649..b75cc230f 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.scss
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss
@@ -22,7 +22,7 @@
border-style: solid;
overflow-y: auto;
overflow-x: hidden;
- color: initial;
+ color: inherit;
display: flex;
flex-direction: row;
transition: opacity 1s;
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index d44f35a96..bc9e8e99d 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -11,7 +11,7 @@ import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from "
import { ReplaceStep } from 'prosemirror-transform';
import { EditorView } from "prosemirror-view";
import { DateField } from '../../../../fields/DateField';
-import { DataSym, Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, WidthSym, AclEdit, AclAdmin, UpdatingFromServer } from "../../../../fields/Doc";
+import { DataSym, Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, WidthSym, AclEdit, AclAdmin, UpdatingFromServer, ForceServerWrite } from "../../../../fields/Doc";
import { documentSchema } from '../../../../fields/documentSchemas';
import applyDevTools = require("prosemirror-dev-tools");
import { removeMarkWithAttrs } from "./prosemirrorPatches";
@@ -805,9 +805,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
tr = tr.addMark(pos, pos + node.nodeSize, link);
}
});
- this.dataDoc[UpdatingFromServer] = true; // need to allow permissions for adding links to readonly/augment only documents
+ this.dataDoc[ForceServerWrite] = this.dataDoc[UpdatingFromServer] = true; // need to allow permissions for adding links to readonly/augment only documents
this._editorView!.dispatch(tr.removeMark(sel.from, sel.to, splitter));
- this.dataDoc[UpdatingFromServer] = false;
+ this.dataDoc[UpdatingFromServer] = this.dataDoc[ForceServerWrite] = false;
}
}
componentDidMount() {
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 2700c508b..cf9b03308 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -31,6 +31,7 @@ const { toggleMark } = require("prosemirror-commands");
export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
static Instance: RichTextMenu;
public overMenu: boolean = false; // kind of hacky way to prevent selects not being selectable
+ private _linkToRef = React.createRef<HTMLInputElement>();
@observable public view?: EditorView;
public editorProps: FieldViewProps & FormattedTextBoxProps | undefined;
@@ -154,6 +155,9 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
@action
public updateMenu(view: EditorView | undefined, lastState: EditorState | undefined, props: any) {
+ if (this._linkToRef.current?.getBoundingClientRect().width) {
+ return;
+ }
this.view = view;
if (!view || !view.hasFocus()) {
return;
@@ -792,7 +796,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
const self = this;
function onLinkChange(e: React.ChangeEvent<HTMLInputElement>) {
- self.TextView.endUndoTypingBatch();
+ self.TextView?.endUndoTypingBatch();
UndoManager.RunInBatch(() => self.setCurrentLink(e.target.value), "link change");
}
@@ -807,7 +811,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
const dropdownContent =
<div className="dropdown link-menu">
<p>Linked to:</p>
- <input value={link} placeholder="Enter URL" onChange={onLinkChange} />
+ <input value={link} ref={this._linkToRef} placeholder="Enter URL" onChange={onLinkChange} />
<button className="make-button" onPointerDown={e => this.makeLinkToURL(link, "add:right")}>Apply hyperlink</button>
<div className="divider"></div>
<button className="remove-button" onPointerDown={e => this.deleteLink()}>Remove link</button>