diff options
9 files changed, 159 insertions, 132 deletions
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index a3d6f5227..646942569 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -1,9 +1,10 @@ import { action, observable, ObservableMap } from 'mobx'; import { computedFn } from 'mobx-utils'; -import { Doc, Opt } from '../../fields/Doc'; +import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { DocCast } from '../../fields/Types'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { DocumentView } from '../views/nodes/DocumentView'; +import { LinkManager } from './LinkManager'; import { ScriptingGlobals } from './ScriptingGlobals'; export namespace SelectionManager { @@ -21,6 +22,9 @@ export namespace SelectionManager { // if doc is not in SelectedDocuments, add it if (!manager.SelectedViews.get(docView) && docView.props.Document.type !== DocumentType.MARKER) { if (!ctrlPressed) { + if (LinkManager.currentLink && !DocListCast(docView.rootDoc.links).includes(LinkManager.currentLink) && docView.rootDoc !== LinkManager.currentLink) { + LinkManager.currentLink = undefined; + } this.DeselectAll(); } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 09063901d..165bb69bb 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -3,15 +3,15 @@ import { faBuffer, faHireAHelper } from '@fortawesome/free-brands-svg-icons'; import * as far from '@fortawesome/free-regular-svg-icons'; import * as fa from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import 'browndash-components/dist/styles/global.min.css'; import { action, computed, configure, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import 'normalize.css'; import * as React from 'react'; -import * as ReactDOM from 'react-dom/client'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { ScriptField } from '../../fields/ScriptField'; import { DocCast, StrCast } from '../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick, Utils } from '../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../Utils'; import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; import { Docs, DocUtils } from '../documents/Documents'; @@ -58,14 +58,12 @@ import { LinkDocPreview } from './nodes/LinkDocPreview'; import { RadialMenu } from './nodes/RadialMenu'; import { TaskCompletionBox } from './nodes/TaskCompletedBox'; import { PresBox } from './nodes/trails'; -import { WebBox } from './nodes/WebBox'; import { OverlayView } from './OverlayView'; import { AnchorMenu } from './pdf/AnchorMenu'; import { PreviewCursor } from './PreviewCursor'; import { PropertiesView } from './PropertiesView'; import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider'; import { TopBar } from './topbar/TopBar'; -import 'browndash-components/dist/styles/global.min.css'; const _global = (window /* browser */ || global) /* node */ as any; @observer diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index e8fd540a8..05dd376f2 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -1549,6 +1549,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const zoom = Number((NumCast(this.sourceAnchor?.presZoom, 1) * 100).toPrecision(3)); const targZoom = this.sourceAnchor?.followLinkZoom; const indent = 30; + const hasSelectedAnchor = SelectionManager.Views().some(dv => DocListCast(this.sourceAnchor?.links).includes(LinkManager.currentLink!)); if (!this.selectedDoc && !this.isPres) { return ( <div className="propertiesView" style={{ width: this.props.width }}> @@ -1575,7 +1576,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { {this.contextsSubMenu} {this.linksSubMenu} - {!this.selectedDoc || !LinkManager.currentLink || !SelectionManager.Views().some(dv => DocListCast(this.sourceAnchor?.links).includes(LinkManager.currentLink!)) ? null : ( + {!this.selectedDoc || !LinkManager.currentLink || (!hasSelectedAnchor && this.selectedDoc !== LinkManager.currentLink) ? null : ( <> <div className="propertiesView-section" style={{ background: 'darkgray' }}> <div className="propertiesView-input first" style={{ display: 'grid', gridTemplateColumns: '84px auto' }}> @@ -1617,108 +1618,110 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { </button> </div> </div> - <div className="propertiesView-section"> - <div className="propertiesView-input inline first" style={{ display: 'grid', gridTemplateColumns: '84px calc(100% - 84px)' }}> - <p>Follow by</p> - <select onChange={e => this.changeFollowBehavior(e.currentTarget.value)} value={StrCast(this.sourceAnchor?.followLinkLocation, 'default')}> - <option value="default">Default</option> - <option value="add:left">Opening in new left pane</option> - <option value="add:right">Opening in new right pane</option> - <option value="replace:left">Replacing left tab</option> - <option value="replace:right">Replacing right tab</option> - <option value="fullScreen">Opening full screen</option> - <option value="add">Opening in new tab</option> - <option value="replace">Replacing current tab</option> - <option value="inPlace">Opening in place</option> - {LinkManager.currentLink?.linksToAnnotation ? <option value="openExternal">Open in external page</option> : null} - </select> - </div> - <div className="propertiesView-input inline first" style={{ display: 'grid', gridTemplateColumns: '84px calc(100% - 134px) 50px' }}> - <p>Animation</p> - <select style={{ width: '100%', gridColumn: 2 }} onChange={e => this.changeAnimationBehavior(e.currentTarget.value)} value={StrCast(this.sourceAnchor?.presEffect, 'default')}> - <option value="default">Default</option> - {[PresEffect.None, PresEffect.Zoom, PresEffect.Lightspeed, PresEffect.Fade, PresEffect.Flip, PresEffect.Rotate, PresEffect.Bounce, PresEffect.Roll].map(effect => ( - <option value={effect.toString()}>{effect.toString()}</option> - ))} - </select> - <div className="effectDirection" style={{ marginLeft: '10px', display: 'grid', width: 40, height: 36, gridColumn: 3, gridTemplateRows: '12px 12px 12px' }}> - {this.animationDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})} - {this.animationDirection(PresEffectDirection.Right, 'angle-left', 3, 2, {})} - {this.animationDirection(PresEffectDirection.Top, 'angle-down', 2, 1, {})} - {this.animationDirection(PresEffectDirection.Bottom, 'angle-up', 2, 3, {})} - {this.animationDirection(PresEffectDirection.Center, '', 2, 2, { width: 10, height: 10, alignSelf: 'center' })} + {!hasSelectedAnchor ? null : ( + <div className="propertiesView-section"> + <div className="propertiesView-input inline first" style={{ display: 'grid', gridTemplateColumns: '84px calc(100% - 84px)' }}> + <p>Follow by</p> + <select onChange={e => this.changeFollowBehavior(e.currentTarget.value)} value={StrCast(this.sourceAnchor?.followLinkLocation, 'default')}> + <option value="default">Default</option> + <option value="add:left">Opening in new left pane</option> + <option value="add:right">Opening in new right pane</option> + <option value="replace:left">Replacing left tab</option> + <option value="replace:right">Replacing right tab</option> + <option value="fullScreen">Opening full screen</option> + <option value="add">Opening in new tab</option> + <option value="replace">Replacing current tab</option> + <option value="inPlace">Opening in place</option> + {LinkManager.currentLink?.linksToAnnotation ? <option value="openExternal">Open in external page</option> : null} + </select> </div> - </div> - {PresBox.inputter( - '0.1', - '0.1', - '10', - NumCast(this.sourceAnchor?.presTransition) / 1000, - true, - (val: string) => PresBox.SetTransitionTime(val, (timeInMS: number) => this.sourceAnchor && (this.sourceAnchor.presTransition = timeInMS)), - indent - )}{' '} - <div - className={'slider-headers'} - style={{ - display: 'grid', - justifyContent: 'space-between', - width: `calc(100% - ${indent * 2}px)`, - marginLeft: indent, - marginRight: indent, - gridTemplateColumns: 'auto auto', - borderTop: 'solid', - }}> - <div className="slider-text">Fast</div> - <div className="slider-text">Slow</div> - </div>{' '} - <div className="propertiesView-input inline"> - <p>Play Target Audio</p> - <button - style={{ background: !this.sourceAnchor?.followLinkAudio ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkAudio', this.sourceAnchor)} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline" style={{ display: 'grid', gridTemplateColumns: '78px calc(100% - 108px) 50px' }}> - <p>Zoom %</p> - <div className="ribbon-property" style={{ display: !targZoom ? 'none' : 'inline-flex' }}> - <input className="presBox-input" style={{ width: '100%' }} type="number" value={zoom} /> - <div className="ribbon-propertyUpDown" style={{ display: 'flex', flexDirection: 'column' }}> - <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), 0.1))}> - <FontAwesomeIcon icon={'caret-up'} /> - </div> - <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), -0.1))}> - <FontAwesomeIcon icon={'caret-down'} /> + <div className="propertiesView-input inline first" style={{ display: 'grid', gridTemplateColumns: '84px calc(100% - 134px) 50px' }}> + <p>Animation</p> + <select style={{ width: '100%', gridColumn: 2 }} onChange={e => this.changeAnimationBehavior(e.currentTarget.value)} value={StrCast(this.sourceAnchor?.presEffect, 'default')}> + <option value="default">Default</option> + {[PresEffect.None, PresEffect.Zoom, PresEffect.Lightspeed, PresEffect.Fade, PresEffect.Flip, PresEffect.Rotate, PresEffect.Bounce, PresEffect.Roll].map(effect => ( + <option value={effect.toString()}>{effect.toString()}</option> + ))} + </select> + <div className="effectDirection" style={{ marginLeft: '10px', display: 'grid', width: 40, height: 36, gridColumn: 3, gridTemplateRows: '12px 12px 12px' }}> + {this.animationDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})} + {this.animationDirection(PresEffectDirection.Right, 'angle-left', 3, 2, {})} + {this.animationDirection(PresEffectDirection.Top, 'angle-down', 2, 1, {})} + {this.animationDirection(PresEffectDirection.Bottom, 'angle-up', 2, 3, {})} + {this.animationDirection(PresEffectDirection.Center, '', 2, 2, { width: 10, height: 10, alignSelf: 'center' })} + </div> + </div> + {PresBox.inputter( + '0.1', + '0.1', + '10', + NumCast(this.sourceAnchor?.presTransition) / 1000, + true, + (val: string) => PresBox.SetTransitionTime(val, (timeInMS: number) => this.sourceAnchor && (this.sourceAnchor.presTransition = timeInMS)), + indent + )}{' '} + <div + className={'slider-headers'} + style={{ + display: 'grid', + justifyContent: 'space-between', + width: `calc(100% - ${indent * 2}px)`, + marginLeft: indent, + marginRight: indent, + gridTemplateColumns: 'auto auto', + borderTop: 'solid', + }}> + <div className="slider-text">Fast</div> + <div className="slider-text">Slow</div> + </div>{' '} + <div className="propertiesView-input inline"> + <p>Play Target Audio</p> + <button + style={{ background: !this.sourceAnchor?.followLinkAudio ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkAudio', this.sourceAnchor)} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline" style={{ display: 'grid', gridTemplateColumns: '78px calc(100% - 108px) 50px' }}> + <p>Zoom %</p> + <div className="ribbon-property" style={{ display: !targZoom ? 'none' : 'inline-flex' }}> + <input className="presBox-input" style={{ width: '100%' }} type="number" value={zoom} /> + <div className="ribbon-propertyUpDown" style={{ display: 'flex', flexDirection: 'column' }}> + <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), 0.1))}> + <FontAwesomeIcon icon={'caret-up'} /> + </div> + <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), -0.1))}> + <FontAwesomeIcon icon={'caret-down'} /> + </div> </div> </div> + <button + style={{ background: !targZoom ? '' : '#4476f7', borderRadius: 3, gridColumn: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> + </button> </div> - <button - style={{ background: !targZoom ? '' : '#4476f7', borderRadius: 3, gridColumn: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> - </button> + {!targZoom ? null : PresBox.inputter('0', '1', '100', zoom, true, this.setZoom, 30)} + <div + className={'slider-headers'} + style={{ + display: !targZoom ? 'none' : 'grid', + justifyContent: 'space-between', + width: `calc(100% - ${indent * 2}px)`, + marginLeft: indent, + marginRight: indent, + gridTemplateColumns: 'auto auto', + borderTop: 'solid', + }}> + <div className="slider-text">0%</div> + <div className="slider-text">100%</div> + </div>{' '} </div> - {!targZoom ? null : PresBox.inputter('0', '1', '100', zoom, true, this.setZoom, 30)} - <div - className={'slider-headers'} - style={{ - display: !targZoom ? 'none' : 'grid', - justifyContent: 'space-between', - width: `calc(100% - ${indent * 2}px)`, - marginLeft: indent, - marginRight: indent, - gridTemplateColumns: 'auto auto', - borderTop: 'solid', - }}> - <div className="slider-text">0%</div> - <div className="slider-text">100%</div> - </div>{' '} - </div> + )} </> )} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss index 858719a08..b44acfce8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss @@ -5,15 +5,8 @@ transition: opacity 0.5s ease-in; fill: transparent; } -.collectionfreeformlinkview-linkCircle { - stroke: rgb(0,0,0); - opacity: 0.5; - pointer-events: all; - cursor: pointer; -} .collectionfreeformlinkview-linkText { - stroke: rgb(0,0,0); - opacity: 0.5; + stroke: rgb(0, 0, 0); pointer-events: all; cursor: move; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index b39fcbd48..be20bf207 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -3,7 +3,7 @@ import { observer } from 'mobx-react'; import { Doc, Field } from '../../../../fields/Doc'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; -import { Cast, NumCast } from '../../../../fields/Types'; +import { Cast, NumCast, StrCast } from '../../../../fields/Types'; import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; import { LinkManager } from '../../../util/LinkManager'; import { SelectionManager } from '../../../util/SelectionManager'; @@ -117,12 +117,16 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo return false; }, emptyFunction, - () => { + action(() => { + SelectionManager.DeselectAll(); + SelectionManager.SelectSchemaViewDoc(this.props.LinkDocs[0], true); + LinkManager.currentLink = this.props.LinkDocs[0]; + this.toggleProperties(); // OverlayView.Instance.addElement( // <LinkEditor sourceDoc={this.props.A.props.Document} linkDoc={this.props.LinkDocs[0]} // showLinks={action(() => { })} // />, { x: 300, y: 300 }); - } + }) ); }; @@ -168,8 +172,11 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo } }; + @action onClickLine = () => { + SelectionManager.DeselectAll(); SelectionManager.SelectSchemaViewDoc(this.props.LinkDocs[0], true); + LinkManager.currentLink = this.props.LinkDocs[0]; this.toggleProperties(); }; @@ -232,44 +239,65 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo render() { if (!this.renderData) return null; + const link = this.props.LinkDocs[0]; const { a, b, pt1norm, pt2norm, aActive, bActive, textX, textY, pt1, pt2 } = this.renderData; const linkRelationship = Field.toString(LinkManager.currentLink?.linkRelationship as any as Field); //get string representing relationship const linkRelationshipList = Doc.UserDoc().linkRelationshipList as List<string>; const linkColorList = Doc.UserDoc().linkColorList as List<string>; const linkRelationshipSizes = Doc.UserDoc().linkRelationshipSizes as List<number>; const currRelationshipIndex = linkRelationshipList.indexOf(linkRelationship); + const linkDescription = Field.toString(link.description as any as Field); const linkSize = currRelationshipIndex === -1 || currRelationshipIndex >= linkRelationshipSizes.length ? -1 : linkRelationshipSizes[currRelationshipIndex]; //access stroke color using index of the relationship in the color list (default black) - const stroke = currRelationshipIndex === -1 || currRelationshipIndex >= linkColorList.length ? 'black' : linkColorList[currRelationshipIndex]; + const stroke = currRelationshipIndex === -1 || currRelationshipIndex >= linkColorList.length ? StrCast(link._backgroundColor, 'black') : linkColorList[currRelationshipIndex]; // const hexStroke = this.rgbToHex(stroke) //calculate stroke width/thickness based on the relative importance of the relationshipship (i.e. how many links the relationship has) //thickness varies linearly from 3px to 12px for increasing link count const strokeWidth = linkSize === -1 ? '3px' : Math.floor(2 + 10 * (linkSize / Math.max(...linkRelationshipSizes))) + 'px'; - if (this.props.LinkDocs[0].linkDisplayArrow === undefined) { - this.props.LinkDocs[0].linkDisplayArrow = false; + if (link.linkDisplayArrow === undefined) { + link.linkDisplayArrow = false; } - return this.props.LinkDocs[0].opacity === 0 || !a.width || !b.width || (!this.props.LinkDocs[0].linkDisplay && !aActive && !bActive) ? null : ( + return link.opacity === 0 || !a.width || !b.width || (!link.linkDisplay && !aActive && !bActive) ? null : ( <> <defs> - <marker id="arrowhead" markerWidth="4" markerHeight="3" refX="0" refY="1.5" orient="auto"> - <polygon points="0 0, 3 1.5, 0 3" fill={Colors.DARK_GRAY} /> + <marker id={`${link[Id] + 'arrowhead'}`} markerWidth="4" markerHeight="3" refX="0" refY="1.5" orient="auto"> + <polygon points="0 0, 3 1.5, 0 3" fill={stroke} /> </marker> + <filter id="outline"> + <feMorphology in="SourceAlpha" result="expanded" operator="dilate" radius="1" /> + <feFlood flood-color={`${Colors.DARK_GRAY}`} /> + <feComposite in2="expanded" operator="in" /> + <feComposite in="SourceGraphic" /> + </filter> + <filter x="0" y="0" width="1" height="1" id={`${link[Id] + 'background'}`}> + <feFlood flood-color={`${StrCast(link._backgroundColor, 'white')}`} result="bg" /> + <feMerge> + <feMergeNode in="bg" /> + <feMergeNode in="SourceGraphic" /> + </feMerge> + </filter> </defs> <path + filter={LinkManager.currentLink === link ? 'url(#outline)' : ''} + fill="pink" + stroke="antiquewhite" + stroke-width="4" className="collectionfreeformlinkview-linkLine" - style={{ pointerEvents: 'all', opacity: this._opacity, stroke: SelectionManager.SelectedSchemaDoc() === this.props.LinkDocs[0] ? Colors.MEDIUM_BLUE : stroke, strokeWidth }} + style={{ pointerEvents: 'all', opacity: this._opacity, stroke, strokeWidth }} onClick={this.onClickLine} d={`M ${pt1[0]} ${pt1[1]} C ${pt1[0] + pt1norm[0]} ${pt1[1] + pt1norm[1]}, ${pt2[0] + pt2norm[0]} ${pt2[1] + pt2norm[1]}, ${pt2[0]} ${pt2[1]}`} - markerEnd={this.props.LinkDocs[0].linkDisplayArrow ? 'url(#arrowhead)' : ''} + markerEnd={link.linkDisplayArrow ? `url(#${link[Id] + 'arrowhead'})` : ''} /> - {textX === undefined ? null : ( - <text className="collectionfreeformlinkview-linkText" x={textX} y={textY} onPointerDown={this.pointerDown}> - {Field.toString(this.props.LinkDocs[0].description as any as Field)} + {textX === undefined || !linkDescription ? null : ( + <text filter={`url(#${link[Id] + 'background'})`} className="collectionfreeformlinkview-linkText" x={textX} y={textY} onPointerDown={this.pointerDown}> + <tspan> </tspan> + <tspan dy="2">{linkDescription}</tspan> + <tspan dy="2"> </tspan> </text> )} </> diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index 9e360f557..420e6a318 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -8,7 +8,7 @@ import { CollectionFreeFormLinkView } from './CollectionFreeFormLinkView'; import React = require('react'); @observer -export class CollectionFreeFormLinksView extends React.Component<React.PropsWithChildren<{}>> { +export class CollectionFreeFormLinksView extends React.Component { @computed get uniqueConnections() { return Array.from(new Set(DocumentManager.Instance.LinkedDocumentViews)) .filter(c => !LightboxView.LightboxDoc || (LightboxView.IsLightboxDocView(c.a.docViewPath) && LightboxView.IsLightboxDocView(c.b.docViewPath))) @@ -19,7 +19,6 @@ export class CollectionFreeFormLinksView extends React.Component<React.PropsWith return ( <div className="collectionfreeformlinksview-container"> <svg className="collectionfreeformlinksview-svgCanvas">{this.uniqueConnections}</svg> - {this.props.children} </div> ); } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index a020b67cd..3fd6ca803 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -17,6 +17,7 @@ import { SelectionManager } from '../../../util/SelectionManager'; import { Transform } from '../../../util/Transform'; import { undoBatch, UndoManager } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; +import { OpenWhere } from '../../nodes/DocumentView'; import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { PresBox } from '../../nodes/trails/PresBox'; import { VideoBox } from '../../nodes/VideoBox'; @@ -120,7 +121,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque const cm = ContextMenu.Instance; const [x, y] = this.Transform.transformPoint(this._downX, this._downY); if (e.key === '?') { - cm.setDefaultItem('?', (str: string) => this.props.addDocTab(Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, { _width: 400, x, y, _height: 512, _nativeWidth: 850, title: 'bing', useCors: true }), 'add:right')); + cm.setDefaultItem('?', (str: string) => this.props.addDocTab(Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, { _width: 400, x, y, _height: 512, _nativeWidth: 850, title: 'bing', useCors: true }), OpenWhere.addRight)); cm.displayMenu(this._downX, this._downY, undefined, true); e.stopPropagation(); diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index c71552a6f..fe8c85e5e 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -13,6 +13,7 @@ import { WebField } from '../../../../fields/URLField'; import { GestureUtils } from '../../../../pen-gestures/GestureUtils'; import { aggregateBounds, StopEvent, Utils } from '../../../../Utils'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; +import { LinkManager } from '../../../util/LinkManager'; import { ScriptingGlobals } from '../../../util/ScriptingGlobals'; import { SelectionManager } from '../../../util/SelectionManager'; import { undoBatch, UndoManager } from '../../../util/UndoManager'; @@ -547,11 +548,11 @@ ScriptingGlobals.add(function setView(view: string) { // toggle: Set overlay status of selected document ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) { - const selected = SelectionManager.Views().lastElement(); + const selected = SelectionManager.Views().lastElement()?.props.Document ?? LinkManager.currentLink; if (checkResult) { - return selected?.props.Document._backgroundColor ?? 'transparent'; + return selected?._backgroundColor ?? 'transparent'; } - if (selected) selected.props.Document._backgroundColor = color; + if (selected) selected._backgroundColor = color; }); // toggle: Set overlay status of selected document diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index c6cabe269..40152551e 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1265,6 +1265,7 @@ export namespace Doc { } export function linkFollowUnhighlight() { + UnhighlightWatchers.forEach(watcher => watcher()); UnhighlightWatchers.length = 0; highlightedDocs.forEach(doc => Doc.UnHighlightDoc(doc)); document.removeEventListener('pointerdown', linkFollowUnhighlight); @@ -1284,7 +1285,6 @@ export namespace Doc { document.addEventListener('pointerdown', linkFollowUnhighlight); if (UnhighlightTimer) clearTimeout(UnhighlightTimer); UnhighlightTimer = window.setTimeout(() => { - UnhighlightWatchers.forEach(watcher => watcher()); linkFollowUnhighlight(); UnhighlightTimer = 0; }, 5000); |