From 10382b7fcac2d92dc845e9b271e38de3d8c09feb Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 21 Jun 2020 22:29:18 -0400 Subject: fixed link lines to text hyperlinks --- .../collections/collectionFreeForm/CollectionFreeFormLinkView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index b65a2486c..859bbc8f8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -62,7 +62,7 @@ export class CollectionFreeFormLinkView extends React.Component { (this.props.A.rootDoc[(this.props.A.props as any).fieldKey] as Doc); const m = targetBhyperlink.getBoundingClientRect(); - const mp = this.props.A.props.ContainingCollectionView?.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5); + const mp = this.props.A.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5); this.props.A.rootDoc[afield + "_x"] = Math.min(1, mp![0] / this.props.A.props.PanelWidth()) * 100; this.props.A.rootDoc[afield + "_y"] = Math.min(1, mp![1] / this.props.A.props.PanelHeight()) * 100; }, 0); @@ -74,7 +74,7 @@ export class CollectionFreeFormLinkView extends React.Component { (this.props.B.rootDoc[(this.props.B.props as any).fieldKey] as Doc); const m = targetAhyperlink.getBoundingClientRect(); - const mp = this.props.B.props.ContainingCollectionView?.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5); + const mp = this.props.B.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5); this.props.B.rootDoc[bfield + "_x"] = Math.min(1, mp![0] / this.props.B.props.PanelWidth()) * 100; this.props.B.rootDoc[bfield + "_y"] = Math.min(1, mp![1] / this.props.B.props.PanelHeight()) * 100; }, 0); -- cgit v1.2.3-70-g09d2 From e81ad333750a86e4dae51907adc489a73d08437a Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 22 Jun 2020 11:19:00 -0400 Subject: cleaned up errors. added ctrl-a to select documents within a freeform collection. fixed ctrl-x to remove documents properly. fixed paste documents to clone only if copied. --- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/GlobalKeyHandler.ts | 14 ++++++----- src/client/views/PreviewCursor.tsx | 24 ++++++++++--------- .../CollectionFreeFormLinkView.tsx | 8 +++---- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../collections/collectionFreeForm/MarqueeView.tsx | 27 +++++++++++++++------- src/client/views/nodes/ImageBox.tsx | 8 +++---- src/client/views/nodes/KeyValueBox.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 12 +++++----- src/client/views/nodes/formattedText/nodes_rts.ts | 2 +- 10 files changed, 58 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index d92fe5203..beb6155ca 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -175,7 +175,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } @undoBatch @action - onCloseClick = async (e: React.MouseEvent) => { + onCloseClick = async (e: React.MouseEvent | undefined) => { if (!e?.button) { const recent = Cast(Doc.UserDoc().myRecentlyClosed, Doc) as Doc; const selected = SelectionManager.SelectedDocuments().slice(); diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index c696625db..27755737e 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -253,8 +253,8 @@ export default class KeyManager { case "x": if (SelectionManager.SelectedDocuments().length) { const bds = DocumentDecorations.Instance.Bounds; - const pt = [bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2]; - const text = `__DashDocId(${pt[0]},${pt[1]}):` + SelectionManager.SelectedDocuments().map(dv => dv.Document[Id]).join(":"); + const pt = SelectionManager.SelectedDocuments()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2); + const text = `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.SelectedDocuments().map(dv => dv.Document[Id]).join(":"); SelectionManager.SelectedDocuments().length && navigator.clipboard.writeText(text); DocumentDecorations.Instance.onCloseClick(undefined); stopPropagation = false; @@ -265,7 +265,7 @@ export default class KeyManager { if (DocumentDecorations.Instance.Bounds.r - DocumentDecorations.Instance.Bounds.x > 2) { const bds = DocumentDecorations.Instance.Bounds; const pt = SelectionManager.SelectedDocuments()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2); - const text = `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.SelectedDocuments().map(dv => dv.Document[Id]).join(":"); + const text = `__DashCloneId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.SelectedDocuments().map(dv => dv.Document[Id]).join(":"); SelectionManager.SelectedDocuments().length && navigator.clipboard.writeText(text); stopPropagation = false; } @@ -280,10 +280,12 @@ export default class KeyManager { }); public paste(e: ClipboardEvent) { - if (e.clipboardData?.getData("text/plain") !== "" && e.clipboardData?.getData("text/plain").startsWith("__DashDocId(")) { + const plain = e.clipboardData?.getData("text/plain"); + const clone = plain?.startsWith("__DashCloneId("); + if (plain && (plain.startsWith("__DashDocId(") || clone)) { const first = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined; if (first?.props.Document.type === DocumentType.COL) { - const docids = e.clipboardData.getData("text/plain").split(":"); + const docids = plain.split(":"); let count = 1; const list: Doc[] = []; const targetDataDoc = Doc.GetProto(first.props.Document); @@ -295,7 +297,7 @@ export default class KeyManager { list.push(doc); } if (count === docids.length) { - const added = list.filter(d => !docList.includes(d)); + const added = list.filter(d => !docList.includes(d)).map(d => clone ? Doc.MakeClone(d) : d); if (added.length) { added.map(doc => doc.context = targetDataDoc); undoBatch(() => { diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index dd65681d4..e27f6b95a 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -32,10 +32,11 @@ export class PreviewCursor extends React.Component<{}> { // tests for URL and makes web document const re: any = /^https?:\/\//g; - if (e.clipboardData.getData("text/plain") !== "") { + const plain = e.clipboardData.getData("text/plain"); + if (plain) { // tests for youtube and makes video document - if (e.clipboardData.getData("text/plain").indexOf("www.youtube.com/watch") !== -1) { - const url = e.clipboardData.getData("text/plain").replace("youtube.com/watch?v=", "youtube.com/embed/"); + if (plain.indexOf("www.youtube.com/watch") !== -1) { + const url = plain.replace("youtube.com/watch?v=", "youtube.com/embed/"); undoBatch(() => PreviewCursor._addDocument(Docs.Create.VideoDocument(url, { title: url, _width: 400, _height: 315, _nativeWidth: 600, _nativeHeight: 472.5, @@ -43,8 +44,8 @@ export class PreviewCursor extends React.Component<{}> { })))(); } - else if (re.test(e.clipboardData.getData("text/plain"))) { - const url = e.clipboardData.getData("text/plain"); + else if (re.test(plain)) { + const url = plain; undoBatch(() => PreviewCursor._addDocument(Docs.Create.WebDocument(url, { title: url, _width: 500, _height: 300, UseCors: true, // nativeWidth: 300, nativeHeight: 472.5, @@ -52,10 +53,11 @@ export class PreviewCursor extends React.Component<{}> { })))(); } - else if (e.clipboardData.getData("text/plain").startsWith("__DashDocId(")) { - const docids = e.clipboardData.getData("text/plain").split(":"); + else if (plain.startsWith("__DashDocId(") || plain.startsWith("__DashCloneId(")) { + const clone = plain.startsWith("__DashCloneId("); + const docids = plain.split(":"); const strs = docids[0].split(","); - const ptx = Number(strs[0].substring("__DashDocId(".length)); + const ptx = Number(strs[0].substring((clone ? "__DashCloneId(" : "__DashDocId(").length)); const pty = Number(strs[1].substring(0, strs[1].length - 1)); let count = 1; const list: Doc[] = []; @@ -65,7 +67,7 @@ export class PreviewCursor extends React.Component<{}> { count++; if (doc instanceof Doc) { i === 1 && (first = doc); - const alias = Doc.MakeClone(doc); + const alias = clone ? Doc.MakeClone(doc) : doc; const deltaX = NumCast(doc.x) - NumCast(first!.x) - ptx; const deltaY = NumCast(doc.y) - NumCast(first!.y) - pty; alias.x = newPoint[0] + deltaX; @@ -115,9 +117,9 @@ export class PreviewCursor extends React.Component<{}> { (e.keyCode < 112 || e.keyCode > 123) && // F1 thru F12 keys !e.key.startsWith("Arrow") && !e.defaultPrevented) { - if ((!e.ctrlKey || (e.keyCode >= 48 && e.keyCode <= 57)) && !e.metaKey) {// /^[a-zA-Z0-9$*^%#@+-=_|}{[]"':;?/><.,}]$/.test(e.key)) { + if ((!e.metaKey && !e.ctrlKey) || (e.keyCode >= 48 && e.keyCode <= 57) || (e.keyCode >= 65 && e.keyCode <= 90)) {// /^[a-zA-Z0-9$*^%#@+-=_|}{[]"':;?/><.,}]$/.test(e.key)) { PreviewCursor.Visible && PreviewCursor._onKeyPress?.(e); - PreviewCursor.Visible = false; + ((!e.ctrlKey && !e.metaKey) || e.key !== "v") && (PreviewCursor.Visible = false); } } else if (PreviewCursor.Visible) { if (e.key === "ArrowRight") { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 859bbc8f8..a24693c30 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -63,8 +63,8 @@ export class CollectionFreeFormLinkView extends React.Component Transform; getTransform: () => Transform; activeDocuments: () => Doc[]; - selectDocuments: (docs: Doc[], ink: { Document: Doc, Ink: Map }[]) => void; + selectDocuments: (docs: Doc[]) => void; addLiveTextDocument: (doc: Doc) => void; isSelected: () => boolean; nudge: (x: number, y: number) => boolean; @@ -80,11 +82,17 @@ export class MarqueeView extends React.Component { @@ -108,6 +116,7 @@ export class MarqueeView extends React.Component { @@ -118,7 +127,8 @@ export class MarqueeView extends React.Component { this.hideMarquee(); @@ -354,7 +364,7 @@ export class MarqueeView extends React.Component this.props.removeDocument(d)); const newCollection = DocUtils.pileup(selected, this.Bounds.left + this.Bounds.width / 2, this.Bounds.top + this.Bounds.height / 2); this.props.addDocument(newCollection!); - this.props.selectDocuments([newCollection!], []); + this.props.selectDocuments([newCollection!]); MarqueeOptionsMenu.Instance.fadeOut(true); this.hideMarquee(); } @@ -379,7 +389,7 @@ export class MarqueeView extends React.Component this.props.selectDocuments([newCollection], []), 0); + setTimeout(() => this.props.selectDocuments([newCollection]), 0); } @undoBatch @@ -731,6 +741,7 @@ export class MarqueeView extends React.Component e.preventDefault()} + onPaste={this.paste} onScroll={(e) => e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0} onClick={this.onClick} onPointerDown={this.onPointerDown}> {this._visible ? this.marqueeDiv : null} {this.props.children} diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index f0818c7b4..c1c6f6baf 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -397,15 +397,15 @@ export class ImageBox extends ViewBoxAnnotatableComponent diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 4442ee2eb..d375466c9 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -147,7 +147,7 @@ export class KeyValueBox extends React.Component { { this._valInput.current!.select(); e.stopPropagation(); }} style={{ width: `${this.splitPercentage}%` }}> - + ; } @action diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 82334688b..f45a86b56 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1082,7 +1082,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; @@ -1092,17 +1092,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" }); } @@ -1232,7 +1232,7 @@ 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 (
Date: Mon, 22 Jun 2020 11:26:01 -0400 Subject: prevent users from deleting the activeWorspace with 'delete' menu item --- src/client/views/nodes/DocumentView.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 345ca479f..9c8c05176 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -576,7 +576,14 @@ export class DocumentView extends DocComponent(Docu } @undoBatch - deleteClicked = (): void => { SelectionManager.DeselectAll(); this.props.removeDocument?.(this.props.Document); } + deleteClicked = (): void => { + if (Doc.UserDoc().activeWorkspace === this.props.Document) { + alert("Can't delete the active workspace"); + } else { + SelectionManager.DeselectAll(); + this.props.removeDocument?.(this.props.Document); + } + } @undoBatch -- cgit v1.2.3-70-g09d2 From b4b1a14f442bdfd41f79c67a6545335e43f85f2f Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 22 Jun 2020 11:37:47 -0400 Subject: fixed onClick events for text. --- src/client/views/nodes/DocumentView.tsx | 8 -------- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 5 +---- 2 files changed, 1 insertion(+), 12 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 9c8c05176..71cb18e08 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -323,20 +323,12 @@ export class DocumentView extends DocComponent(Docu const alias = Doc.MakeAlias(this.props.Document); DocUtils.makeCustomViewClicked(alias, undefined, "onClick"); this.props.addDocTab(alias, "onRight"); - // UndoManager.RunInBatch(() => Doc.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"); - //ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", e.clientX, e.clientY), "on button click"); } else if (this.props.Document.links && this.Document.isLinkButton && !e.shiftKey && !e.ctrlKey) { DocListCast(this.props.Document.links).length && this.followLinkClick(e.altKey, e.ctrlKey, e.shiftKey); } else { if ((this.props.Document.onDragStart || (this.props.Document.rootDocument)) && !(e.ctrlKey || e.button > 0)) { // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTEmplaetForField implies we're clicking on part of a template instance and we want to select the whole template, not the part stopPropagate = false; // don't stop propagation for field templates -- want the selection to propagate up to the root document of the template } else { - // if (this.props.Document.type === DocumentType.RTF) { - // DocumentView._focusHack = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY) || [0, 0]; - // DocumentView._focusHack = [DocumentView._focusHack[0] + NumCast(this.props.Document.x), DocumentView._focusHack[1] + NumCast(this.props.Document.y)]; - - // this.props.focus(this.props.Document, false); - // } SelectionManager.SelectDoc(this, e.ctrlKey || e.shiftKey); } preventDefault = false; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index f45a86b56..86757296e 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1066,12 +1066,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); } } -- cgit v1.2.3-70-g09d2