From 3a8f534a9bea20cedbb194d3cc9dceff6afcef37 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 22 Jun 2020 12:19:21 -0400 Subject: added a way to broadcast a message to all users (e.g., for restarting server) --- src/client/views/MainView.tsx | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index fcaa349cd..d6c46e3b0 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -80,6 +80,11 @@ export class MainView extends React.Component { componentDidMount() { const tag = document.createElement('script'); + const proto = DocServer.GetRefField("rtfProto").then(proto => { + (proto instanceof Doc) && reaction(() => StrCast(proto.BROADCAST_MESSAGE), + msg => msg && alert(msg)); + }); + tag.src = "https://www.youtube.com/iframe_api"; const firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode!.insertBefore(tag, firstScriptTag); -- cgit v1.2.3-70-g09d2 From 9e37056e3b1e5412e2eca9020841a56503f70d32 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 24 Jun 2020 01:46:42 -0400 Subject: changed richTextMenu to dock at top of window. fixed ColorBox to set foreground color of selected text. --- deploy/index.html | 2 +- src/client/views/AntimodeMenu.tsx | 6 ++++- src/client/views/MainView.tsx | 2 +- src/client/views/MetadataEntryMenu.tsx | 26 +++++++++++++--------- .../views/collections/CollectionDockingView.tsx | 17 +++++++------- src/client/views/nodes/ColorBox.tsx | 6 ++--- .../views/nodes/formattedText/RichTextMenu.tsx | 6 ++--- 7 files changed, 37 insertions(+), 28 deletions(-) (limited to 'src/client/views/MainView.tsx') diff --git a/deploy/index.html b/deploy/index.html index fdfd77cc2..e441e3610 100644 --- a/deploy/index.html +++ b/deploy/index.html @@ -10,7 +10,7 @@ -
+
diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx index 2d26afcf6..3e4d20fea 100644 --- a/src/client/views/AntimodeMenu.tsx +++ b/src/client/views/AntimodeMenu.tsx @@ -147,7 +147,11 @@ export default abstract class AntimodeMenu extends React.Component { protected getElementWithRows(rows: JSX.Element[], numRows: number, hasDragger: boolean = true) { return (
+ style={{ + left: this._left, top: this._top, opacity: this._opacity, transitionProperty: this._transitionProperty, + transitionDuration: this._transitionDuration, transitionDelay: this._transitionDelay, height: "auto", + flexDirection: this.Pinned ? "row" : undefined, position: this.Pinned ? "unset" : undefined + }}> {hasDragger ?
: (null)} {rows}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index d6c46e3b0..0686e797e 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -570,6 +570,7 @@ export class MainView extends React.Component { + {this.mainContent} @@ -578,7 +579,6 @@ export class MainView extends React.Component { - {this.snapLines} diff --git a/src/client/views/MetadataEntryMenu.tsx b/src/client/views/MetadataEntryMenu.tsx index e100d3f52..b0752ffb2 100644 --- a/src/client/views/MetadataEntryMenu.tsx +++ b/src/client/views/MetadataEntryMenu.tsx @@ -197,19 +197,23 @@ export class MetadataEntryMenu extends React.Component{ render() { return (
e.stopPropagation()}>
- Key: -
this.autosuggestRef.current!.input?.focus()} > - +
+ Key: +
this.autosuggestRef.current!.input?.focus()} > + +
- Value: +
+ Value: this._ref.current!.focus()} onChange={this.onValueChange} onKeyDown={this.onValueKeyDown} /> +
{this.considerChildOptions}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index a969e302d..ee987abdb 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -11,7 +11,7 @@ import { Id } from '../../../fields/FieldSymbols'; import { FieldId } from "../../../fields/RefField"; import { Cast, NumCast, StrCast } from "../../../fields/Types"; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, returnOne, returnTrue, Utils, returnZero, returnEmptyFilter } from "../../../Utils"; +import { emptyFunction, returnOne, returnTrue, Utils, returnZero, returnEmptyFilter, setupMoveUpEvents, returnFalse } from "../../../Utils"; import { DocServer } from "../../DocServer"; import { Docs } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; @@ -521,13 +521,14 @@ export class CollectionDockingView extends React.Component { - if (!(e.nativeEvent as any).defaultPrevented) { - e.preventDefault(); - e.stopPropagation(); - const dragData = new DragManager.DocumentDragData([doc]); - dragData.dropAction = doc.dropAction as dropActionType; - DragManager.StartDocumentDrag([gearSpan], dragData, e.clientX, e.clientY); - } + setupMoveUpEvents(this, e, (e) => { + if (!(e as any).defaultPrevented) { + const dragData = new DragManager.DocumentDragData([doc]); + dragData.dropAction = doc.dropAction as dropActionType; + DragManager.StartDocumentDrag([gearSpan], dragData, e.clientX, e.clientY); + return true; + } return false + }, returnFalse, emptyFunction); }; tab.buttonDisposer = reaction(() => ((view: Opt) => view ? [view] : [])(DocumentManager.Instance.getDocumentView(doc)), diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx index 7b7c4d266..d6d9a8cfd 100644 --- a/src/client/views/nodes/ColorBox.tsx +++ b/src/client/views/nodes/ColorBox.tsx @@ -36,11 +36,11 @@ export class ColorBox extends ViewBoxBaseComponent
-
+ {/*
-
+
*/} @@ -788,7 +788,7 @@ export default class RichTextMenu extends AntimodeMenu {
; return ( -
+
{this.getElementWithRows([row1, row2], 2, false)}
); -- cgit v1.2.3-70-g09d2 From 7e02ca22f9667d0bdb89b29da3c412ba52976fbf Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 24 Jun 2020 09:52:05 -0400 Subject: fixed placement of settings panel icon & panel. fixed layout of docked text bar. added blockquote icon --- deploy/index.html | 2 +- src/client/views/AntimodeMenu.scss | 5 +- src/client/views/MainView.tsx | 54 ++++++++++++---------- src/client/views/globalCssVariables.scss | 2 + src/client/views/globalCssVariables.scss.d.ts | 1 + .../views/nodes/formattedText/RichTextMenu.tsx | 39 +++++++++------- 6 files changed, 60 insertions(+), 43 deletions(-) (limited to 'src/client/views/MainView.tsx') diff --git a/deploy/index.html b/deploy/index.html index e441e3610..29a3f15cd 100644 --- a/deploy/index.html +++ b/deploy/index.html @@ -10,7 +10,7 @@ -
+
diff --git a/src/client/views/AntimodeMenu.scss b/src/client/views/AntimodeMenu.scss index d4a76ee17..e56574bb7 100644 --- a/src/client/views/AntimodeMenu.scss +++ b/src/client/views/AntimodeMenu.scss @@ -1,7 +1,10 @@ +@import "./globalCssVariables"; + + .antimodeMenu-cont { position: absolute; z-index: 10000; - height: 35px; + height: $antimodemenu-height; background: #323232; box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); border-radius: 0px 6px 6px 6px; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 0686e797e..97953452d 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -5,8 +5,9 @@ import { faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt, faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, - faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye + faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft } from '@fortawesome/free-solid-svg-icons'; +import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; @@ -134,7 +135,7 @@ export class MainView extends React.Component { faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt, faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTrashAlt, faAngleRight, faBell, - faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye); + faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft); this.initEventListeners(); this.initAuthenticationRouters(); } @@ -326,9 +327,7 @@ export class MainView extends React.Component { const width = this.flyoutWidth; return {({ measureRef }) => -
{ - console.log("ENTERING"); - }} onDrop={this.onDrop} style={{ width: `calc(100% - ${width}px)` }}> +
{!mainContainer ? (null) : this.mainDocView}
} @@ -459,28 +458,33 @@ export class MainView extends React.Component { @computed get mainContent() { const sidebar = this.userDoc?.["tabs-panelContainer"]; return !this.userDoc || !(sidebar instanceof Doc) ? (null) : ( -
-
-
- -
-
- {this.flyout} - {this.expandButton} +
+
+
+
+ +
+
+ {this.flyout} + {this.expandButton} +
+ {this.dockingContent}
- {this.dockingContent}
); } diff --git a/src/client/views/globalCssVariables.scss b/src/client/views/globalCssVariables.scss index 9d3d2e592..4e85fe0ca 100644 --- a/src/client/views/globalCssVariables.scss +++ b/src/client/views/globalCssVariables.scss @@ -12,6 +12,7 @@ $lighter-alt-accent: rgb(207, 220, 240); $darker-alt-accent: rgb(178, 206, 248); $intermediate-color: #9c9396; $dark-color: #121721; +$antimodemenu-height: 35px; // fonts $sans-serif: "Noto Sans", sans-serif; @@ -40,4 +41,5 @@ $MAX_ROW_HEIGHT: 44px; MINIMIZED_ICON_SIZE: $MINIMIZED_ICON_SIZE; MAX_ROW_HEIGHT: $MAX_ROW_HEIGHT; SEARCH_THUMBNAIL_SIZE: $search-thumnail-size; + ANTIMODEMENU_HEIGHT: $antimodemenu-height; } \ No newline at end of file diff --git a/src/client/views/globalCssVariables.scss.d.ts b/src/client/views/globalCssVariables.scss.d.ts index d95cec9d8..a7ca4b300 100644 --- a/src/client/views/globalCssVariables.scss.d.ts +++ b/src/client/views/globalCssVariables.scss.d.ts @@ -5,6 +5,7 @@ interface IGlobalScss { MINIMIZED_ICON_SIZE: string; MAX_ROW_HEIGHT: string; SEARCH_THUMBNAIL_SIZE: string; + ANTIMODEMENU_HEIGHT: string; } declare const globalCssVariables: IGlobalScss; diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index e80951918..68101fbde 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -161,11 +161,10 @@ export default class RichTextMenu extends AntimodeMenu { return; } this.view = view; - const state = view.state; props && (this.editorProps = props); // Don't do anything if the document/selection didn't change - if (lastState && lastState.doc.eq(state.doc) && lastState.selection.eq(state.selection)) return; + if (lastState?.doc.eq(view.state.doc) && lastState.selection.eq(view.state.selection)) return; // update active marks const activeMarks = this.getActiveMarksOnSelection(); @@ -173,18 +172,18 @@ export default class RichTextMenu extends AntimodeMenu { // update active font family and size const active = this.getActiveFontStylesOnSelection(); - const activeFamilies = active && active.get("families"); - const activeSizes = active && active.get("sizes"); + const activeFamilies = active?.get("families"); + const activeSizes = active?.get("sizes"); - this.activeFontFamily = !activeFamilies || activeFamilies.length === 0 ? "Arial" : activeFamilies.length === 1 ? String(activeFamilies[0]) : "various"; - this.activeFontSize = !activeSizes || activeSizes.length === 0 ? "13pt" : activeSizes.length === 1 ? String(activeSizes[0]) + "pt" : "various"; + this.activeFontFamily = !activeFamilies?.length ? "Arial" : activeFamilies.length === 1 ? String(activeFamilies[0]) : "various"; + this.activeFontSize = !activeSizes?.length ? "13pt" : activeSizes.length === 1 ? String(activeSizes[0]) : "various"; // update link in current selection const targetTitle = await this.getTextLinkTargetTitle(); this.setCurrentLink(targetTitle); } - setMark = (mark: Mark, state: EditorState, dispatch: any) => { + setMark = (mark: Mark, state: EditorState, dispatch: any, dontToggle: boolean = false) => { if (mark) { const node = (state.selection as NodeSelection).node; if (node?.type === schema.nodes.ordered_list) { @@ -194,14 +193,15 @@ export default class RichTextMenu extends AntimodeMenu { if (mark.type === schema.marks.pFontColor) attrs = { ...attrs, fontColor: mark.attrs.color }; const tr = updateBullets(state.tr.setNodeMarkup(state.selection.from, node.type, attrs), state.schema); dispatch(tr.setSelection(new NodeSelection(tr.doc.resolve(state.selection.from)))); - } else { + } else if (dontToggle) { toggleMark(mark.type, mark.attrs)(state, (tx: any) => { const { from, $from, to, empty } = tx.selection; - // if (!tx.doc.rangeHasMark(from, to, mark.type)) { - // toggleMark(mark.type, mark.attrs)({ tr: tx, doc: tx.doc, selection: tx.selection, storedMarks: tx.storedMarks }, dispatch); - // } else - dispatch(tx); + if (!tx.doc.rangeHasMark(from, to, mark.type)) { // hack -- should have just set the mark in the first place + toggleMark(mark.type, mark.attrs)({ tr: tx, doc: tx.doc, selection: tx.selection, storedMarks: tx.storedMarks }, dispatch); + } else dispatch(tx); }); + } else { + toggleMark(mark.type, mark.attrs)(state, (tx: any) => dispatch(tx)); } } } @@ -368,11 +368,11 @@ export default class RichTextMenu extends AntimodeMenu { } changeFontSize = (mark: Mark, view: EditorView) => { - this.setMark(view.state.schema.marks.pFontSize.create({ fontSize: mark.attrs.fontSize }), view.state, view.dispatch); + this.setMark(view.state.schema.marks.pFontSize.create({ fontSize: mark.attrs.fontSize }), view.state, view.dispatch, true); } changeFontFamily = (mark: Mark, view: EditorView) => { - this.setMark(view.state.schema.marks.pFontFamily.create({ family: mark.attrs.family }), view.state, view.dispatch); + this.setMark(view.state.schema.marks.pFontFamily.create({ family: mark.attrs.family }), view.state, view.dispatch, true); } // TODO: remove doesn't work @@ -406,7 +406,13 @@ export default class RichTextMenu extends AntimodeMenu { tr.addMark(state.selection.from, state.selection.to, mark); const content = tr.selection.content(); const newNode = state.schema.nodes.summary.create({ visibility: false, text: content, textslice: content.toJSON() }); - dispatch && dispatch(tr.replaceSelectionWith(newNode).removeMark(tr.selection.from - 1, tr.selection.from, mark)); + dispatch?.(tr.replaceSelectionWith(newNode).removeMark(tr.selection.from - 1, tr.selection.from, mark)); + return true; + } + + insertBlockquote(state: EditorState, dispatch: any) { + if (state.selection.empty) return false; + setBlockType(state.schema.nodes.blockquote)(state, (tx: any) => dispatch(tx)); return true; } @@ -539,7 +545,7 @@ export default class RichTextMenu extends AntimodeMenu { dispatch(state.tr.addStoredMark(colorMark)); return false; } - this.setMark(colorMark, state, dispatch); + this.setMark(colorMark, state, dispatch, true); } @action toggleHighlightDropdown() { this.showHighlightDropdown = !this.showHighlightDropdown; } @@ -766,6 +772,7 @@ export default class RichTextMenu extends AntimodeMenu { this.createLinkButton(), this.createBrushButton(), this.createButton("indent", "Summarize", undefined, this.insertSummarizer), + this.createButton("quote-left", "Blockquote", undefined, this.insertBlockquote), ]}
; const row2 =
-- cgit v1.2.3-70-g09d2 From ab55a59f47efdd8f134a619ca0fa59203efe2fa9 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 24 Jun 2020 13:43:23 -0400 Subject: fixed summary icon --- src/client/views/MainView.tsx | 4 ++-- src/client/views/nodes/formattedText/RichTextMenu.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 97953452d..415f8b364 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -5,7 +5,7 @@ import { faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt, faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, - faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft + faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft, faSortAmountDown } from '@fortawesome/free-solid-svg-icons'; import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -135,7 +135,7 @@ export class MainView extends React.Component { faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt, faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTrashAlt, faAngleRight, faBell, - faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft); + faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft, faSortAmountDown); this.initEventListeners(); this.initAuthenticationRouters(); } diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 5e32b3ef8..3a4363587 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -779,7 +779,7 @@ export default class RichTextMenu extends AntimodeMenu { this.createHighlighterButton(), this.createLinkButton(), this.createBrushButton(), - this.createButton("indent", "Summarize", undefined, this.insertSummarizer), + this.createButton("sort-amount-down", "Summarize", undefined, this.insertSummarizer), this.createButton("quote-left", "Blockquote", undefined, this.insertBlockquote), ]}
; -- cgit v1.2.3-70-g09d2 From 8e9f77d93ec4393c52a215e75bcd9a362173e06a Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 24 Jun 2020 16:24:37 -0400 Subject: made persistent link Icon in bottom left of document --- src/client/views/DocumentButtonBar.tsx | 18 +++--- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/MainView.tsx | 3 + src/client/views/globalCssVariables.scss | 1 + src/client/views/linking/LinkMenu.scss | 4 ++ src/client/views/linking/LinkMenu.tsx | 37 ++++++----- src/client/views/nodes/DocumentLinksButton.scss | 39 +++++++++++ src/client/views/nodes/DocumentLinksButton.tsx | 75 ++++++++++++++++++++++ src/client/views/nodes/DocumentView.tsx | 10 +-- .../views/nodes/formattedText/RichTextMenu.tsx | 7 +- 10 files changed, 160 insertions(+), 36 deletions(-) create mode 100644 src/client/views/nodes/DocumentLinksButton.scss create mode 100644 src/client/views/nodes/DocumentLinksButton.tsx (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 62a95116f..208b4d57a 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -239,14 +239,14 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV get linkButton() { const view0 = this.view0; const linkCount = view0 && DocListCast(view0.props.Document.links).length; - return !view0 ? (null) :
- }> -
- {linkCount ? linkCount : } + return !view0 || linkCount ? (null) : +
+
+
+ {linkCount ? linkCount : } +
- -
; +
; } @computed @@ -317,9 +317,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV const considerPull = isText && this.considerGoogleDocsPull; const considerPush = isText && this.considerGoogleDocsPush; return
-
- {this.linkButton} -
+ {this.linkButton}
{this.templateButton}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index beb6155ca..d7b0ab7a9 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -552,7 +552,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> onPointerDown={this.onRadiusDown} onContextMenu={(e) => e.preventDefault()}>
-
+
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 415f8b364..374fd7421 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -55,6 +55,8 @@ import { TimelineMenu } from './animationtimeline/TimelineMenu'; import { SnappingManager } from '../util/SnappingManager'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { DocumentManager } from '../util/DocumentManager'; +import { DocumentLinksButton } from './nodes/DocumentLinksButton'; +import { LinkMenu } from './linking/LinkMenu'; @observer export class MainView extends React.Component { @@ -578,6 +580,7 @@ export class MainView extends React.Component { {this.mainContent} + {DocumentLinksButton.EditLink ? : (null)} diff --git a/src/client/views/globalCssVariables.scss b/src/client/views/globalCssVariables.scss index 4e85fe0ca..3e54d001b 100644 --- a/src/client/views/globalCssVariables.scss +++ b/src/client/views/globalCssVariables.scss @@ -12,6 +12,7 @@ $lighter-alt-accent: rgb(207, 220, 240); $darker-alt-accent: rgb(178, 206, 248); $intermediate-color: #9c9396; $dark-color: #121721; +$link-color: lightBlue; $antimodemenu-height: 35px; // fonts $sans-serif: "Noto Sans", diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss index 7dee22f66..c372e7098 100644 --- a/src/client/views/linking/LinkMenu.scss +++ b/src/client/views/linking/LinkMenu.scss @@ -8,6 +8,10 @@ .linkMenu-list { max-height: 200px; overflow-y: scroll; + position: absolute; + z-index: 10; + background: $link-color; + min-width: 150px } .linkMenu-group { diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index 56f40ad69..0fcc0f0b9 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -4,11 +4,12 @@ import { DocumentView } from "../nodes/DocumentView"; import { LinkEditor } from "./LinkEditor"; import './LinkMenu.scss'; import React = require("react"); -import { Doc } from "../../../fields/Doc"; +import { Doc, Opt } from "../../../fields/Doc"; import { LinkManager } from "../../util/LinkManager"; import { LinkMenuGroup } from "./LinkMenuGroup"; import { faTrash } from '@fortawesome/free-solid-svg-icons'; import { library } from "@fortawesome/fontawesome-svg-core"; +import { DocumentLinksButton } from "../nodes/DocumentLinksButton"; library.add(faTrash); @@ -16,16 +17,29 @@ interface Props { docView: DocumentView; changeFlyout: () => void; addDocTab: (document: Doc, where: string) => boolean; + location: number[]; } @observer export class LinkMenu extends React.Component { @observable private _editingLink?: Doc; + @observable private _linkMenuRef: Opt; + @action + onClick = (e: PointerEvent) => { + if (!Array.from(this._linkMenuRef?.getElementsByTagName((e.target as HTMLElement).tagName) || []).includes(e.target as any)) { + DocumentLinksButton.EditLink = undefined; + } + } @action componentDidMount() { this._editingLink = undefined; + document.addEventListener("pointerdown", this.onClick); + } + + componentWillUnmount() { + document.removeEventListener("pointerdown", this.onClick); } clearAllLinks = () => { @@ -56,20 +70,11 @@ export class LinkMenu extends React.Component { render() { const sourceDoc = this.props.docView.props.Document; const groups: Map = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc); - if (this._editingLink === undefined) { - return ( -
- {/* */} - {/* */} -
- {this.renderAllGroups(groups)} -
-
- ); - } else { - return ( - this._editingLink = undefined)}> - ); - } + return
this._linkMenuRef = r} style={{ left: this.props.location[0], top: this.props.location[1] }}> + {!this._editingLink ? + this.renderAllGroups(groups) : + this._editingLink = undefined)} /> + } +
; } } \ No newline at end of file diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss new file mode 100644 index 000000000..b9d5d437b --- /dev/null +++ b/src/client/views/nodes/DocumentLinksButton.scss @@ -0,0 +1,39 @@ +@import "../globalCssVariables.scss"; + + +.documentLinksButton-button-empty:hover { + background: $main-accent; + transform: scale(1.05); + cursor: pointer; +} + +.documentLinksButton-button-nonempty:hover { + background: $main-accent; + transform: scale(1.05); + cursor: pointer; +} + +.documentLinksButton-button-empty, +.documentLinksButton-button-nonempty { + height: 20px; + width: 20px; + border-radius: 50%; + opacity: 0.9; + pointer-events: auto; + background-color: $link-color; + color: black; + text-transform: uppercase; + letter-spacing: 2px; + font-size: 75%; + transition: transform 0.2s; + text-align: center; + display: flex; + justify-content: center; + align-items: center; + + &:hover { + background: $main-accent; + transform: scale(1.05); + cursor: pointer; + } +} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx new file mode 100644 index 000000000..4f94b06cb --- /dev/null +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -0,0 +1,75 @@ +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { computed, action, runInAction, observable } from "mobx"; +import { observer } from "mobx-react"; +import './DocumentLinksButton.scss'; +import React = require("react"); +import { emptyFunction, setupMoveUpEvents } from "../../../Utils"; +import { DocListCast, Doc } from "../../../fields/Doc"; +import { DocumentView } from "./DocumentView"; +import { LinkMenu } from "../linking/LinkMenu"; +import { UndoManager } from "../../util/UndoManager"; +import { DragManager } from "../../util/DragManager"; +const higflyout = require("@hig/flyout"); +export const { anchorPoints } = higflyout; +export const Flyout = higflyout.default; + +interface DocumentLinksButtonProps { + View: DocumentView; +} +@observer +export class DocumentLinksButton extends React.Component { + private _linkButton = React.createRef(); + + @action + onLinkButtonMoved = (e: PointerEvent) => { + if (this._linkButton.current !== null) { + const linkDrag = UndoManager.StartBatch("Drag Link"); + this.props.View && DragManager.StartLinkDrag(this._linkButton.current, this.props.View.props.Document, e.pageX, e.pageY, { + dragComplete: dropEv => { + const linkDoc = dropEv.linkDragData?.linkDocument as Doc; // equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop + if (this.props.View && linkDoc) { + !linkDoc.linkRelationship && (Doc.GetProto(linkDoc).linkRelationship = "hyperlink"); + + // we want to allow specific views to handle the link creation in their own way (e.g., rich text makes text hyperlinks) + // the dragged view can regiser a linkDropCallback to be notified that the link was made and to update their data structures + // however, the dropped document isn't so accessible. What we do is set the newly created link document on the documentView + // The documentView passes a function prop returning this link doc to its descendants who can react to changes to it. + dropEv.linkDragData?.linkDropCallback?.(dropEv.linkDragData); + runInAction(() => this.props.View._link = linkDoc); + setTimeout(action(() => this.props.View._link = undefined), 0); + } + linkDrag?.end(); + }, + hideSource: false + }); + return true; + } + return false; + } + + onLinkButtonDown = (e: React.PointerEvent): void => { + setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, action((e) => { + DocumentLinksButton.EditLink = this.props.View; + DocumentLinksButton.EditLinkLoc = [e.clientX, e.clientY]; + })); + } + + @observable + public static EditLink: DocumentView | undefined; + public static EditLinkLoc: number[] = [0, 0]; + + @computed + get linkButton() { + const view0 = this.props.View; + const linkCount = view0 && DocListCast(view0.props.Document.links).length; + return !view0 || !linkCount ? (null) : +
+
+ {linkCount ? linkCount : } +
+
; + } + render() { + return this.linkButton; + } +} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7e20b40a3..d9a211e7a 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -41,6 +41,7 @@ import "./DocumentView.scss"; import { LinkAnchorBox } from './LinkAnchorBox'; import { RadialMenu } from './RadialMenu'; import React = require("react"); +import { DocumentLinksButton } from './DocumentLinksButton'; library.add(fa.faEdit, fa.faTrash, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faCompressArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faAlignCenter, fa.faCaretSquareRight, fa.faSquare, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faLink, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, fa.faLock, fa.faLaptopCode, fa.faMale, @@ -735,10 +736,8 @@ export class DocumentView extends DocComponent(Docu const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : []; const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null); templateDoc && optionItems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, "onRight"), icon: "eye" }); - if (!options) { - options = { description: "Options...", subitems: optionItems, icon: "compass" }; - cm.addItem(options); - } + optionItems.push({ description: "Toggle Show Each Link Dot", event: () => this.layoutDoc.showLinks = !this.layoutDoc.showLinks, icon: "eye" }); + !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" }); const existingOnClick = cm.findByDescription("OnClick..."); const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; @@ -1037,7 +1036,8 @@ export class DocumentView extends DocComponent(Docu select={this.select} onClick={this.onClickHandler} layoutKey={this.finalLayoutKey} /> - {this.anchors} + {this.layoutDoc.showLinks ? this.anchors : (null)} + {this.props.forcedBackgroundColor?.(this.Document) === "transparent" ? (null) : }
); } diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 3a4363587..839943aac 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -11,7 +11,7 @@ import { EditorState, NodeSelection, TextSelection } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import { Doc } from "../../../../fields/Doc"; import { DarkPastelSchemaPalette, PastelSchemaPalette } from '../../../../fields/SchemaHeaderField'; -import { Cast, StrCast } from "../../../../fields/Types"; +import { Cast, StrCast, BoolCast } from "../../../../fields/Types"; import { unimplementedFunction, Utils } from "../../../../Utils"; import { DocServer } from "../../../DocServer"; import { LinkManager } from "../../../util/LinkManager"; @@ -72,7 +72,7 @@ export default class RichTextMenu extends AntimodeMenu { super(props); RichTextMenu.Instance = this; this._canFade = false; - this.Pinned = true; + this.Pinned = BoolCast(Doc.UserDoc()["menuRichText-pinned"]); this.fontSizeOptions = [ { mark: schema.marks.pFontSize.create({ fontSize: 7 }), title: "Set font size", label: "7pt", command: this.changeFontSize }, @@ -147,7 +147,6 @@ export default class RichTextMenu extends AntimodeMenu { this.updateFromDash(view, lastState, this.editorProps); } - public MakeLinkToSelection = (linkDocId: string, title: string, location: string, targetDocId: string): string => { if (this.view) { const link = this.view.state.schema.marks.link.create({ href: Utils.prepend("/doc/" + linkDocId), title: title, location: location, linkId: linkDocId, targetId: targetDocId }); @@ -750,7 +749,7 @@ export default class RichTextMenu extends AntimodeMenu { @action toggleMenuPin = (e: React.MouseEvent) => { - this.Pinned = !this.Pinned; + Doc.UserDoc()["menuRichText-pinned"] = this.Pinned = !this.Pinned; if (!this.Pinned) { this.fadeOut(true); } -- cgit v1.2.3-70-g09d2 From ba42ca25ae828b6279f618dea87f7cd37a3b3814 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 25 Jun 2020 00:19:40 -0400 Subject: added link preview for blue buttons. --- src/client/util/DragManager.ts | 2 +- src/client/views/DocumentButtonBar.tsx | 2 +- src/client/views/MainView.tsx | 4 + src/client/views/nodes/DocumentLinksButton.scss | 28 ++----- src/client/views/nodes/DocumentLinksButton.tsx | 15 +++- src/client/views/nodes/DocumentView.tsx | 10 ++- src/client/views/nodes/LinkAnchorBox.tsx | 8 ++ src/client/views/nodes/LinkDocPreview.tsx | 107 ++++++++++++++++++++++++ 8 files changed, 148 insertions(+), 28 deletions(-) create mode 100644 src/client/views/nodes/LinkDocPreview.tsx (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 91bc51101..417ddf989 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -353,7 +353,7 @@ export namespace DragManager { const dragElement = ele.parentNode === dragDiv ? ele : ele.cloneNode(true) as HTMLElement; const rect = ele.getBoundingClientRect(); const scaleX = rect.width / ele.offsetWidth, - scaleY = rect.height / ele.offsetHeight; + scaleY = ele.offsetHeight ? rect.height / ele.offsetHeight : scaleX; elesCont.left = Math.min(rect.left, elesCont.left); elesCont.top = Math.min(rect.top, elesCont.top); elesCont.right = Math.max(rect.right, elesCont.right); diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 8cd1b650e..106b7163e 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -248,7 +248,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV get linkButton() { const view0 = this.view0; const linkCount = view0 && DocListCast(view0.props.Document.links).length; - return !view0 || linkCount ? (null) : + return !view0 ? (null) :
{DocumentLinksButton.EditLink ? : (null)} + {LinkDocPreview.LinkInfo ? : (null)} diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss index b4c59b91c..79364ab8e 100644 --- a/src/client/views/nodes/DocumentLinksButton.scss +++ b/src/client/views/nodes/DocumentLinksButton.scss @@ -1,21 +1,9 @@ @import "../globalCssVariables.scss"; -.documentLinksButton-button-empty:hover { - background: $main-accent; - transform: scale(1.05); - cursor: pointer; -} - -.documentLinksButton-button-nonempty:hover { - background: $main-accent; - transform: scale(1.05); - cursor: pointer; -} - -.documentLinksButton-button, -.documentLinksButton-button-empty, -.documentLinksButton-button-nonempty { +.documentLinksButton, +.documentLinksButton-endLink, +.documentLinksButton-startLink { height: 20px; width: 20px; left: -15px; @@ -34,18 +22,18 @@ align-items: center; &:hover { - background: $main-accent; + background: deepskyblue; transform: scale(1.05); - cursor: pointer; + cursor: default; } } -.documentLinksButton-button-nonempty { +.documentLinksButton { background-color: $link-color; } -.documentLinksButton-button-empty { +.documentLinksButton-endLink { border: red solid 2px; } -.documentLinksButton-button { +.documentLinksButton-startLink { border: red solid 2px; background-color: rgba(255, 192, 203, 0.5); } \ No newline at end of file diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index c9083a65f..fc314ae8b 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -9,6 +9,7 @@ import { DocumentView } from "./DocumentView"; import React = require("react"); import { DocUtils } from "../../documents/Documents"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { LinkDocPreview } from "./LinkDocPreview"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -80,11 +81,19 @@ export class DocumentLinksButton extends React.Component -
+
LinkDocPreview.LinkInfo = undefined)} + onPointerEnter={action(e => LinkDocPreview.LinkInfo = { + addDocTab: this.props.View.props.addDocTab, + linkSrc: this.props.View.props.Document, + linkDoc: links[0], + Location: [e.clientX, e.clientY + 20] + })} > {links.length ? links.length : }
- {DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View ?
: (null)} - {DocumentLinksButton.StartLink === this.props.View ?
: (null)} + {DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View ?
: (null)} + {DocumentLinksButton.StartLink === this.props.View ?
: (null)}
; } render() { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 20a606937..4cb08bab3 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1047,7 +1047,7 @@ export class DocumentView extends DocComponent(Docu onClick={this.onClickHandler} layoutKey={this.finalLayoutKey} /> {this.layoutDoc.showLinks ? this.anchors : (null)} - {this.props.forcedBackgroundColor?.(this.Document) === "transparent" ? (null) : } + {this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.props.dontRegisterView ? (null) : }
); } @@ -1071,7 +1071,7 @@ export class DocumentView extends DocComponent(Docu anchorPanelHeight = () => this.props.PanelHeight() || 1; @computed get anchors() { TraceMobx(); - return this.layoutDoc.presBox ? (null) : DocListCast(this.Document.links).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) => + return this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.layoutDoc.presBox || this.props.dontRegisterView ? (null) : DocListCast(this.Document.links).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) => (Docu PanelWidth={this.anchorPanelWidth} PanelHeight={this.anchorPanelHeight} ContentScaling={returnOne} + dontRegisterView={false} forcedBackgroundColor={returnTransparent} removeDocument={this.hideLinkAnchor} pointerEvents={false} @@ -1202,7 +1203,10 @@ export class DocumentView extends DocComponent(Docu color: StrCast(this.layoutDoc.color, "inherit"), outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px", border: highlighting && borderRounding ? `${highlightStyles[fullDegree]} ${highlightColors[fullDegree]} ${localScale}px` : undefined, - boxShadow: this.Document.isLinkButton ? StrCast(this.props.Document._linkButtonShadow, "lightblue 0em 0em 1em") : this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : undefined, + boxShadow: this.Document.isLinkButton && !this.props.dontRegisterView && this.props.forcedBackgroundColor?.(this.Document) !== "transparent" ? + StrCast(this.props.Document._linkButtonShadow, "lightblue 0em 0em 1em") : + this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : + undefined, background: finalColor, opacity: finalOpacity, fontFamily: StrCast(this.Document._fontFamily, "inherit"), diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index 2b64cdab6..2bcc6168b 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -18,6 +18,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { SelectionManager } from "../../util/SelectionManager"; import { TraceMobx } from "../../../fields/util"; import { Id } from "../../../fields/FieldSymbols"; +import { LinkDocPreview } from "./LinkDocPreview"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -132,6 +133,13 @@ export class LinkAnchorBox extends ViewBoxBaseComponent LinkDocPreview.LinkInfo = undefined)} + onPointerEnter={action(e => LinkDocPreview.LinkInfo = { + addDocTab: this.props.addDocTab, + linkSrc: this.props.ContainingCollectionDoc!, + linkDoc: this.rootDoc, + Location: [e.clientX, e.clientY + 20] + })} onPointerDown={this.onPointerDown} onClick={this.onClick} title={targetTitle} onContextMenu={this.specificContextMenu} ref={this._ref} style={{ background: c, diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx new file mode 100644 index 000000000..126dc240a --- /dev/null +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -0,0 +1,107 @@ +import { action, computed, observable, runInAction } from 'mobx'; +import { observer } from "mobx-react"; +import wiki from "wikijs"; +import { Doc, DocCastAsync, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; +import { Cast, FieldValue, NumCast } from "../../../fields/Types"; +import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero } from "../../../Utils"; +import { Docs } from "../../documents/Documents"; +import { DocumentManager } from "../../util/DocumentManager"; +import { Transform } from "../../util/Transform"; +import { ContentFittingDocumentView } from "./ContentFittingDocumentView"; +import React = require("react"); +import { DocumentView } from './DocumentView'; + +interface Props { + linkDoc?: Doc; + linkSrc?: Doc; + href?: string; + backgroundColor: (doc: Doc) => string; + addDocTab: (document: Doc, where: string) => boolean; + location: number[]; +} +@observer +export class LinkDocPreview extends React.Component { + @observable public static LinkInfo: Opt<{ linkDoc?: Doc; addDocTab: (document: Doc, where: string) => boolean, linkSrc: Doc; href?: string; Location: number[] }>; + @observable _targetDoc: Opt; + @observable _toolTipText = ""; + + componentDidUpdate() { this.updatePreview() } + componentDidMount() { this.updatePreview() } + async updatePreview() { + const linkDoc = this.props.linkDoc; + const linkSrc = this.props.linkSrc; + if (this.props.href) { + if (this.props.href.startsWith("https://en.wikipedia.org/wiki/")) { + wiki().page(this.props.href.replace("https://en.wikipedia.org/wiki/", "")).then(page => page.summary().then(action(summary => this._toolTipText = summary.substring(0, 500)))); + } else { + runInAction(() => this._toolTipText = "external => " + this.props.href); + } + } else if (linkDoc && linkSrc) { + const anchor = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(linkDoc.anchor1, Doc)), linkSrc) ? Cast(linkDoc.anchor2, Doc) : (Cast(linkDoc.anchor1, Doc)) || linkDoc); + const target = anchor?.annotationOn ? await DocCastAsync(anchor.annotationOn) : anchor; + runInAction(() => { + this._toolTipText = ""; + this._targetDoc = target; + if (anchor !== this._targetDoc && anchor && this._targetDoc) { + this._targetDoc._scrollY = NumCast(anchor?.y); + } + }); + } + } + pointerDown = (e: React.PointerEvent) => { + if (this.props.linkDoc && this.props.linkSrc) { + DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.linkSrc, + (doc: Doc, followLinkLocation: string) => this.props.addDocTab(doc, e.ctrlKey ? "inTab" : followLinkLocation)); + } else if (this.props.href) { + this.props.addDocTab(Docs.Create.WebDocument(this.props.href, { title: this.props.href, _width: 200, _height: 400, UseCors: true }), "onRight"); + } + } + width = () => Math.min(350, NumCast(this._targetDoc?.[WidthSym](), 350)); + height = () => Math.min(350, NumCast(this._targetDoc?.[HeightSym](), 350)); + @computed get targetDocView() { + return !this._targetDoc ? +
+
+ {this._toolTipText} +
+
: + ; + } + + render() { + return
+ {this.targetDocView} +
; + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2