diff options
Diffstat (limited to 'src/client/views/pdf')
| -rw-r--r-- | src/client/views/pdf/PDFMenu.scss | 19 | ||||
| -rw-r--r-- | src/client/views/pdf/PDFMenu.tsx | 68 | ||||
| -rw-r--r-- | src/client/views/pdf/PDFViewer.scss | 4 | ||||
| -rw-r--r-- | src/client/views/pdf/PDFViewer.tsx | 43 |
4 files changed, 97 insertions, 37 deletions
diff --git a/src/client/views/pdf/PDFMenu.scss b/src/client/views/pdf/PDFMenu.scss index 3c08ba80d..fa43a99b2 100644 --- a/src/client/views/pdf/PDFMenu.scss +++ b/src/client/views/pdf/PDFMenu.scss @@ -3,4 +3,23 @@ width: 200px; padding: 5px; grid-template-columns: 90px 20px 90px; +} + +.color-wrapper { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + + button.color-button { + width: 20px; + height: 20px; + border-radius: 15px !important; + margin: 3px; + border: 2px solid transparent !important; + padding: 3px; + + &.active { + border: 2px solid white; + } + } }
\ No newline at end of file diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index 6dcf5cce6..00c56d73e 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -1,22 +1,43 @@ import React = require("react"); import "./PDFMenu.scss"; -import { observable, action, } from "mobx"; +import { observable, action, computed, } from "mobx"; import { observer } from "mobx-react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { unimplementedFunction, returnFalse } from "../../../Utils"; +import { unimplementedFunction, returnFalse, Utils } from "../../../Utils"; import AntimodeMenu from "../AntimodeMenu"; import { Doc, Opt } from "../../../fields/Doc"; +import { ColorState } from "react-color"; +import { ButtonDropdown } from "../nodes/formattedText/RichTextMenu"; + @observer export default class PDFMenu extends AntimodeMenu { static Instance: PDFMenu; private _commentCont = React.createRef<HTMLButtonElement>(); + private _palette = [ + "rgba(208, 2, 27, 0.8)", + "rgba(238, 0, 0, 0.8)", + "rgba(245, 166, 35, 0.8)", + "rgba(248, 231, 28, 0.8)", + "rgba(245, 230, 95, 0.616)", + "rgba(139, 87, 42, 0.8)", + "rgba(126, 211, 33, 0.8)", + "rgba(65, 117, 5, 0.8)", + "rgba(144, 19, 254, 0.8)", + "rgba(238, 169, 184, 0.8)", + "rgba(224, 187, 228, 0.8)", + "rgba(225, 223, 211, 0.8)", + "rgba(255, 255, 255, 0.8)", + "rgba(155, 155, 155, 0.8)", + "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 public _colorBtn = false; @observable public Highlighting: boolean = false; @observable public Status: "pdf" | "annotation" | "" = ""; @@ -70,11 +91,47 @@ export default class PDFMenu extends AntimodeMenu { @action highlightClicked = (e: React.MouseEvent) => { - if (!this.Highlight("rgba(245, 230, 95, 0.616)") && this.Pinned) { // yellowish highlight color for a marker type highlight + if (!this.Highlight(this.highlightColor) && this.Pinned) { this.Highlighting = !this.Highlighting; } } + @computed get highlighter() { + const button = + <button className="antimodeMenu-button color-preview-button" title="" key="highilghter-button" onPointerDown={this.highlightClicked}> + <FontAwesomeIcon icon="highlighter" size="lg" style={{ transition: "transform 0.1s", transform: this.Highlighting ? "" : "rotate(-45deg)" }} /> + <div className="color-preview" style={{ backgroundColor: this.highlightColor }}></div> + </button>; + + const dropdownContent = + <div className="dropdown"> + <p>Change highlighter color:</p> + <div className="color-wrapper"> + {this._palette.map(color => { + if (color) { + return this.highlightColor === color ? + <button className="color-button active" key={`active ${color}`} style={{ backgroundColor: color }} onPointerDown={e => this.changeHighlightColor(color, e)}></button> : + <button className="color-button" key={`inactive ${color}`} style={{ backgroundColor: color }} onPointerDown={e => this.changeHighlightColor(color, e)}></button>; + } + })} + </div> + </div>; + return ( + <ButtonDropdown key={"highlighter"} button={button} dropdownContent={dropdownContent} /> + ); + } + + @action + changeHighlightColor = (color: string, e: React.PointerEvent) => { + const col: ColorState = { + hex: color, hsl: { a: 0, h: 0, s: 0, l: 0, source: "" }, hsv: { a: 0, h: 0, s: 0, v: 0, source: "" }, + rgb: { a: 0, r: 0, b: 0, g: 0, source: "" }, oldHue: 0, source: "", + }; + e.preventDefault(); + e.stopPropagation(); + this.highlightColor = Utils.colorString(col); + } + deleteClicked = (e: React.PointerEvent) => { this.Delete(); } @@ -101,12 +158,11 @@ export default class PDFMenu extends AntimodeMenu { render() { const buttons = this.Status === "pdf" ? [ - <button key="1" className="antimodeMenu-button" title="Click to Highlight" onClick={this.highlightClicked} style={this.Highlighting ? { backgroundColor: "#121212" } : {}}> - <FontAwesomeIcon icon="highlighter" size="lg" style={{ transition: "transform 0.1s", transform: this.Highlighting ? "" : "rotate(-45deg)" }} /></button>, + this.highlighter, <button key="2" className="antimodeMenu-button" title="Drag to Annotate" ref={this._commentCont} onPointerDown={this.pointerDown}> <FontAwesomeIcon icon="comment-alt" size="lg" /></button>, <button key="4" className="antimodeMenu-button" title="Pin Menu" onClick={this.togglePin} style={this.Pinned ? { backgroundColor: "#121212" } : {}}> - <FontAwesomeIcon icon="thumbtack" size="lg" style={{ transition: "transform 0.1s", transform: this.Pinned ? "rotate(45deg)" : "" }} /> </button> + <FontAwesomeIcon icon="thumbtack" size="lg" style={{ transition: "transform 0.1s", transform: this.Pinned ? "rotate(45deg)" : "" }} /></button>, ] : [ <button key="5" className="antimodeMenu-button" title="Delete Anchor" onPointerDown={this.deleteClicked}> <FontAwesomeIcon icon="trash-alt" size="lg" /></button>, diff --git a/src/client/views/pdf/PDFViewer.scss b/src/client/views/pdf/PDFViewer.scss index cfe0b3d4b..86c73bfee 100644 --- a/src/client/views/pdf/PDFViewer.scss +++ b/src/client/views/pdf/PDFViewer.scss @@ -12,14 +12,14 @@ // transform-origin: top left; // } .textLayer { - + opacity: unset; mix-blend-mode: multiply;// bcz: makes text fuzzy! span { padding-right: 5px; padding-bottom: 4px; } } - .textLayer ::selection { background: yellow; } // should match the backgroundColor in createAnnotation() + .textLayer ::selection { background: #ACCEF7; } // should match the backgroundColor in createAnnotation() .textLayer .highlight { background-color: yellow; } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 8185dd67f..98f64edec 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -115,8 +115,8 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu private _downX: number = 0; private _downY: number = 0; private _coverPath: any; + private _lastSearch = false; private _viewerIsSetup = false; - private _lastSearch: string = ""; @computed get allAnnotations() { return DocListCast(this.dataDoc[this.props.fieldKey + "-annotations"]). @@ -150,27 +150,11 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu runInAction(() => this._showWaiting = this._showCover = true); this.props.startupLive && this.setupPdfJsViewer(); this._mainCont.current && (this._mainCont.current.scrollTop = this.layoutDoc._scrollTop || 0); - this._searchReactionDisposer = reaction(() => this.Document.searchMatch, search => { - if (search) { - this.search(Doc.SearchQuery(), false); - this._lastSearch = Doc.SearchQuery(); - } - else { - setTimeout(() => this._lastSearch === "mxytzlaf" && this.search("mxytzlaf", true), 200); // bcz: how do we clear search highlights? - this._lastSearch && (this._lastSearch = "mxytzlaf"); - } - }, { fireImmediately: true }); - - this._searchReactionDisposer2 = reaction(() => this.Document.searchMatch2, search => { - if (search) { - this.search(Doc.SearchQuery(), true); - this._lastSearch = Doc.SearchQuery(); - } - else { - setTimeout(() => this._lastSearch === "mxytzlaf" && this.search("mxytzlaf", true), 200); // bcz: how do we clear search highlights? - this._lastSearch && (this._lastSearch = "mxytzlaf"); - } - }, { fireImmediately: true }); + this._searchReactionDisposer = reaction(() => this.Document.searchMatch, + m => { + if (m) (this._lastSearch = true) && this.search(Doc.SearchQuery(), true); + else !(this._lastSearch = false) && setTimeout(() => !this._lastSearch && this.search("", false, true), 200); + }, { fireImmediately: true }); this._selectionReactionDisposer = reaction(() => this.props.isSelected(), selected => { @@ -305,7 +289,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu let minY = Number.MAX_VALUE; if ((this._savedAnnotations.values()[0][0] as any).marqueeing) { const anno = this._savedAnnotations.values()[0][0]; - const annoDoc = Docs.Create.FreeformDocument([], { backgroundColor: color, _LODdisable: true, title: "Annotation on " + this.Document.title }); + const annoDoc = Docs.Create.FreeformDocument([], { backgroundColor: color, title: "Annotation on " + this.Document.title }); if (anno.style.left) annoDoc.x = parseInt(anno.style.left); if (anno.style.top) annoDoc.y = parseInt(anno.style.top); if (anno.style.height) annoDoc._height = parseInt(anno.style.height); @@ -399,7 +383,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu div.style.top = (parseInt(div.style.top)/*+ this.getScrollFromPage(page)*/).toString(); } this._annotationLayer.current.append(div); - div.style.backgroundColor = "yellow"; + div.style.backgroundColor = "#ACCEF7"; div.style.opacity = "0.5"; const savedPage = this._savedAnnotations.getValue(page); if (savedPage) { @@ -413,11 +397,12 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu } @action - search = (searchString: string, fwd: boolean) => { - if (!searchString) { + search = (searchString: string, fwd: boolean, clear: boolean = false) => { + if (clear) { + this._pdfViewer.findController.executeCommand('reset', {}); + } else if (!searchString) { fwd ? this.nextAnnotation() : this.prevAnnotation(); - } - else if (this._pdfViewer.pageViewsReady) { + } else if (this._pdfViewer.pageViewsReady) { this._pdfViewer.findController.executeCommand('findagain', { caseSensitive: false, findPrevious: !fwd, @@ -686,7 +671,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu panelWidth = () => (this.Document.scrollHeight || this.Document._nativeHeight || 0); panelHeight = () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : (this.Document._nativeWidth || 0); @computed get overlayLayer() { - return <div className={`pdfViewer-overlay${Doc.GetSelectedTool() !== InkTool.None || SnappingManager.GetIsDragging() ? "-inking" : ""}`} id="overlay" + return <div className={`pdfViewerDash-overlay${Doc.GetSelectedTool() !== InkTool.None || SnappingManager.GetIsDragging() ? "-inking" : ""}`} id="overlay" style={{ transform: `scale(${this._zoomed})` }}> <CollectionFreeFormView {...this.props} LibraryPath={this.props.ContainingCollectionView?.props.LibraryPath ?? emptyPath} |
