diff options
| author | mehekj <mehek.jethani@gmail.com> | 2023-01-28 22:39:23 -0500 |
|---|---|---|
| committer | mehekj <mehek.jethani@gmail.com> | 2023-01-28 22:39:23 -0500 |
| commit | 9f139c7f0f571bdfea8ce99fc0a507724eb8fd74 (patch) | |
| tree | 4de6642112f9c6c2df1a85cf8fa9ed700bb94cbd /src/client/views/pdf | |
| parent | 9d2af1180f0dd5af5ab86b922cd8b0cdfcf4ea09 (diff) | |
| parent | 95b8a5a2b470d3118b6eeac484a45b23df2830b4 (diff) | |
Merge branch 'master' into schema-mehek
Diffstat (limited to 'src/client/views/pdf')
| -rw-r--r-- | src/client/views/pdf/AnchorMenu.tsx | 154 | ||||
| -rw-r--r-- | src/client/views/pdf/Annotation.tsx | 27 | ||||
| -rw-r--r-- | src/client/views/pdf/PDFViewer.tsx | 4 |
3 files changed, 88 insertions, 97 deletions
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index 265328036..c53cc608c 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -17,6 +17,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { static Instance: AnchorMenu; private _disposer: IReactionDisposer | undefined; + private _disposer2: IReactionDisposer | undefined; private _commentCont = React.createRef<HTMLButtonElement>(); private _palette = [ 'rgba(208, 2, 27, 0.8)', @@ -36,9 +37,6 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { 'rgba(0, 0, 0, 0.8)', ]; - @observable private _keyValue: string = ''; - @observable private _valueValue: string = ''; - @observable private _added: boolean = false; @observable private highlightColor: string = 'rgba(245, 230, 95, 0.616)'; @observable private _showLinkPopup: boolean = false; @@ -52,13 +50,13 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { public OnAudio: (e: PointerEvent) => void = unimplementedFunction; public StartDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; public StartCropDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; - public Highlight: (color: string, isPushpin: boolean) => Opt<Doc> = (color: string, isPushpin: boolean) => undefined; - public GetAnchor: (savedAnnotations?: ObservableMap<number, HTMLDivElement[]>) => Opt<Doc> = () => undefined; + public Highlight: (color: string, isTargetToggler: boolean, savedAnnotations?: ObservableMap<number, HTMLDivElement[]>, addAsAnnotation?: boolean) => Opt<Doc> = (color: string, isTargetToggler: boolean) => undefined; + public GetAnchor: (savedAnnotations: Opt<ObservableMap<number, HTMLDivElement[]>>, addAsAnnotation: boolean) => Opt<Doc> = (savedAnnotations: Opt<ObservableMap<number, HTMLDivElement[]>>, addAsAnnotation: boolean) => undefined; public Delete: () => void = unimplementedFunction; - public AddTag: (key: string, value: string) => boolean = returnFalse; public PinToPres: () => void = unimplementedFunction; - public MakePushpin: () => void = unimplementedFunction; - public IsPushpin: () => boolean = returnFalse; + public MakeTargetToggle: () => void = unimplementedFunction; + public ShowTargetTrail: () => void = unimplementedFunction; + public IsTargetToggler: () => boolean = returnFalse; public get Active() { return this._left > 0; } @@ -70,7 +68,17 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { AnchorMenu.Instance._canFade = false; } + componentWillUnmount() { + this._disposer?.(); + this._disposer2?.(); + } + componentDidMount() { + this._disposer2 = reaction( + () => this._opacity, + opacity => !opacity && (this._showLinkPopup = false), + { fireImmediately: true } + ); this._disposer = reaction( () => SelectionManager.Views(), selected => { @@ -112,7 +120,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { @action highlightClicked = (e: React.MouseEvent) => { - if (!this.Highlight(this.highlightColor, false) && this.Pinned) { + if (!this.Highlight(this.highlightColor, false, undefined, true) && this.Pinned) { this.Highlighting = !this.Highlighting; } AnchorMenu.Instance.fadeOut(true); @@ -174,82 +182,62 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { this.highlightColor = Utils.colorString(col); }; - @action keyChanged = (e: React.ChangeEvent<HTMLInputElement>) => { - this._keyValue = e.currentTarget.value; - }; - @action valueChanged = (e: React.ChangeEvent<HTMLInputElement>) => { - this._valueValue = e.currentTarget.value; - }; - @action addTag = (e: React.PointerEvent) => { - if (this._keyValue.length > 0 && this._valueValue.length > 0) { - this._added = this.AddTag(this._keyValue, this._valueValue); - setTimeout( - action(() => (this._added = false)), - 1000 - ); - } - }; - render() { const buttons = - this.Status === 'marquee' - ? [ - this.highlighter, - - <Tooltip key="annotate" title={<div className="dash-tooltip">{'Drag to Place Annotation'}</div>}> - <button className="antimodeMenu-button annotate" ref={this._commentCont} onPointerDown={this.pointerDown} style={{ cursor: 'grab' }}> - <FontAwesomeIcon icon="comment-alt" size="lg" /> - </button> - </Tooltip>, - AnchorMenu.Instance.OnAudio === unimplementedFunction ? ( - <></> - ) : ( - <Tooltip key="annoaudiotate" title={<div className="dash-tooltip">{'Click to Record Annotation'}</div>}> - <button className="antimodeMenu-button annotate" onPointerDown={this.audioDown} style={{ cursor: 'grab' }}> - <FontAwesomeIcon icon="microphone" size="lg" /> - </button> - </Tooltip> - ), - <Tooltip key="link" title={<div className="dash-tooltip">{'Find document to link to selected text'}</div>}> - <button className="antimodeMenu-button link" onPointerDown={this.toggleLinkPopup} style={{}}> - <FontAwesomeIcon style={{ position: 'absolute', transform: 'scale(1.5)' }} icon={'search'} size="lg" /> - <FontAwesomeIcon style={{ position: 'absolute', transform: 'scale(0.5)', transformOrigin: 'top left', top: 12, left: 12 }} icon={'link'} size="lg" /> - </button> - </Tooltip>, - <LinkPopup key="popup" showPopup={this._showLinkPopup} linkCreateAnchor={this.onMakeAnchor} />, - AnchorMenu.Instance.StartCropDrag === unimplementedFunction ? ( - <></> - ) : ( - <Tooltip key="crop" title={<div className="dash-tooltip">{'Click/Drag to create cropped image'}</div>}> - <button className="antimodeMenu-button annotate" onPointerDown={this.cropDown} style={{ cursor: 'grab' }}> - <FontAwesomeIcon icon="image" size="lg" /> - </button> - </Tooltip> - ), - ] - : [ - <Tooltip key="trash" title={<div className="dash-tooltip">{'Remove Link Anchor'}</div>}> - <button className="antimodeMenu-button" onPointerDown={this.Delete}> - <FontAwesomeIcon icon="trash-alt" size="lg" /> - </button> - </Tooltip>, - <Tooltip key="Pin" title={<div className="dash-tooltip">{'Pin to Presentation'}</div>}> - <button className="antimodeMenu-button" onPointerDown={this.PinToPres}> - <FontAwesomeIcon icon="map-pin" size="lg" /> - </button> - </Tooltip>, - <Tooltip key="pushpin" title={<div className="dash-tooltip">{'toggle pushpin behavior'}</div>}> - <button className="antimodeMenu-button" style={{ color: this.IsPushpin() ? 'black' : 'white', backgroundColor: this.IsPushpin() ? 'white' : 'black' }} onPointerDown={this.MakePushpin}> - <FontAwesomeIcon icon="thumbtack" size="lg" /> - </button> - </Tooltip>, - // <div key="7" className="anchorMenu-addTag" > - // <input onChange={this.keyChanged} placeholder="Key" style={{ gridColumn: 1 }} /> - // <input onChange={this.valueChanged} placeholder="Value" style={{ gridColumn: 3 }} /> - // </div>, - // <button key="8" className="antimodeMenu-button" title={`Add tag: ${this._keyValue} with value: ${this._valueValue}`} onPointerDown={this.addTag}> - // <FontAwesomeIcon style={{ transition: "all .2s" }} color={this._added ? "#42f560" : "white"} icon="check" size="lg" /></button>, - ]; + this.Status === 'marquee' ? ( + <> + {this.highlighter} + <Tooltip key="annotate" title={<div className="dash-tooltip">Drag to Place Annotation</div>}> + <button className="antimodeMenu-button annotate" ref={this._commentCont} onPointerDown={this.pointerDown} style={{ cursor: 'grab' }}> + <FontAwesomeIcon icon="comment-alt" size="lg" /> + </button> + </Tooltip> + {AnchorMenu.Instance.OnAudio === unimplementedFunction ? null : ( + <Tooltip key="annoaudiotate" title={<div className="dash-tooltip">Click to Record Annotation</div>}> + <button className="antimodeMenu-button annotate" onPointerDown={this.audioDown} style={{ cursor: 'grab' }}> + <FontAwesomeIcon icon="microphone" size="lg" /> + </button> + </Tooltip> + )} + <Tooltip key="link" title={<div className="dash-tooltip">Find document to link to selected text</div>}> + <button className="antimodeMenu-button link" onPointerDown={this.toggleLinkPopup}> + <FontAwesomeIcon style={{ position: 'absolute', transform: 'scale(1.5)' }} icon={'search'} size="lg" /> + <FontAwesomeIcon style={{ position: 'absolute', transform: 'scale(0.5)', transformOrigin: 'top left', top: 12, left: 12 }} icon={'link'} size="lg" /> + </button> + </Tooltip> + <LinkPopup key="popup" showPopup={this._showLinkPopup} linkCreateAnchor={this.onMakeAnchor} />, + {AnchorMenu.Instance.StartCropDrag === unimplementedFunction ? null : ( + <Tooltip key="crop" title={<div className="dash-tooltip">Click/Drag to create cropped image</div>}> + <button className="antimodeMenu-button annotate" onPointerDown={this.cropDown} style={{ cursor: 'grab' }}> + <FontAwesomeIcon icon="image" size="lg" /> + </button> + </Tooltip> + )} + </> + ) : ( + <> + <Tooltip key="trash" title={<div className="dash-tooltip">Remove Link Anchor</div>}> + <button className="antimodeMenu-button" onPointerDown={this.Delete}> + <FontAwesomeIcon icon="trash-alt" size="lg" /> + </button> + </Tooltip> + <Tooltip key="Pin" title={<div className="dash-tooltip">Pin to Presentation</div>}> + <button className="antimodeMenu-button" onPointerDown={this.PinToPres}> + <FontAwesomeIcon icon="map-pin" size="lg" /> + </button> + </Tooltip> + <Tooltip key="trail" title={<div className="dash-tooltip">Show Linked Trail</div>}> + <button className="antimodeMenu-button" onPointerDown={this.ShowTargetTrail}> + <FontAwesomeIcon icon="taxi" size="lg" /> + </button> + </Tooltip> + <Tooltip key="toggle" title={<div className="dash-tooltip">make target visibility toggle on click</div>}> + <button className="antimodeMenu-button" style={{ color: this.IsTargetToggler() ? 'black' : 'white', backgroundColor: this.IsTargetToggler() ? 'white' : 'black' }} onPointerDown={this.MakeTargetToggle}> + <FontAwesomeIcon icon="thumbtack" size="lg" /> + </button> + </Tooltip> + </> + ); return this.getElement(buttons); } diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index 7069ff399..3b101a0c6 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -4,12 +4,13 @@ import { observer } from 'mobx-react'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; -import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; +import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types'; import { LinkFollower } from '../../util/LinkFollower'; import { undoBatch } from '../../util/UndoManager'; import { FieldViewProps } from '../nodes/FieldView'; import { AnchorMenu } from './AnchorMenu'; import './Annotation.scss'; +import { OpenWhere } from '../nodes/DocumentView'; interface IAnnotationProps extends FieldViewProps { anno: Doc; @@ -55,9 +56,17 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> { pinToPres = () => this.props.pinToPres(this.annoTextRegion, {}); @undoBatch - makePushpin = () => (this.annoTextRegion.followLinkToggle = !this.annoTextRegion.followLinkToggle); + makeTargretToggle = () => (this.annoTextRegion.followLinkToggle = !this.annoTextRegion.followLinkToggle); - isPushpin = () => BoolCast(this.annoTextRegion.followLinkToggle); + isTargetToggler = () => BoolCast(this.annoTextRegion.followLinkToggle); + @undoBatch + showTargetTrail = (anchor: Doc) => { + const trail = DocCast(anchor.presTrail); + if (trail) { + Doc.ActivePresentation = trail; + this.props.addDocTab(trail, OpenWhere.replaceRight); + } + }; @action onPointerDown = (e: React.PointerEvent) => { @@ -65,10 +74,10 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> { AnchorMenu.Instance.Status = 'annotation'; AnchorMenu.Instance.Delete = this.deleteAnnotation.bind(this); AnchorMenu.Instance.Pinned = false; - AnchorMenu.Instance.AddTag = this.addTag.bind(this); AnchorMenu.Instance.PinToPres = this.pinToPres; - AnchorMenu.Instance.MakePushpin = this.makePushpin; - AnchorMenu.Instance.IsPushpin = this.isPushpin; + AnchorMenu.Instance.MakeTargetToggle = this.makeTargretToggle; + AnchorMenu.Instance.IsTargetToggler = this.isTargetToggler; + AnchorMenu.Instance.ShowTargetTrail = () => this.showTargetTrail(this.annoTextRegion); AnchorMenu.Instance.jumpTo(e.clientX, e.clientY, true); e.stopPropagation(); } else if (e.button === 0) { @@ -77,12 +86,6 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> { } }; - addTag = (key: string, value: string): boolean => { - const valNum = parseInt(value); - this.annoTextRegion[key] = isNaN(valNum) ? value : valNum; - return true; - }; - render() { const brushed = this.annoTextRegion && Doc.isBrushedHighlightedDegree(this.annoTextRegion); return ( diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index f95d5ac2e..b0b7816b8 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -135,7 +135,7 @@ export class PDFViewer extends React.Component<IViewerProps> { copy = (e: ClipboardEvent) => { if (this.props.isContentActive() && e.clipboardData) { e.clipboardData.setData('text/plain', this._selectionText); - const anchor = this._getAnchor(); + const anchor = this._getAnchor(undefined, false); if (anchor) { anchor.textCopied = true; e.clipboardData.setData('dash/pdfAnchor', anchor[Id]); @@ -317,7 +317,7 @@ export class PDFViewer extends React.Component<IViewerProps> { this._ignoreScroll = false; if (this._scrollTimer) clearTimeout(this._scrollTimer); // wait until a scrolling pause, then create an anchor to audio this._scrollTimer = setTimeout(() => { - DocUtils.MakeLinkToActiveAudio(() => this.props.DocumentView?.().ComponentView?.getAnchor!()!, false); + DocUtils.MakeLinkToActiveAudio(() => this.props.DocumentView?.().ComponentView?.getAnchor!(true)!, false); this._scrollTimer = undefined; }, 200); } |
